我在业余时间开发了一款自己的独立产品:升讯威在线客服与营销系统。陆陆续续开发了几年,从一开始的偶有用户尝试,到如今线上环境和私有化部署均有了越来越多的稳定用户。

而我收到的用户需求也越来越多,产品化的需求,个性化的需求都有。这段时间收到一个海外 APP 的对接需求,需要我将客服系统的消息以队列的形式转发到对方的业务服务器上。

对方有两个核心需求:

  • 访客上线的时候,要通知对方的业务系统,业务系统根据访客的身份信息,推送个性化的欢迎词。
  • 访客完成下单的时候,要能推送一个下单成功的通知,并且包含订单信息和链接。

根据这两个需求,那就需要实现由客服系统到业务系统的消息队列推送,以及通过 Open Api 开放接口,以队列的形式接收对方业务系统的消息。


什么是消息队列,以及使用消息队列的好处这些基础知识,这里就不再赘述,本文重点讲一讲如何用 python 实现一个消息队列。

要用 Python 实现一个消息队列,你可以使用内置的 queue 模块来创建一个简单的队列,或者使用第三方库如 RabbitMQRedis 或者 Kafka 来实现更复杂的分布式消息队列。

如何通过 python 实现消息队列

1. 使用 Python 内置的 queue.Queue(适用于单机应用)

queue.Queue 提供了线程安全的队列操作,适合在多线程应用中使用。

import queue
import threading
import time # 创建一个先进先出(FIFO)队列
msg_queue = queue.Queue() # 生产者线程
def producer():
for i in range(5):
time.sleep(1) # 模拟一些处理
msg = f"消息{i}"
msg_queue.put(msg) # 将消息放入队列
print(f"生产者放入:{msg}") # 消费者线程
def consumer():
while True:
msg = msg_queue.get() # 从队列获取消息
if msg is None: # 终止条件
break
print(f"消费者处理:{msg}")
msg_queue.task_done() # 标记任务已完成 # 创建生产者和消费者线程
producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer) # 启动线程
producer_thread.start()
consumer_thread.start() # 等待生产者线程完成
producer_thread.join() # 向消费者线程发送终止信号
msg_queue.put(None) # 等待消费者线程完成
consumer_thread.join()

2. 使用 Redis(适用于分布式应用)

Redis 是一个高效的内存数据存储,可以用作分布式消息队列。你可以使用 redis-py 库与 Redis 进行交互。

pip install redis
import redis
import time # 创建 Redis 连接
r = redis.StrictRedis(host='localhost', port=6379, db=0) # 生产者:将消息放入队列
def producer():
for i in range(5):
time.sleep(1) # 模拟一些处理
msg = f"消息{i}"
r.lpush('msg_queue', msg) # 将消息推送到队列
print(f"生产者放入:{msg}") # 消费者:从队列中获取消息
def consumer():
while True:
msg = r.brpop('msg_queue')[1].decode('utf-8') # 从队列中获取消息
print(f"消费者处理:{msg}") # 启动生产者和消费者
producer()
consumer()

3. 使用 RabbitMQ(适用于更复杂的消息传递)

RabbitMQ 是一个强大的消息代理系统,支持多种消息队列模式。如果需要高度可靠和高性能的消息队列,可以使用 pika 库连接 RabbitMQ。

pip install pika
import pika

# 连接到 RabbitMQ
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel() # 声明一个队列
channel.queue_declare(queue='msg_queue') # 生产者:发送消息
def producer():
for i in range(5):
msg = f"消息{i}"
channel.basic_publish(exchange='',
routing_key='msg_queue',
body=msg)
print(f"生产者发送:{msg}") # 消费者:接收并处理消息
def consumer(ch, method, properties, body):
print(f"消费者处理:{body.decode('utf-8')}") # 启动消费者
channel.basic_consume(queue='msg_queue', on_message_callback=consumer, auto_ack=True) # 启动生产者和消费者
producer()
print('等待消息...')
channel.start_consuming()

选择合适的实现

  • 如果你是单机应用并且需要线程安全的队列,使用 queue.Queue
  • 如果你的应用是分布式的,使用 RedisRabbitMQ 更加合适,它们提供了高可用性、消息持久化和可靠的消息传递机制。

如何把 http 请求放在队列中执行

将 HTTP 请求放入队列并异步执行的场景通常用于处理高并发、后台任务、延迟任务等情况。你可以使用消息队列系统(如 queue.QueueRedisRabbitMQ)来将 HTTP 请求放入队列,消费队列中的任务并执行相应的 HTTP 请求。

这里我会展示几种不同的实现方式,供你参考。

1. 使用 queue.Queuerequests

你可以将 HTTP 请求封装为任务,并将其放入队列中,然后使用多个消费者线程异步处理队列中的请求。

import queue
import threading
import time
import requests # 创建一个队列
task_queue = queue.Queue() # HTTP 请求任务处理函数
def handle_request():
while True:
url = task_queue.get() # 从队列中获取任务
if url is None: # 终止条件
break
try:
response = requests.get(url)
print(f"请求 {url} 的响应状态: {response.status_code}")
except Exception as e:
print(f"请求 {url} 失败: {e}")
task_queue.task_done() # 标记任务完成 # 生产者:将 HTTP 请求放入队列
def producer():
urls = [
"https://jsonplaceholder.typicode.com/posts/1",
"https://jsonplaceholder.typicode.com/posts/2",
"https://jsonplaceholder.typicode.com/posts/3"
] for url in urls:
print(f"将 URL {url} 放入队列")
task_queue.put(url)
time.sleep(1) # 模拟任务产生的延迟 # 创建多个消费者线程
consumer_threads = []
for i in range(3):
t = threading.Thread(target=handle_request)
t.start()
consumer_threads.append(t) # 启动生产者线程
producer_thread = threading.Thread(target=producer)
producer_thread.start() # 等待生产者线程完成
producer_thread.join() # 向消费者线程发送终止信号
for _ in range(3):
task_queue.put(None) # 等待消费者线程完成
for t in consumer_threads:
t.join()

2. 使用 Redisrequests

Redis 可以作为一个分布式的消息队列,适用于分布式系统中将 HTTP 请求放入队列并异步执行。你可以使用 Redis 的列表数据结构(lpushbrpop)来实现。

import redis
import requests
import time # 创建 Redis 连接
r = redis.StrictRedis(host='localhost', port=6379, db=0) # 生产者:将 HTTP 请求放入队列
def producer():
urls = [
"https://jsonplaceholder.typicode.com/posts/1",
"https://jsonplaceholder.typicode.com/posts/2",
"https://jsonplaceholder.typicode.com/posts/3"
] for url in urls:
print(f"将 URL {url} 放入 Redis 队列")
r.lpush('task_queue', url)
time.sleep(1) # 模拟任务产生的延迟 # 消费者:从队列中获取请求并执行
def consumer():
while True:
url = r.brpop('task_queue')[1].decode('utf-8') # 从队列中获取任务
try:
response = requests.get(url)
print(f"请求 {url} 的响应状态: {response.status_code}")
except Exception as e:
print(f"请求 {url} 失败: {e}") # 启动生产者和消费者
producer_thread = threading.Thread(target=producer)
consumer_thread = threading.Thread(target=consumer) producer_thread.start()
consumer_thread.start() # 等待生产者线程完成
producer_thread.join() # 由于 Redis 队列会一直阻塞等待任务,可以根据需要添加退出逻辑

3. 使用 RabbitMQrequests

RabbitMQ 提供了强大的消息队列机制,适合用于大规模的消息传递。你可以创建一个任务队列,将 HTTP 请求放入队列中,并通过消费者处理队列中的请求。

import pika
import requests
import time # 连接到 RabbitMQ
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel() # 声明队列
channel.queue_declare(queue='http_requests') # 生产者:将 HTTP 请求放入队列
def producer():
urls = [
"https://jsonplaceholder.typicode.com/posts/1",
"https://jsonplaceholder.typicode.com/posts/2",
"https://jsonplaceholder.typicode.com/posts/3"
] for url in urls:
print(f"将 URL {url} 放入 RabbitMQ 队列")
channel.basic_publish(exchange='',
routing_key='http_requests',
body=url)
time.sleep(1) # 模拟任务产生的延迟 # 消费者:处理 HTTP 请求
def consumer(ch, method, properties, body):
url = body.decode('utf-8')
try:
response = requests.get(url)
print(f"请求 {url} 的响应状态: {response.status_code}")
except Exception as e:
print(f"请求 {url} 失败: {e}") # 启动消费者
channel.basic_consume(queue='http_requests', on_message_callback=consumer, auto_ack=True) # 启动生产者
producer_thread = threading.Thread(target=producer)
producer_thread.start() # 启动消费者并等待消息
print('等待消费者处理 HTTP 请求...')
producer_thread.join()
channel.start_consuming()

4. 使用 Celery 异步任务队列

Celery 是一个强大的异步任务队列,适用于分布式任务执行。通过 Celery,你可以把 HTTP 请求封装为任务,放入队列中进行异步执行。

首先,你需要安装 Celeryrequests

pip install celery requests

然后在 celery.py 中配置 Celery:

from celery import Celery
import requests app = Celery('http_requests', broker='redis://localhost:6379/0') @app.task
def fetch_url(url):
try:
response = requests.get(url)
print(f"请求 {url} 的响应状态: {response.status_code}")
except Exception as e:
print(f"请求 {url} 失败: {e}")

然后在主程序中提交任务:

from celery import Celery
from celery.py import fetch_url # 添加任务到队列
fetch_url.apply_async(args=["https://jsonplaceholder.typicode.com/posts/1"])
fetch_url.apply_async(args=["https://jsonplaceholder.typicode.com/posts/2"])
fetch_url.apply_async(args=["https://jsonplaceholder.typicode.com/posts/3"])

启动 Celery Worker:

celery -A celery worker --loglevel=info

总结

  • queue.Queue:适用于单机和多线程环境,可以通过队列异步执行 HTTP 请求。
  • Redis:适用于分布式环境,将 HTTP 请求放入 Redis 队列,多个消费者异步执行。
  • RabbitMQ:适合高并发任务和消息传递的分布式环境,使用队列来管理 HTTP 请求。
  • Celery:适用于大规模异步任务队列的场景,可以使用 Redis 或其他消息中间件作为代理。

简介下这个 .net 开发的小系统

https://kf.shengxunwei.com/

升讯威在线客服与营销系统是一款客服软件,但更重要的是一款营销利器。

  • 可以追踪正在访问网站或使用 APP 的所有访客,收集他们的浏览情况,使客服能够主动出击,施展话术,促进成单。
  • 可嵌入网站、手机 APP、公众号、或者通过 URL 地址直接联系客服。
  • 支持访客信息互通,可传输访客标识、名称和其它任意信息到客服系统,与您的业务系统对接。
  • 可全天候 7 × 24 小时挂机运行,网络中断,拔掉网线,手机飞行模式,不掉线不丢消息,欢迎实测。

希望能够打造: 开放、开源、共享。努力打造 .net 社区的一款优秀开源产品。

钟意的话请给个赞支持一下吧,谢谢~

如何通过 Python 实现一个消息队列,为在线客服系统与海外运营的APP对接的更多相关文章

  1. .net core 和 WPF 开发升讯威在线客服系统:怎样实现拔网线也不丢消息的高可靠通信(附视频)

    本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...

  2. 百度AI开放平台 UNIT平台开发在线客服 借助百度的人工智能如何开发一个在线客服系统

    这段时间在研究一些人工智能的产品,对比了国内几家做人工智能在线客服的,有些接口是要收费的,有些是免费的,但是做了很多限制,比如每天调用的接口次数限制是100次.后来就找到了百度的AI,大家也知道,目前 ...

  3. (原创)用.NET Core实现一个在线客服系统(上篇)

    前言 没有视频的介绍显得尤为空白仓促.所以,如果你不赶时间,看看视频先 → → 戳我看视频 ← ←  在线演示访客端:http://role.fuyue.xyz/visitor/index客服端:ht ...

  4. Python操作rabbitmq消息队列持久化

    消息队列持久化 Python操作rabbit消息队列的持久化,如下: # 创建一个名为balance的队列,对queue进行durable持久化设为True(持久化第一步)channel.queue_ ...

  5. openresty 学习笔记番外篇:python访问RabbitMQ消息队列

    openresty 学习笔记番外篇:python访问RabbitMQ消息队列 python使用pika扩展库操作RabbitMQ的流程梳理. 客户端连接到消息队列服务器,打开一个channel. 客户 ...

  6. Python 番外 消息队列设计精要

    消息队列已经逐渐成为企业IT系统内部通信的核心手段.它具有低耦合.可靠投递.广播.流量控制.最终一致性等一系列功能,成为异步RPC的主要手段之一.当今市面上有很多主流的消息中间件,如老牌的Active ...

  7. skynet源代码学习 - 从全局队列中弹出/压入一个消息队列过程

    学习云风的skynet源代码,简单记录下. void skynet_globalmq_push(struct message_queue * queue) { struct global_queue ...

  8. 什么鬼,面试官竟然让我用Redis实现一个消息队列!!?

    GitHub 9.4k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 9.4k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 9.4k Star 的 ...

  9. 用过消息队列?Kafka?能否手写一个消息队列?懵

    是否有同样的经历?面试官问你做过啥项目,我一顿胡侃,项目利用到了消息队列,kafka,rocketMQ等等. 好的,那请开始你的表演,面试官递过一支笔:给我手写一个消息队列!!WHAT? 为了大家遇到 ...

  10. 进阶高阶IoT架构-教你如何简单实现一个消息队列

    前言 消息队列是软件系统领域用来实现系统间通信最广泛的中间件.基于消息队列的方式是指由应用中的某个系统负责发送消息,由关心这条消息的相关系统负责接收消息,并在收到消息后进行各自系统内的业务处理.消息可 ...

随机推荐

  1. S2P主数据助力医药企业建立数据化管理平台

    随着国家信息化进程的推进,医药软件行业市场规模正在不断扩大,其应用领域也在逐步拓宽,企业面临着多样化的销售渠道和模式选择.然而,要想在这样的多变市场中占据优势地位,单纯依靠经验决策已经不足以应对挑战. ...

  2. Qt Creator 5.0 发布

    我们很高兴地宣布 Qt Creator 5.0 的发布! 正如4.15 发布博文中所宣布的,我们将切换到语义版本控制方案,因此这是 Qt Creator 很长一段时间以来的第一次主要版本更新!不过不要 ...

  3. Qt编写的项目作品22-自定义委托全家桶

    一.功能特点 可设置多种委托类型,例如复选框/文本框/下拉框/日期框/微调框/进度条等. 可设置是否密文显示,一般用于文本框. 可设置是否允许编辑,一般用于下拉框. 可设置是否禁用,一般用来禁用某列. ...

  4. 2024-12-28:求出出现两次数字的 XOR 值。用go语言,给定一个数组 nums,其中的数字出现的频率要么是一次,要么是两次。 请找出所有出现两次的数字,并计算它们的按位 XOR 值。 如果没

    2024-12-28:求出出现两次数字的 XOR 值.用go语言,给定一个数组 nums,其中的数字出现的频率要么是一次,要么是两次. 请找出所有出现两次的数字,并计算它们的按位 XOR 值. 如果没 ...

  5. Windows7系统启用ipv6的详细步骤(图文)

    IPV6是IETF设计的用于替代现行版本IP协议(IPv4)的下一代IP协议.一般情况下,win7系统默认是关闭IPV6服务的,之前教程也有分享过win7禁用ipv6协议的方法.那么如果要启用ipv6 ...

  6. vmstorage如何将原始指标转换为有组织的历史

    vmstorage如何将原始指标转换为有组织的历史 参考自:vmstorage-how-it-handles-data-ingestion vmstorage是VictoriaMetrics中负责处理 ...

  7. 揭秘百度IM消息中台的全量用户消息推送技术改造实践

    本文内容由百度技术团队分享,原题"基于公共信箱的全量消息实现",为了帮助理解,有较多修订.内容重组和重新排版. 1.引言 百度的IM消息中台为百度APP以及厂内百度系产品提供即时通 ...

  8. 使用Matlab进行图像分类

    Classify images Instructions are in the task pane to the left. Complete and submit each task one at ...

  9. 从BIOS+MBR迁移到UEFI+GPT 并修复Ubuntu Grub2 UEFI引导

    之前在虚拟机里使用了默认配置安装了Ubuntu16.04,由于需要扩充磁盘空间不得不将磁盘从MBR分区表转换到GPT分区表. 简单介绍一下思路:首先通过Windows下的DiskGenius软件备份U ...

  10. WxPython跨平台开发框架之使用PyInstaller 进行打包处理

    使用PyInstaller 打包Python项目是一个常见的需求,它可以将Python程序及其所有依赖项打包成一个独立的可执行文件或者安装文件,方便在没有安装Python环境的机器上运行.本随笔介绍W ...