一、前言
- 不知不觉来到新公司已经快半年,经历了智能客服项目从刚开线时什么都不确定,到现在系统基本稳定并且扛过了大促时的高峰流量,这其中经历了很多艰辛,但是也的确收获了很多。特别是刚开始从原有阿里云客服流量全切我们系统时,很多问题都爆发了出来,由于是我负责核心通信模块的开发,自然也是由我去跟踪线上问题并解决。也是跳过了很多坑,在这里总结一下吧
二、原有的通信架构
- 在我没来之前,其实项目已经启动了一段时间了,但是只是在开发相应的基础模块,所以通信这块只是实现了简单的首发消息,采用了Netty框架,通信协议采用的websocket
- 技术实现:
- websocket+Netty+mq
- 交互步骤:
- 首先前端页面通过http请求携带用户token请求服务端
- 服务端验证token,验证成功后将用户信息和channel缓存在本地,并将请求升级为websocket协议,此时建立连接
- 当服务端接收到用户发送的消息时,直接将消息丢到MQ进行群发
- 每个Netty节点同时作为一个MQ消费者,消费该消息,根据消息体中指定的消息目的地寻找本地是否有对应的channel,如果没有丢弃消息,如果有的话进行发送
- 简易架构图
- 缺点:
- 效率很低,不适合高并发的场景下
- 无法确保消息的可达性,出现丢消息的情况
三、通信架构改进
- 由于要迎接后续的分段切流量,现在的通讯方式肯定不能满足需求,需要进行改进。当时也是咨询了架构组,架构组给出的方案就是做Netty节点间的消息投递
- 方案简述
- 每当用户发起HTTP连接并成功升级为websocket后,后台会在redis中存储用户的路由信息
- 用户连接到Netty节点A,并发送相应消息
- Netty节点A收到用户发送的消息,并进行暂存后返回ACK,此时消息发送成功
- Netty节点A根据消息体中消息接收方信息查询路由,发现消息需要发送到Netty节点B
- 将消息发送到NettyB节点,NettyB节点接收到消息后进行暂存并返回ACK,Netty节点A接收到ACK后删除暂存的信息
- Netty节点B根据消息体中接收方信息查询是否存在channel,存在则继续投递消息到用户B
- 用户B接收到消息后,返回ACK。Netty节点B删除调用暂存消息
- 此时消息投递成功
- 简易架构图
四、总结
- 这边总结只是大概简述了下通信模块的一个演进过程,其中的消息重推等机制并未详解。一方面原因的确是忙,为了实现每周一篇Blog的flag也是不容易。另一方面现在也没有好好整理这一块,也是希望自己能够坚持写下去,能够慢慢提高自己的文字水平
- 最后还是自勉一下吧:保持学习