socket长连接在手游场景下的技术实践

本文由37手游黄子键分享,有排版和内容优化等。

1、引言

本文介绍了37手游基于B站goim框架自研长连接系统的实践。系统采用分层设计,支持多协议和发布/订阅机制,用于直播弹幕、实时推送等场景,实现了高性能与业务适配。

2、长连接对于大部分公司的意义

实时的响应总是让人兴奋的,就如你在微信里看到对方正在输入,如你在王者峡谷里一呼百应,如你们在直播弹幕里不约而同的 666,它们的背后都离不开长连接技术的加持。

每个互联网公司里几乎都有一套长连接系统,它们被应用在消息提醒、即时通讯、推送、直播弹幕、游戏、共享定位、股票行情等等场景。而当公司发展到一定规模,业务场景变得更复杂后,更有可能是多个业务都需要同时使用长连接系统。

3、长连接是什么?

**长连接,在百科上的定义:**指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。

**严格上来说:**长连接是一种概念,它指的是在网络发送,接收双方保持一个持续连接的状态,双方都可以发送或接收消息(全双工)。

当然,长连接系统听起来好像高深莫测,但实际不可能说完全脱离于我们实际公司的业务去出发设计,这就引出来我们今天的主题------ 长连接技术在37手游内是如何设计以及实践的?

4、技术痛点

**从服务端而言:**缺乏在SDK内实时推送通知用户的能力,如防沉迷的弹窗通过http定时轮询来实现,给服务造成很大的压力

**从客户端而言:**也缺乏低成本告知服务端自身在线的能力,如维持用户在线状态靠客户端定时上报心跳到防沉迷服务实现。

5、搭建背景

**业务背景:**手游的SDK需要提供内嵌直播弹幕的功能,供玩家在看直播的时候进行沟通发言,业界一般会用到长连接来进行实时的推送,以降低服务的轮训和请求。

**从业务上而言:**直播弹幕需求由于初始量级很少,不用通过长连接的形式也能实现具体业务逻辑;但出于平台的拓展和能力考虑,长连接的能力是必须具备的。

长连接系统的这次搭建,本质是通过SDK内嵌直播弹幕为切入点,从0到1,为平台提供了完整的一套实时推送触达用户的能力。

**从以上角度出发:**我们便着手想要设计一个高可用且高性能的长连接系统提供给我们使用。

6、方案选型

从实际上而言,我们考虑三个方向。

**1)云服务:

市面上可购买的服务如环信等,大多数都以即时聊天通讯为主,长连接往往只是附带产品,过于偏向于社交业务,在花钱的同时也很难适应到自身游戏业务。

**2)开源框架:

b站的goim框架、NettyChat框架、MobileIMSDK框架等,好处是免费且能快速接入,但业务还是不相适应,且语言栈和技术栈不一定相契合。

**3)自研:

开发成本高,且容易踩坑。**:**基础组件完善,统一框架好进行监控和问题查询。且能充分契合自身业务进行拓展,并将数据源掌控在自己手中。

**4)结论:

出于扩展性的考虑,肯定是自研的方式更加合适,但完全自研相应的成本和不确定性会非常高,因此最终的选型方案为借鉴b站的goim框架设计和部分代码,并做了符合自身技术栈和业务架构的改善。

可认为是基于开源框架的自研方案的形式完成了长连接这个系统的落地。

7、goim技术概况

7.1 goim是什么?为什么借鉴它?

goim是b站开源研发的一个支持集群的im及实时推送服务。业务上为直播间的弹幕发送场景。

主要考虑到:

  • *1)*技术栈契合:语言栈为Golang ,消息队列为kafka,缓存设计为redis;
  • *2)*高性能:有压测报告,性能设计有保障;
  • *3)*多协议支持:websocket、tcp。

7.2 goim的模块?

如上图所示:

  • *1)*comet:用于跟端上保连,在内存中存储订阅信息;
  • *2)*logic:用于处理鉴权,在线房间等业务逻辑;
  • *3)*business:业务服务;
  • *4)*balancer:负载均衡模块;
  • *5)*discovery:服务发现模块;
  • *6)*job:kafka用于削峰。redis用于缓存房间信息;
  • *7)*logic和comet的通讯:采用rpc,优化性能。

从上面的goim的设计而言,我们可以总结出长连接的设计原则。

长连接架构的设计总是大同小异的,通用的有这几点:

  • *1)*业务层次分明:分接入层,逻辑层,存储层,服务发现层;通过这几层,实现业务解耦
  • *2)*协议通用:传输的数据协议必须在所有服务内进行通讯,并支持扩展
  • *3)*上行和下行收敛:上行和下行都会有一个对应的网关来进行收敛消息的收敛
  • *4)*消息削峰:通过队列来将发送信息削峰。并使接入层和逻辑层解藕

8、手游长连接系统的设计实践

根据以上的通用设计原则,我们不难得出,需要针对goim的架构如何做适配才能实际满足我们的业务需求,下面我们将会一一介绍。

8.1 架构改动

从架构而言,我们改动的点不多:

  • *1)*cient获取连接节点:手游内无统一的服务发现模块,但有外层LB,因此通过LB来实现comet节点负载均衡
  • *2)*推送消息:同上,消费者获取节点时需要到logic服务中查询,而不是discovery
  • *3)*服务通讯协议:由于手游内架构通讯协议的统一,接入层和逻辑层的通讯由RPC转为http

8.2 逻辑改动

***1)*鉴权机制:**客户端第一次连接上comet的时候,会发送鉴权上行。comet会解析客户端传输的数据,若包体协议或对应的签名错误,comet会将会直接主动断连

***2)*心跳机制:**comet会有心跳计时器,若客户端无定时上报心跳,则认为该连接已经超时,直接断开。这种业务的心跳主要是为了防止僵尸连接的存在。

***3)*回包机制:**客户端每发送一次上行操作,comet都会有对应的消息回包给端上。端上可根据回包,来知道自己鉴权,心跳,或者订阅,退订的操作是否成功,从而决定是否进行重试。

**4)发布/订阅机制:

我们在观看goim的源码时,发现goim适用于直播,群体推送以房间为维度,带有强业务属性,因此我们针对该部分抽象出发布/订阅机制。将房间抽象为topic,修改进房/出房动作为 订阅/退订。

将所有的通知抽象为业务事件,客户端想要接受到哪个事件过来的消息时,可发送对应的订阅上行。单个连接订阅的事件不做限制,对某个用户或某个事件范围内的用户推送消息时,comet会根据事件去取到推送的用户,只有用户订阅了才会收到消息。

**5)内存设计:

  • a. bucket维护消息通道和事件的信息;
  • b. 一个session对应一个用户连接;
  • c. 根据sessionid做一致性哈希来选择落到那个bucket上;
  • d. bucket有两个map,一个是session map,一个是topic map;
  • e. 所有bucket都会开启一个chan做监听,广播的时候,会通知到所有bucket,所有bucket再取出某个事件的所有连接进行下发。

8.3 总体交互

8.4 总体特点

因此,我们可以总结出来,我们手游长连接系统的总体特点:

  • *1)*纯golang实现;
  • *2)*多协议支持:websocket和tcp;
  • *3)*可拓扑结构:主要模块均无状态,可横向扩展;
  • *4)*消息支持单推/群推,消息协议业务可自定义;
  • *5)*发布/订阅机制,事件可业务自定义。

9、性能评估

在说性能之前,我们先抛出一个疑问:协程数过多实际占用的是什么?连接数过多是否影响CPU?

**从实际上来说:**长连接的性能瓶颈一般卡在接入层,因此以接入层为评估维度,通过全链路压测得出来结果。

如下:

  • *1)*压测参数:3000连接+ 3000 qps的实时推送;
  • *2)*推送内容:{msg:test} ;
  • *3)*推送类型:群推;
  • *4)*推送持续时长:5分钟 ;
  • *5)*资源使用:1核2G的容器;
  • *6)*CPU的使用:达到100%。

目前采用的长连接系统,通过压测结果发现,本身的连接数的维持和实时推送实际影响到是机器两个维度的性能,推送量影响到的是CPU,连接数影响到的是内存。分别提高两个参数对相应的内存,CPU的影响并不大。

10、实际应用情况

直播弹幕:

悬浮球实时红点:

从实际上来说,接入的业务虽小,但基础能力已经具备。

11、本文小结

长连接系统从根本上来说,对应的设计都是大同小异的,我们应该更加关注的是对于自身业务的适配以及实现。

12、参考资料

1\] [以网游服务端的网络接入层设计为例,理解实时通信的技术挑战](http://www.52im.net/thread-1915-1-1.html "以网游服务端的网络接入层设计为例,理解实时通信的技术挑战") \[2\] [知乎千万级并发的高性能长连接网关技术实践](http://www.52im.net/thread-2737-1-1.html "知乎千万级并发的高性能长连接网关技术实践") \[3\] [手淘亿级移动端接入层网关的技术演进之路](http://www.52im.net/thread-3110-1-1.html "手淘亿级移动端接入层网关的技术演进之路") \[4\] [喜马拉雅自研亿级API网关技术实践](http://www.52im.net/thread-3564-1-1.html "喜马拉雅自研亿级API网关技术实践") \[5\] [石墨文档单机50万WebSocket长连接架构实践](http://www.52im.net/thread-3757-1-1.html "石墨文档单机50万WebSocket长连接架构实践") \[6\] [小米小爱单机120万长连接接入层的架构演进](http://www.52im.net/thread-3860-1-1.html "小米小爱单机120万长连接接入层的架构演进") \[7\] [B站基于微服务的API网关从0到1的演进之路](http://www.52im.net/thread-3941-1-1.html "B站基于微服务的API网关从0到1的演进之路") \[8\] [去哪儿网酒店高性能业务网关技术实践](http://www.52im.net/thread-4618-1-1.html "去哪儿网酒店高性能业务网关技术实践") \[9\] [百度基于Go的千万级统一长连接服务架构实践](http://www.52im.net/thread-4623-1-1.html "百度基于Go的千万级统一长连接服务架构实践") \[10\] [揭秘腾讯公网TGW网关系统的技术架构演进](http://www.52im.net/thread-4641-1-1.html "揭秘腾讯公网TGW网关系统的技术架构演进") \[11\] [基于Netty的携程高性能网关异步改造实践](http://www.52im.net/thread-4854-1-1.html "基于Netty的携程高性能网关异步改造实践") \[12\] [手把手教你写基于TCP的Socket长连接](http://www.52im.net/thread-4623-1-1.html "手把手教你写基于TCP的Socket长连接") \[13\] [正确理解IM长连接、心跳及重连机制,并动手实现](http://www.52im.net/thread-2799-1-1.html "正确理解IM长连接、心跳及重连机制,并动手实现") \[14\] [万字长文:手把手教你实现一套高效的IM长连接自适应心跳保活机制](http://www.52im.net/thread-3908-1-1.html "万字长文:手把手教你实现一套高效的IM长连接自适应心跳保活机制") \[15\] [用JWT技术解决IM系统Socket长连接的身份认证痛点](http://www.52im.net/thread-2106-1-1.html "用JWT技术解决IM系统Socket长连接的身份认证痛点") \[16\] [TCP/IP详解](http://www.52im.net/topic-tcpipvol1.html "TCP/IP详解") - [第11章·UDP:用户数据报协议](http://docs.52im.net/extend/docs/book/tcpip/vol1/11/ "第11章·UDP:用户数据报协议") \[17\] [TCP/IP详解](http://www.52im.net/topic-tcpipvol1.html "TCP/IP详解") - [第17章·TCP:传输控制协议](http://docs.52im.net/extend/docs/book/tcpip/vol1/17/ "第17章·TCP:传输控制协议") \[18\] [WebSocket从入门到精通,半小时就够!](http://www.52im.net/thread-3134-1-1.html "WebSocket从入门到精通,半小时就够!") \[19\] [快速理解TCP协议一篇就够](http://www.52im.net/thread-1107-1-1.html "快速理解TCP协议一篇就够") \[20\] [快速理解TCP和UDP的差异](http://www.52im.net/thread-1160-1-1.html "快速理解TCP和UDP的差异") \[21\] [一泡尿的时间,快速搞懂TCP和UDP的区别](http://www.52im.net/thread-3793-1-1.html "一泡尿的时间,快速搞懂TCP和UDP的区别") \[22\] [到底什么是Socket?一文即懂!](http://www.52im.net/thread-3821-1-1.html "到底什么是Socket?一文即懂!") \[23\] [我们在读写Socket时,究竟在读写什么?](http://www.52im.net/thread-1732-1-1.html "我们在读写Socket时,究竟在读写什么?") \[24\] [假如你来设计TCP协议,会怎么做?](http://www.52im.net/thread-3339-1-1.html "假如你来设计TCP协议,会怎么做?") \[25\] [深入操作系统,一文搞懂Socket到底是什么](http://www.52im.net/thread-4146-1-1.html "深入操作系统,一文搞懂Socket到底是什么") > **即时通讯技术学习:** > > - 移动端IM开发入门文章:《[新手入门一篇就够:从零开发移动端IM](http://www.52im.net/thread-464-1-1.html "新手入门一篇就够:从零开发移动端IM")》 > > - 开源IM框架源码:[https://github.com/JackJiang2011/MobileIMSDK](https://github.com/JackJiang2011/MobileIMSDK "https://github.com/JackJiang2011/MobileIMSDK")([备用地址点此](https://gitee.com/jackjiang/MobileIMSDK "备用地址点此")) (**本文同步发布于:** [http://www.52im.net/thread-4907-1-1.html](http://www.52im.net/thread-4907-1-1.html "http://www.52im.net/thread-4907-1-1.html"))

相关推荐
精益数智小屋1 小时前
设备维护方案核心功能拆解:一套好的设备维护方案如何解决设备突发故障
大数据·运维·网络·数据库·人工智能·面试·自动化
其实防守也摸鱼1 小时前
VS code怎么使用 Conda 安装预编译包
开发语言·网络·c++·vscode·安全·web安全·conda
Pushkin.1 小时前
LangGraph 多 Agent 架构与 Supervisor 模式
人工智能·架构
zhangfeng11331 小时前
IB = InfiniBand:一种超高速、低延迟的专用网络 和和一般我们在用的光纤网络的区别
网络
Wyc724091 小时前
信息安全与多媒体基础知识
网络·安全·web安全
Agent产品评测局1 小时前
设备运维自动化预警系统,从0到1落地实操方法:2026企业级架构与智能体选型全指南
运维·人工智能·ai·chatgpt·架构·自动化
摇滚侠1 小时前
Java 项目教程《尚庭公寓》标签管理、自定义 converter 14 - 18
java·elasticsearch·架构
轻刀快马1 小时前
穿透 MySQL 索引专栏 (五):【架构哲学】性能调优的终局之战:深分页灾难与千万级大表的索引设计原则
数据库·mysql·架构
源远流长jerry2 小时前
Linux 本机网络通信机制深度解析:Loopback 设备原理
linux·运维·服务器·网络·tcp/ip·nginx·负载均衡