Java面试经验个人总结(十四)——百万用户的即时消息系统

百万用户的即时消息系统

一、IO技术选型

1. 要求:满足大量连接数、支持全双工通信,并且性能需要保障。

2. IO模型:NIO多路复用模型。->netty框架

3. 架构图

Java面试经验个人总结(十四)——百万用户的即时消息系统_第1张图片

 

二、协议解析

服务器集群内部使用RPC协议,用户和服务器之间利用HTTP协议,使用API网关来适配不同的协议通信。

 

三、简单实现

1. 注册鉴权

在消息上下行之前先要登录鉴权,确保登录客户端的是用户本人。

通常来说都需要客户端通过HTTP请求传递一个唯一标识,后台鉴权通过之后会响应一个token,并将这个token和客户端的关系维护到Redis或者是数据库中。客户端将这个token也保存到本地,今后的每一次请求都得带上这个token(cookie)。一旦这个 token 过期,客户端需要再次请求获取 token。

鉴权通过之后客户端会直接通过TCP长连接到图中的push-server模块。这个模块就是真正处理消息的上、下行。

2. 保存通道关系

在连接接入后要维护当前客户端ID和通道的关系,维护到Map中。类似Springboot 整合长连接心跳机制。可以利用高性能NIO框架Netty。

(1)客户端每隔 N 秒检测是否需要发送心跳。

(2)服务端也每隔 N 秒检测是否需要发送心跳。

(3)服务端可以主动 push 消息到客户端。

(4)基于 SpringBoot 监控,可以查看实时连接以及各种应用信息。

3. 消息上行

利用JSON上传不同类型的消息,添加字段用于区分。

4. 消息解析与业务解耦

消息解析后要处理业务,业务包括数据库处理和其他接口调用。

5. 下行消息

(1)点对点

a. A 将消息发送给服务器。

b. 服务器收到消息之后,得知消息是要发送给 B,需要在内存中找到 B 的 Channel。

c. 通过 B 的 Channel 将 A 的消息转发下去。

(2)在线推送

遍历Map,挨个发送消息。

 

四、分布式实现

1. 连接数的决定因素:服务器配置,包括内存,网卡等硬件;应用自身配置;

2. 注册发现

推送服务器节点将自身服务注册到zookeeper中,注册登录模块会自动获取新的服务列表;

3. 有状态连接

在平台向客户端推送消息的时候,首先要知道这个客户端的通道保存在哪台节点上。

将路由关系存放在redis中,客户端接入推送服务器时要将UserID和服务节点的IP和端口号一并存进redis中。客户端下线时,将该关系删除。

4. 推送路由

(1)遍历一遍redis,获得所有活跃的推送服务器节点信息,通过该节点保存的channel信息,推送到客户端;

(2)首先我们需要将这批号码通过平台下的 Nginx 下发到一个推送路由中。为了提高效率甚至可以将这批号码再次分散到每个push-route中。拿到具体号码之后再根据号码的数量启动多线程的方式去之前的路由Redis中获取客户端所对应的push-server。再通过HTTP的方式调用push-server进行真正的消息下发(Netty也很好的支持HTTP协议)。

5. 消息流转(客户端消息持久化)

由于信息量巨大,推送服务器节点不能直接将消息持久化,否则MySQL无法负载巨量的写操作。可以直接将上行数据送往kafka。再由消费程序写入数据库

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Java面试经验个人总结(十四)——百万用户的即时消息系统)