Jack Jiang

我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
posts - 426, comments - 13, trackbacks - 0, articles - 0

2024年5月8日

本文由哔哩哔哩资深开发工程师黄山成分享,原题“千万长连消息系统”,本文进行了排版和内容优化等。

1、引言

在当今数字娱乐时代,弹幕已经成为直播平台上不可或缺的互动元素之一。

用户通过发送弹幕、送礼等,可以实时在直播画面上展现自己的想法、评论和互动内容,从而丰富了用户观看体验。在这个过程中,实时向终端推送互动信息,就需要用到长连接。

长连接,顾名思义,是应用存活期间和服务端一直保持的网络数据通道,能够支持全双工上下行数据传输。其和请求响应模式的短连接服务最大的差异,在于它可以提供服务端主动给用户实时推送数据的能力。

本文将介绍B站基于golang实现的千万级长连接实时消息系统的架构设计与实践,包括长连接服务的框架设计,以及针对稳定性与高吞吐做的相关优化。

 
 
 技术交流:

- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK备用地址点此

(本文已同步发布于:http://www.52im.net/thread-4647-1-1.html

2、关联文章

3、架构设计

3.1概述

长连接服务是多业务方共同使用一条长连接。

因为在设计时,需要考虑到不同业务方、不同业务场景对长连接服务的诉求,同时也要考虑长连接服务的边界,避免介入业务逻辑,影响后续长连接服务的迭代和发展。

长连接服务主要分为三个方面:

  • 1)长连接建立、维护、管理;
  • 2)下行数据推送;
  • 3)上行数据转发(目前只有心跳,还没实际业务场景需求)。

3.2整体架构

长连接服务整体构架如上图所示,整体服务包含以下几个部分。

1)控制层:建连的前置调用,主要做接入合法性校验、身份校验和路由管控。

主要职责:

  • 1)用户身份鉴权;
  • 2)加密组装数据,生成合法token;
  • 3)动态调度分配接入节点。

2)接入层:长连接核心服务,主要做卸载证书、协议对接和长连接维护。

主要职责:

  • 1)卸载证书和协议;
  • 2)负责和客户端建立并维护连接,管理连接id和roomid的映射关系;
  • 3)处理上下行消息。

3)逻辑层:简化接入层,主要做长连的业务功能。

主要职责:

  • 1)在线人数上报记录;
  • 2)记录连接ID各属性和各节点的映射关系。
  • 4)消息分发层:消息推送到接入层。

主要职责:

  • 1)消息封装、压缩和聚合推送给相应的边缘节点;

5)服务层:业务服务对接层,提供下行消息推送入口。

主要职责:

  • 1)管控业务推送权限;
  • 2)消息检测和重组装;
  • 3)消息按一定策略限流,保护自身系统。

3.3核心流程

长连接主要是3个核心流程:

  • 1)建立连接:由客户端发起,先通过控制层,获取该设备合法的token和接入点配置;
  • 2)维持连接:主要是客户端定时发起心跳,来保证长连接活跃;
  • 3)下行推送:下行推送由业务Server发起,经由服务层根据相关标识确定连接标识和接入节点,经过消息分发层,把推送到对应的接入层,写入到指定连接上,然后下发到客户端。

3.4功能列表

结合B站业务场景,下行数据推送,提供如下通用功能:

  • 1)用户级消息:指定推送给某些用户(比如给某个主播发送邀请pk消息);
  • 2)设备级消息:制定推送给某些设备(比如针对未登陆的设备,推送客户端日志上报指令);
  • 3)房间级消息:给某房间内的连接推送消息(比如给直播间的所有在线用户推送弹幕消息);
  • 4)分区消息:给某分区的房间推送消息(比如给某个分区下,所有开播的房间,推送某个营收活动);
  • 5)全区消息:给全平台用户推送消息(比如给全部在线用户推送活动通知)。

4、高吞吐技术设计

随着业务发展壮大,在线用户越来越多,长连系统的压力越来越大,尤其是热门赛事直播,比如s赛期间,全平台在线人数快达到千万,消息吞吐量有上亿,长连系统消息分发平均延迟耗时在1s左右,消息到达率达到99%,下面具体分析下长连做了哪些措施。

4.1网络协议

选择合适的网络协议对于长连接系统的性能至关重要:

  • 1)TCP协议:可以提供可靠的连接和数据传输,适用于对数据可靠性要求较高的场景;
  • 2)UDP协议:是一个不可靠的协议,但是传输效率高,适用于对数据可靠性要求不高的场景;
  • 3)WebSocket协议:也是实现双向通信而不增加太多的开销,更多的用于web端。

接入层拆分成协议模块和连接模块:

  • 1)协议模块:和具体的通讯层协议交互,封装不同通讯协议的接口和逻辑差异。
  • 2)连接模块:维护长连接业务连接状态,支持请求上行、下行等业务逻辑,维护连接各属性,以及和房间id的绑定关系。

针对以上第 1)点,协议模块同时给连接模块提供统一的数据接口,包括连接建立、数据读取、写入等。后续增加新协议,只要在协议模块做适配,不影响其他模块的长连业务逻辑。

优势在于:

  • 1)业务逻辑和通讯协议做了隔离,方便迭代增加通讯协议,简化兼容多通讯协议的实现难度;
  • 2)控制层可以根据客户端的实际情况,下发更优的通讯协议。

4.2负载均衡

采用负载均衡技术可以将请求分发到不同的服务器节点上处理,避免了单一节点的负载过高,提高了系统的扩展性和稳定性。

长连增加控制层,做负载均衡。控制层提供http短连接口,基于客户端和各边缘节点实际情况,根据就近原则,动态选择合适的接入节点。

接入层支持水平扩展,控制层可以实时增加、减少分配节点。在S赛期间,在线人数快到达千万时,平衡调度各接入节点,保障了各节点的CPU和内存都在稳定的范围内。

4.3消息队列

消息推送链路是:业务发送推送,经过服务层推到边缘节点,然后下发给客户端。

服务层实时分发到各边缘节点,如果是房间类型消息,需要推到多个边缘节点,服务层同时还要处理业务逻辑,很影响消息的吞吐量。

所以增加消息队列和消息分发层,消息分发层维护各边缘节点信息和推送消息,提高了系统的并发处理能力和稳定性,避免了因消息推送阻塞而导致的性能问题。

4.4消息聚合

当有热门赛事时,同时在线可能达到千万级别,一条弹幕消息就要扩散到千万个终端,假如在线的每个人每秒发一条,需要发送消息量就是1kw*1kw,消息量非常大,此时消息分发层和接入层,压力都会很大。

分析发现:这些消息都是同一个房间的,属于热点房间,比如s赛房间,观众数量是无法减少的,那只能在消息数上做文章。业务消息推送不能减少,又要减少扩散的消息数,就想到了消息聚合。

针对房间消息,按照一定的规则进行消息聚合,批量推送:

消息聚合上线后,消息分发层对接入层调用QPS下降60%左右,极大的降低了接入层和消息分发层的压力。

4.5压缩算法

消息聚合后,降低了消息的数量,但是增加了消息体的大小,影响了写入IO,需要减少消息体大小,就想到了消息压缩。

压缩算法,选了市面上比较常用的两个:zlib和brotli,进行比较。

抓取了线上业务推送的数据,选择最高等级的压缩等级,进过压缩验证:

由此可见,brotli相比zlib有很大的优势,最后选择了brotli压缩算法。

选择在消息分发层进行消息压缩,避免在各接入节点多次重复压缩,浪费性能。上线后提升吞吐量的同时,也降低的宽带使用成本。

5、服务保障技术设计

现在有些业务是强依赖长连推送消息,消息丢失,轻则影响用户体验,重则阻塞业务后续流程,进而影响业务流水。针对长连服务消息保障,做了如下工作。

5.1多活部署

多活部署,通过在不同地理位置部署相同的系统架构和服务,实现了系统在单一地域故障时的快速故障转移,从而提高了系统的稳定性和可用性。

长连服务部署,主要做了以下几点:

  • 1)长连接在国内华东、华南、华北地域均部署了接入点,支持三大运营商;华南和华中自建机房也部署了接入点;为支持海外用户,增加了新加坡机房独立接入点;
  • 2)针对业务场景不同,在云上节点和自建节点之间,实时切换,因为云上节点和自建机房的成本是不一样的,在保证服务质量的前提下,尽可能的控制成本。

目前线上运行过程中,偶尔会遇到单节点或机房的网络抖动,通过控制层,对有问题的节点,进行秒级摘流,大大减少了对业务的影响。

5.2高低消息通道

多业务消息接入长连接,但不同消息之间的重要性是不一样的,比如弹幕消息和邀请pk消息,丢失几条弹幕对用户体验不会影响很大,但如果邀请pk消息丢失,则会导致pk业务无法进行后续的流程。

针对不同等级的消息,采用了高低优消息通道。重要消息走高优通道,普通消息走低优通道。这样重要和普通消息进行了物理隔离,消息分发优先保证重要消息。

针对高优通道,做了双投递的保障,在接入层做幂等去重。首先重要消息是针对用户级别的,量不会很大,所以对接入层的压力不会增加很大。另外双投递的job是部署在多机房的,这也就降低单机房网络抖动造成的影响。

高低优通道上线后,遇到过内网出网抖动,当时内网部属的job节点推送消息异常,而云上高优job节点可正常推送,很好的保障了高优消息的到达,进而保障了高优业务不受影响。

5.3高达功能

高低优通道解决的是job到接入层的这一个环节,但消息推送联路涉及到多个环节,比如服务层到job、接入层到客户端。

针对整个链路,通过实现必达机制来确保终端的到达率,简称高达功能。

功能实现:

  • 1)每条消息引入msgID,客户端收到消息后进行幂等去重和ack回执;
  • 2)服务端针对msgid进行ack检测,针对未ack的,有效期内再次重试下发。

最终到达率 = (1-(1-r)^(n+1)),其中:r为广播单次到达率,n为最大重试次数。

例如:r = 97%、n=2,那么最终到达率可以达到(1-(1-0.97)^(2+1)) = 99.9973%

6、进出”房“消息的送达保证设计

有些业务场景,需要用到用户进出房消息,比如用户A进入直播间,页面会显示欢迎用户A进入房间,或者是加入在线榜单。

1)进房消息会存在丢失,需要有补偿机制。想到可以通过连接心跳来补偿进房消息,但心跳是持续不断的,连接在线期间,业务希望只收到一次进房消息,所以进房消息需要有幂等机制。

2)出房消息也会存在丢失,如果丢失了,业务无法从在线榜单剔除用户,此时也需要有补偿机制。此时就需要增加连接的状态机,通过心跳维护状态机,当心跳丢失时,认为连接断开,用户退房。

7、未来规划

统一长连接服务经历数次迭代后,目前基本功能已经趋于稳定,后续对长连接服务进行改善和优化。

主要集中在以下几个方向:

  • 1)数据化:进一步完善长连接全链路网络质量数据统计和高价值消息全链路追踪的能力;
  • 2)智能化:端上建联、接入点选择等能够根据实际环境进行自动化调整;
  • 3)性能优化:接入层的连接模块中,处理上下行消息的携程进行共享,减少接入层的携程数,进一步提升单机性能和连接数;
  • 4)功能扩展:新增离线消息功能等。

8、参考资料

[1] 手把手教你写基于TCP的Socket长连接

[2] 正确理解IM长连接、心跳及重连机制,并动手实现

[3] 万字长文:手把手教你实现一套高效的IM长连接自适应心跳保活机制

[4] 用JWT技术解决IM系统Socket长连接的身份认证痛点

[5] TCP/IP详解 - 第11章·UDP:用户数据报协议

[6] TCP/IP详解 - 第17章·TCP:传输控制协议

[7] WebSocket从入门到精通,半小时就够!

[8] 快速理解TCP协议一篇就够

[9] 快速理解TCP和UDP的差异

[10] 一泡尿的时间,快速搞懂TCP和UDP的区别

[11] 到底什么是Socket?一文即懂!

[12] 我们在读写Socket时,究竟在读写什么?

[13] 假如你来设计TCP协议,会怎么做?

[14] 深入操作系统,一文搞懂Socket到底是什么

[15] 通俗易懂,高性能服务器到底是如何实现的

[16] 12306抢票带来的启示:看我如何用Go实现百万QPS的秒杀系统(含源码)


(本文已同步发布于:http://www.52im.net/thread-4647-1-1.html

posted @ 2024-05-16 11:44 Jack Jiang 阅读(30) | 评论 (0)编辑 收藏

一、更新内容简介

本次更新为次要版本更新,进行了bug修复和优化升级(更新历史详见:码云 Release NotesGithub Release Notes)。

MobileIMSDK 可能是市面上唯一同时支持 UDP+TCP+WebSocket 三种协议的同类开源IM框架。轻量级、高度提炼,历经10年、久经考验。客户端支持iOSAndroidJavaH5微信小程序Uniapp,服务端基于Netty

二、MobileIMSDK简介

MobileIMSDK 是一套专为移动端开发的原创IM通信层框架:

  • 历经10年、久经考验;
  • 超轻量级、高度提炼,lib包50KB以内;
  • 精心封装,一套API同时支持UDP、TCP、WebSocket三种协议(可能是全网唯一开源的);
  • 客户端支持 iOSAndroid标准JavaH5小程序Uniapp
  • 服务端基于Netty,性能卓越、易于扩展;👈
  • 可与姊妹工程 MobileIMSDK-Web 无缝互通实现网页端聊天或推送等;👈
  • 可应用于跨设备、跨网络的聊天APP、企业OA、消息推送等各种场景。

MobileIMSDK工程始于2013年10月,历经10年,起初用作某产品的即时通讯底层实现,完全从零开发,技术自主可控!

您可能需要:查看关于MobileIMSDK的详细介绍

三、源码托管同步更新

OsChina.net

GitHub.com

四、MobileIMSDK设计目标

让开发者专注于应用逻辑的开发,底层复杂的即时通讯算法交由SDK开发人员,从而解偶即时通讯应用开发的复杂性。

五、MobileIMSDK框架组成

整套MobileIMSDK框架由以下7部分组成:

  1. Android客户端SDK:用于Android版即时通讯客户端,支持Android 4.0及以上,查看API文档
  2. iOS客户端SDK:用于开发iOS版即时通讯客户端,支持iOS 12.0及以上,查看API文档
  3. Java客户端SDK:用于开发跨平台的PC端即时通讯客户端,支持Java 16及以上,查看API文档
  4. H5客户端SDK查看精编注释版
  5. 微信小程序端SDK查看精编注释版
  6. Uniapp端SDK查看精编注释版
  7. 服务端SDK:用于开发即时通讯服务端,支持Java 1.7及以上版本,查看API文档

整套MobileIMSDK框架的架构组成:

 另外:MobileIMSDK可与姊妹工程 MobileIMSDK-Web 无缝互通,从而实现Web网页端聊天或推送等。

六、MobileIMSDK v6.5更新内容 

【重要说明】:

MobileIMSDK v6.5 为次要版本,进行了若干优化! 查看详情 (github

【新增重要特性】:

  • 1. [Android端] 新增了Demo中当APP处于后台时,收到消息时显示系统通知的功能。

【解决的Bug】:

  • 1. [服务端] 尝试解决极小几率下Android端会误把“自已”踢掉的问题。

【其它优化和提升】:

  • 1. [服务端] 升级了log4j2等基础库,解决基础库低版中带来的安全漏洞风险;
  • 2. [服务端] 服务端SDK和Demo工程已迁移至IDEA;
  • 3. [Java端] Java桌面端的TCP和UDP两种协议的SDK和Demo工程已迁移至IDEA;
  • 4. [Android端] 提升targetSdkVersion至34(即Android 14);
  • 5. [Android端] 解决了Demo中绑定前台服务在Android 14中崩溃等问题。
  • 6. [iOS端] 提升最低系统支持版本为iOS 12;
  • 7. [iOS端] 优化了JSON解析库中的一处过时API调用。

【最新版本源码地址】:

七、Demo运行演示

八、技术应用示例

8.1 示例1:基于MobileIMSDK的移动端IM RainbowChat更多运行截图):

 

8.2 示例2:基于MobileIMSDK-Web的Web端IM RainbowChat-Web更多运行截图):

 

posted @ 2024-05-09 11:34 Jack Jiang 阅读(25) | 评论 (0)编辑 收藏

即时通讯技术文集(第37期):IM代码入门实践(Part1) [共16篇]

为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第37 期。

[- 1 -] 一种Android端IM智能心跳算法的设计与实现探讨(含样例代码)

[链接] http://www.52im.net/thread-783-1-1.html

[摘要] 本文将与大家一起探讨一种更加简单易行和实用的心跳算法,不一定适合所有人,但希望能需要的同行带来一些启发。


[- 2 -] 详解Netty的安全性:原理介绍、代码演示(上篇)

[链接] http://www.52im.net/thread-426-1-1.html

[摘要] 作为一个高性能的NIO通信框架,基于Netty的行业应用非常广泛,不同的行业、不同的应用场景,面临的安全挑战也不同,下面我们根据Netty的典型应用场景,分析下Netty面临的安全挑战。


[- 3 -] 详解Netty的安全性:原理介绍、代码演示(下篇)

[链接] http://www.52im.net/thread-427-1-1.html

[摘要] 接上篇《详解Netty的安全性:原理介绍、代码演示(上篇)》。


[- 4 -] Java NIO基础视频教程、MINA视频教程、Netty快速入门视频 [有源码]

[链接] http://www.52im.net/thread-1244-1-1.html

[摘要] 本次分享的是自己收藏的Java nio、mima、netty的视频教程,现分享给各位,希望对大家有帮助。


[- -] 轻量级即时通讯框架MobileIMSDK的源码

[链接]http://git.oschina.net/jackjiang/MobileIMSDK

https://github.com/JackJiang2011/MobileIMSDK

[摘要] 如Github下载慢,请往:https://gitee.com/jackjiang/MobileIMSDK,代码完全同步,请放心下载 


[- 6 -] 开源IM工程“蘑菇街TeamTalk”2015年5月前未删减版完整代码 [附件下载]

[链接] http://www.52im.net/thread-777-1-1.html

[摘要] 本次分享的源码来自即时通讯群群友的个人分享,因可能涉及网易泡泡源码版权纠纷,请开发者保证仅用于个人学习和研究之用,切勿用于商业用途。


[- 7 -]  NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战 [附件下载]

[链接] http://www.52im.net/thread-388-1-1.html

[摘要] 本文中,服务端将分别用MINA2和Netty4进行实现,但在你实际的项目中服务端实现只需选其一就行了。


[- 8 -] NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战 [附件下载]

[链接] http://www.52im.net/thread-378-1-1.html

[摘要] 本文将演示一个iOS客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo。


[- 9 -] NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示 [附件下载]

[链接] http://www.52im.net/thread-373-1-2.html

[摘要] 本文将演示的是一个基于MINA2的UDP服务端和一个标准UDP客户端(Java实现)双向通信的完整例子。


[- 10 -] NIO框架入门(一):服务端基于Netty4的UDP双向通信Demo演示 [附件下载]

[链接] http://www.52im.net/thread-367-1-2.html

[摘要] 本文将演示的是一个基于Netty4的UDP服务端和一个标准UDP客户端(Java实现)双向通信的完整例子。


[- 11 -] 用于IM中图片压缩的Android工具类源码,效果可媲美微信 [附件下载]

[链接] http://www.52im.net/thread-701-1-2.html

[摘要] 本文要分享的工具类源码来自IM产品 RainbowChat,压缩效果可媲美微信,详情请参见源码。


[- 12 -] 高仿Android版手机QQ可拖拽未读数小气泡源码 [附件下载]

[链接] http://www.52im.net/thread-922-1-2.html

[摘要] 本文分享的源码高仿了手机QQ的这个效果,希望可以为有相同需求的IM开发者同行节省点撸码时间。


[- 13 -] 一个WebSocket实时聊天室Demo:基于node.js+socket.io [附件下载]

[链接] http://www.52im.net/thread-516-1-2.html

[摘要] 本文将基于HTML5规范中的WebSocket技术,使用Node.js和Socket.io(关于Socket.io介绍,请参见《Socket.IO介绍:支持WebSocket、用于WEB端的即时通讯的框架》)来实现一个可用于Web端的简易实时聊天室,源码可从文末附件中下载到。


[- 14 -] Android聊天界面源码:实现了聊天气泡、表情图标(可翻页) [附件下载]

[链接] http://www.52im.net/thread-409-1-2.html

[摘要] Android聊天界面源码:实现了聊天气泡、表情图标。


👉52im社区本周新文:《即时通讯安全篇(十四):网络端口的安全防护技术实践》,欢迎阅读!👈

我是Jack Jiang,我为自已带盐!https://github.com/JackJiang2011/MobileIMSDK/

posted @ 2024-05-08 12:24 Jack Jiang 阅读(25) | 评论 (0)编辑 收藏

Jack Jiang的 Mail: jb2011@163.com, 联系QQ: 413980957, 微信: hellojackjiang