目的
建立一套通用的分布式事件传递机制,满足以下业务场景:
1,将前端事件传递到后端,将后端事件传递到前端。如站内信、待办消息等
2,浏览器之间的事件传递,如即时通讯、编辑锁的抢锁场景
技术架构
前端每个浏览器最多只能建立一个websocket(同域),不管浏览器打开了多少个标签页
前端在需要用到websocket的时候才能建立websocket
前端每个浏览器生成一个clientId
建立websocket时需要传递clientId, userId, cookie
开发原则
1,Socket server 不负责具体业务逻辑,只按定好的规则来传递事件
2,逻辑层复杂具体业务逻辑
3,Socket server 可以独立部署,也可以附属在lowcode-design进程(如果使用Socket.io则需要独立监听端口)
事件传递流程
Socket server
Socket server监听以下websocket事件:
ws.back.**: 浏览器发给后端的事件,直接转发到Kafka集群的对应Topic
ws.front.broadcast:浏览器广播给其他浏览器的事件,直接封装,转发到Kafka集群的ws.front Topic,excludeClientId=当前clientId
ws.front.client: 浏览器定向发给指定浏览器的事件,直接封装,转发到Kafka集群的ws.front Topic,clientId=指定浏览器的clientId
Socket server订阅Kafka集群以下主题:
ws.front:后端给浏览器发的事件,解释数据JSON中的完整事件名,作如下处理:
1)ws.front.client:需要传递到指定浏览器的事件,数据JSON中必须包含clientId,如果clientId已连接到当前Socket server,则传递事件,否则忽略
2)ws.front.broadcast:需要广播到所有浏览器的事件,数据JSON中可以包含excludeClientId,广播的时候会跳过这个浏览器
1,浏览器A向后端Socket server A发送事件
WS事件名:ws.front.client
数据:
{
eventName: ws.front.client.lowcode.editLock,
fromClient: browserA,
toClient: browserB,
data: {...}
}
2,如果browserB注册在Socket server A,直接处理;否则下一步
3,Socket server A向Kafka集群发布事件
Kafka主题名:ws.front
数据:
{
eventName: ws.front.client.lowcode.editLock,
fromClient: browserA,
toClient: browserB,
data: {...}
}
4,所有Socket server订阅到Kafka的 ws.front 事件
5,如果browserB注册在当前Socket server,则向browserB发送websocket事件
WS事件名:ws.front.client
数据:
{
eventName: ws.front.client.lowcode.editLock,
fromClient: browserA,
toClient: browserB,
data: {...}
}
6,后端转让编辑权成功后,向Kafka集群发布事件
Kafka主题名:ws.front
数据:
{
eventName: ws.front.client.lowcode.editLock.response,
fromClient: SYSTEM,
toClient: browserA,
data: {...}
}
7,Socket server A订阅到Kafka的 ws.front 事件后,向browserA发送websocket事件
WS事件名:ws.front.client
数据:
{
eventName: ws.front.client.lowcode.editLock.response,
fromClient: SYSTEM,
toClient: browserA,
data: {...}
}
以编辑锁抢锁场景为例
总结
本文设计了一种基于websocket的事件传播机制,将后端事件传播给前端,将前端事件传播给后端。