# socket-framework **Repository Path**: IdeaHome_admin/socket-framework ## Basic Information - **Project Name**: socket-framework - **Description**: socket相关的工程代码 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 15 - **Forks**: 3 - **Created**: 2021-05-11 - **Last Updated**: 2023-05-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # socket-framework #### 介绍 socket相关的工程代码,分布式集群模式下的websocket通讯案例 #### 项目背景 和各位读者大致介绍下具体场景,线上的小程序中开放一些语音麦克风的房间,让用户进入房间之后可以互相通过语音聊天的方式进行互动。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0511/143813_2c639285_1777749.png "屏幕截图.png") 这里我分享一下相关的技术设计方案。 这款系统的核心点设计在于如何能让一个用户发出的语音通知到其他用户上边。语音数据在客户端同事的处理下最终变成了io数据流请求到了后端,后端只需要将这些数据流传达给各个不同的终端即可达到广播通知的效果。 #### 单机版架构 最初期上线的时候,为了赶速度,快速试错,所以简单地采用了单机版架构去设计。结合技术栈为 SpringBoot,WebSocket,MySQL技术。 线上一间语音房间的同时在线人数并不会特别多,大概在15-50人的区间段内,系统核心代码是通过SpringBoot内部的WebSocket技术去进行数据的主动推送。 #### 设计思路 整体的设计图比较简单,基本就是一台服务器存储WebSocket连接,如下图所示: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0511/143840_3bcdd8b1_1777749.png "屏幕截图.png") 用户进行WebSocket初始化连接的时候需要一个连接分配和存储的过程: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0511/143851_6aa4e412_1777749.png "屏幕截图.png") 早期的存储是存放在了服务器本地的一个Map集合中。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0511/143927_d0461da5_1777749.png "屏幕截图.png") 当WebSocket进行连接的时候就会往内存中写入一条数据信息,当链接断开的时候,就将内存中的数据移除。 然后进行语音广播的时候需要结合WebSocket内部的广播发送功能进行通知。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0511/143936_61ca7621_1777749.png "屏幕截图.png") 看似设计比较简单,但是在后期业务变得庞大的时候出现了瓶颈。 因为随着参加语音活动用户的增加,越来越多的WebSocketSession对象需要被存储到内存当中,这种有状态性的存储对于单机扩容不灵活。 #### 设计缺陷 1.假设原先的服务器扩容到了A,B两台机器,A用户在A机器上边建立了WebSocketSession,B用户在B机器上边建立的WebSocketSession连接。此时如果A想要和B进行对话发送,需要先查找到具体WebSocketSession存放在哪台机器上边。 2.当用户出现了网络异常,临时断开连接进行重连的时候,也可能会出现1所说的问题。 ### 集群架构 设计思路 一旦出现需要发送语音通知的时候,发送一条广播的mq消息,每个机器都接收到消息之后,触发自己的广播操作即可。 mq模块的处理代码核心设计模块: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0511/143947_38c4546f_1777749.png "屏幕截图.png") 整体设计结构如下图: ![输入图片说明](https://images.gitee.com/uploads/images/2021/0511/143958_76ffe612_1777749.png "屏幕截图.png") 于是按照这个结构进行了一版本的紧急开发迭代,原先的单台服务器扩展为了服务集群。 #### 业务拓展 后续产品经理提出一个需求,要求支持在同一间房内的两个用户之间发送悄悄话功能。 这就需要我们进行一个点对点之间传输通讯的功能了。因此需要在mq通知到每台机器的时候加一个本地Session遍历的逻辑,如果当前机器存有用户token对应的session变量,那么就单独争对那个session进行websocket的发送通知。 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0511/144010_ec0f62da_1777749.png "屏幕截图.png") #### 设计弊端 一旦某台机器出现了异常崩溃,那么就意味着这台机器上的所有语音连接可能会出现中断情况。 目前这一块的问题也在考虑解决,计划是将WebSocketSession存入到分布式缓存的redis中保证数据可靠存储,但是在后续尝试的时候发现WebSocketSession对象没有实现序列化接口,在存储到redis的时候会出现异常。目前这个问题还在寻找解决思路中,不知道各位读者朋友们有什么好的案。 #### 遇到的问题点 用户请求直接访问到了我们的内部服务器,如果在请求的中间加入一台nginx做负载均衡则需要在nginx中配置一些额外信息。