摘要: 我的开源项目过去一直托管在 Github 上。目前也同步上传到了国内的 Gitee 平台,同步维护。本文整理了所有开源项目的链接和简介,希望对你有用。 阅读全文
posted @ 2021-03-16 09:43 升讯威在线客服系统 阅读(5729) 评论(19) 推荐(53) 编辑
摘要: 本系统文章详细介绍使用 .net core 和 WPF 开发升讯威在线客服与营销系统的过程。我将从系统的功能设计、技术架构、开发细节以及各个功能,详细介绍开发实现的过程。在未来的系统开发和完善过程中,如果时间允许,我也会同步更新这一系列的文章进行介绍。 阅读全文
posted @ 2020-12-14 21:53 升讯威在线客服系统 阅读(4969) 评论(17) 推荐(33) 编辑

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

而我收到的用户需求也越来越多,产品化的需求,个性化的需求都有。这段时间收到一个海外 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 社区的一款优秀开源产品。

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

posted @ 2025-02-21 13:09 升讯威在线客服系统 阅读(277) 评论(0) 推荐(4) 编辑
摘要: 在 .NET 中实现 QPS 限流有很多方案,对于小流量的应用,内存限流和基于中间件的限流方式可能已经足够,而对于高并发的分布式系统,可能需要 Redis 或者更复杂的算法,如令牌桶或滑动窗口。 阅读全文
posted @ 2025-02-16 22:35 升讯威在线客服系统 阅读(323) 评论(0) 推荐(3) 编辑
摘要: 我在业余时间开发了一款自己的独立产品:升讯威在线客服与营销系统。陆陆续续开发了几年,从一开始的偶有用户尝试,到如今线上环境和私有化部署均有了越来越多的稳定用户,在这个过程中,我也积累了不少如何开发运营一款独立产品的经验。在这篇文章中,我主要讲 Docker 打包发布的过程和一些注意事项。 阅读全文
posted @ 2025-02-12 11:49 升讯威在线客服系统 阅读(465) 评论(2) 推荐(11) 编辑
摘要: 通过 Docker 环境变量,在启动容器时带入配置信息,自动写入配置文件中,完全免去了进入容器内部 vim 修改的步骤,真正实现在线客服系统1分钟上线。 阅读全文
posted @ 2025-02-05 18:54 升讯威在线客服系统 阅读(61) 评论(0) 推荐(1) 编辑
摘要: 我在业余时间开发了一款自己的独立产品:升讯威在线客服与营销系统。陆陆续续开发了几年,从一开始的偶有用户尝试,到如今线上环境和私有化部署均有了越来越多的稳定用户,在这个过程中,我也积累了不少如何开发运营一款独立产品的经验。我将在本文中介绍如何借助 AI 辅助产品 UI 设计。 阅读全文
posted @ 2025-02-02 12:41 升讯威在线客服系统 阅读(31) 评论(0) 推荐(0) 编辑
摘要: 如果你的产品是和我的在线客服系统一样,100% 允许用户私有化部署的,那你一定要使用 Docker 技术,让用户能够快速体验到你的系统,以及能够在生产环境中非常轻松的把你的产品用起来。 阅读全文
posted @ 2025-01-31 00:03 升讯威在线客服系统 阅读(430) 评论(0) 推荐(3) 编辑
摘要: 阿里云真贵啊。我在业余时间开发了一款自己的独立产品:升讯威在线客服与营销系统。陆陆续续开发了几年,从一开始的偶有用户尝试,到如今的 QPS 突破 240 次/秒,连接数突破 4000,日请求数接近 1000 万。在这篇文章中,我将简要介绍我在技术上做了哪些工作,我是如何做到的。 阅读全文
posted @ 2025-01-17 10:24 升讯威在线客服系统 阅读(1127) 评论(2) 推荐(14) 编辑
摘要: 详细介绍如何为 Web Api 类型的项目,添加美观实用,可交互的状态显示页面。 阅读全文
posted @ 2024-12-17 14:03 升讯威在线客服系统 阅读(1143) 评论(0) 推荐(11) 编辑
摘要: 我在业余时间开发的这个客服系统,有一个问题始终让我饱受困扰,360以及各种国产安全管家十分容易报威胁。即便ESET、卡巴斯基、Windows Defender、小红伞全部一切正常,但360、国产管家就是倔强的报威胁。而这些国产管家的用户基数又很大,非常让人恼火。难道真的必须交保护费吗? 阅读全文
posted @ 2024-12-02 10:16 升讯威在线客服系统 阅读(2874) 评论(26) 推荐(37) 编辑
摘要: 我看到很多产品开发者习惯于先去“找模板”,再就着模板向里面填充内容,这是不对的。首先自己的思路是否理清了,其次所谓的模板,其内容层次结构是否适合自己的产品?我看到一些产品网站虽然看起来还算漂亮,但是传递的内容十分有限。 阅读全文
posted @ 2024-11-28 13:27 升讯威在线客服系统 阅读(1330) 评论(6) 推荐(11) 编辑
点击右上角即可分享
微信分享提示