做企业微信 API 二次开发时,消息回调入口经常会接到各种业务事件。如果收到消息后,直接在回调方法里查询数据库、调用 AI、创建工单,业务一多,回调处理就容易变慢。
尤其是多个客户群同时产生消息时,一个耗时操作就可能影响后续请求。
一、回调入口不要处理太多业务
比较常见的写法是:收到消息后,先查客户信息,再查询订单,最后调用 AI 生成回复。
这种方式开发起来比较直接,但有个问题:所有操作都依赖回调请求完成。一旦数据库查询变慢,或者 AI 服务响应超时,整个处理过程都会被拖长。
更合适的方式是把接收消息和业务处理分开。
回调入口只负责校验必要字段、记录消息并提交任务;后续的客户查询、AI 分析和工单创建交给后台任务处理。
二、用 Python 简单拆分处理逻辑
下面用一个简化示例说明任务拆分思路:
python
def message_callback(data):
if not data:
return {"code": 400}
message_id = data.get("message_id")
if not message_id:
return {"code": 400}
# 实际项目中应先可靠保存消息,
# 并通过唯一键完成去重
save_message(data)
# 提交后台任务
enqueue_task(message_id)
return {"code": 200}
这里的 save_message() 和 enqueue_task() 是示意方法,需要根据实际项目实现。
需要特别注意:如果消息保存成功,但任务提交失败,就可能出现消息没有被处理的情况。因此,生产环境可以使用数据库任务表或 Outbox 模式,将消息记录与待处理任务放在同一个事务中,再由后台程序投递任务。
三、异步处理也要考虑失败情况
把业务放到后台,并不代表问题就解决了。还需要关注几个细节:
-
消息去重: 相同事件重复到达时,避免重复创建工单或重复回复。
-
任务重试: 临时网络错误可以重试,但要限制次数。
-
任务超时: AI 或外部服务长时间没有响应时,不能一直占用工作线程。
-
处理状态: 记录待处理、处理中、成功和失败状态,方便排查问题。
-
回复顺序: 同一个客户连续发送多条消息时,需要根据业务要求决定是否按顺序处理。
如果涉及企业微信外部群自动回复,还应区分消息接收成功和回复发送成功,不能只根据回调入口返回正常就认定整个业务已经完成。
四、什么时候需要引入消息队列?
如果消息量不大,可以先用数据库任务表实现异步处理;如果任务数量持续增长,或者需要多个工作节点并行消费,再考虑 Redis、RabbitMQ 等消息队列。
选择哪种方式,主要看消息量、任务可靠性要求和部署复杂度,不必一开始就把架构做得很重。
总结:回调入口越轻,越容易保持稳定。 先做好消息持久化、任务拆分和失败处理,再根据实际负载决定是否引入更复杂的队列机制。