Jack Jiang

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

置顶随笔

相关链接:

一、理论知识准备

您需要对鸿蒙Next和ArkTS开发有所了解:

您需要对WebSocket技术有所了解:

HTML5的标准WebSocket协议文档、API手册:

鸿蒙Next的WebSocket文档和手册:

小提示:鸿蒙Next中的WebSocket API跟标准HTML5中的WebSocket接口及用法略有不同,但主要API都能一一对应,相差不大。

二、开发工具准备

1)DevEco-Studio:

JackJiang 使用的版本号如上图所示,为了方便直接引用工程,建议你也使用此版或较新版本

2)一站式下载地址:鸿蒙官网下载地址 点此进入。(需要注册成为开发者才能下载哟!

3)DevEco-Studio效果预览:

三、SDK 文件用途说明

3.1文件概览

纯ArkTS实现,无任何第3方库依赖,更无本地原生代码混编:

MobileIMSDK-鸿蒙端SDK本身只是ets文件源码的集合,自带的Demo代码只是为了方便随时测试SDK代码,目的主要是用于演示SDK的API调用,Demo代码不属于SDK框架的一部分。

大致的目录说明:

3.2详细说明

SDK 各模块/文件作用说明:

四、主要API接口和用途说明

* 主要API文档地址是:http://docs.52im.net/extend/docs/api/mobileimsdk/harmony/

1)ClientCoreSDK.getInstance().loginHasInit:

  • 用途:是否已经完成过首次登陆。
  • 说明 :用户一旦从自已的应用中完成登陆IM服务器后,本方法就会一直返回true(直到退出登陆IM)。
  • 返回值:{boolean},true表示已完成首次成功登陆(即已经成功登陆过IM服务端了,后面掉线时不影响此标识),否则表示尚未连接IM服务器。

2)ClientCoreSDK.getInstance().connectedToServer:

  • 用途:是否在线。
  • 说明 :表示网络连接是否正常。
  • 返回值:{boolean},true表示网络连接正常,否则表示已掉线,本字段只在this._logined=true时有意义(如果都没有登陆到IM服务器,怎么存在在线或掉线的概念呢)。

3)ClientCoreSDK.getInstance().currentLoginInfo:

4)ClientCoreSDK.getInstance().init(eventHub: common.EventHub): void:

  • 用途:初始化SDK核心。
  • 说明:不同于MobileIMSDK的iOS和Java客户端,本方法需要由开发者调用,以确保MobileIMSDK核心已被初始化完成。
  • 本方法被调用后, #isInitialed() 将返回true,否则返回false。

5)ClientCoreSDK.getInstance().release(): void:

  • 用途:保释放MobileIMSDK框架资源统一方法。
  • 说明 :本方法建议在退出登陆(或退出APP时)时调用。调用时将尝试关闭所有MobileIMSDK框架的后台守护线程并同设置核心框架init=false、loginHasInit=false、connectedToServer=false。

6)LocalDataSender.getInstance().sendLogin(loginInfo: PLoginInfo | undefined): number:

  • 用途:发送登陆(连接)信息给服务端。
  • 说明 :不同于其它IM框架,本框架的登录和连接高度封装在了一个sendLogin方法中,无需单独再去connect服务器,大大简化了SDK的使用。loginInfo登陆信息各字段定义见:http://docs.52im.net/extend/docs/api/mobileimsdk/harmony/#1697

7)LocalDataSender.getInstance().sendLoginout(): number:

  • 用途:发送注销登陆信息。
  • 说明:此方法的调用将被本库理解为退出库的使用,本方法将会额外调用资源释放方法 ClientCoreSDK#release() ,以保证资源释放。本方法调用后,除非再次进行登陆过程,否则核心库将处于初始未初始化状态。

8)LocalDataSender.getInstance().sendCommonDataPlain(dataContentWidthStr: string, to_user_id: string, QoS: boolean = true, fingerPrint: string = '', typeu: number = -1): number:

  • 用途:向某人发送一条消息。
  • 参数dataContentWidthStr:要发送的数据内容(字符串方式组织)。
  • 参数to_user_id:要发送到的目标用户id。
  • 参数QoS :true表示需QoS机制支持,否则不需要。
  • 参数fingerPrint:QoS机制中要用到的指纹码(即消息包唯一id),可设为null,生成方法见 Protocal.genFingerPrint()。
  • 参数typeu:应用层专用字段——用于应用层存放聊天、推送等场景下的消息类型。注意:此值为-1时表示未定义。MobileIMSDK框架中,本字段为保留字段,不参与框架的核心算法,专留作应用层自行定义和使用。
  • 返回值:0表示数据发出成功,否则返回的是错误码,see ErrorCode。

9)LocalDataSender.getInstance().sendCommonData(p: Protocal): number:

  • 用途:通用数据协议包的发送根方法。
  • 参数p:{Protocal} 要发送的消息协议包对象,Protocal详情请见“/module/mb_constants.js”下的createCommonData函数说明。
  • 返回值:0表示数据发出成功,否则返回的是错误码,see ErrorCode。

10)SocketEvent.SOCKET_EVENT_ON_RECIEVE_MESSAGE事件通知:

11)SocketEvent.SOCKET_EVENT_ON_LOGIN_RESPONSE事件通知:

  • 用途:本地用户的登陆结果回调事件通知(此事件发生时表示客户端已登陆/连接或重连完成)。
  • 推荐用法:开发者可在此事件中处理登录连接和掉线重连响应反馈。
  • 参数1: {PLoginInfoResponse}:API文档详见:http://docs.52im.net/extend/docs/api/mobileimsdk/harmony/#1434

12)SocketEvent.SOCKET_EVENT_ON_LINK_CLOSE事件通知:

  • 用途:与服务端的通信断开的回调事件通知(此事件发生时表示客户端已掉线)。
  • 该消息只有在客户端连接服务器成功之后网络异常中断之时触发。导致与与服务端的通信断开的原因有(但不限于):无线网络信号不稳定、WiFi与2G/3G/4G/5G等同开情况下的网络切换、手机系统的省电策略等。
  • 推荐用法 :开发者可在此通知中处理掉线时的界面状态更新等,比如设置将界面上的“在线”文字更新成“离线”。

13)SocketEvent.SOCKET_EVENT_PING事件通知:

  • 用途:本地发出心跳包后的回调通知(本回调并非MobileIMSDK-鸿蒙端核心逻辑,开发者可以不需要实现!)。
  • 推荐用法 :开发者可在此回调中处理底层网络的活动情况。

14)SocketEvent.SOCKET_EVENT_PONG事件通知:

  • 用途:收到服务端的心跳包反馈的回调通知(本回调并非MobileIMSDK-鸿蒙端核心逻辑,开发者可以不需要实现!)。
  • 推荐用法 :开发者可在此回调中处理底层网络的活动情况。

15)SocketEvent.SOCKET_EVENT_KICKOUT事件通知:

16)SocketEvent.SOCKET_EVENT_ON_ERROR_RESPONSE事件通知:

17)SocketEvent.SOCKET_EVENT_RECONNECT_ATTEMPT事件通知:

  • 用途:“自动重连尝试中”事件(本回调并非MobileIMSDK-鸿蒙端核心逻辑,开发者可以不需要实现!)。
  • 参数 code :{numeric}:0:已停止,1:持续运行中,2:单次脉搏

18)SocketEvent.SOCKET_EVENT_MESSAGE_LOST事件通知:

  • 用途:消息未送达的回调事件通知。
  • 发生场景:比如用户刚发完消息但网络已经断掉了的情况下,表现形式如:就像手机qq或微信一样消息气泡边上会出现红色图标以示没有发送成功)。
  • 建议用途:应用层可通过回调中的指纹特征码找到原消息并可以UI上将其标记为“发送失败”以便即时告之用户。
  • 参数1:{Array}:由框架的QoS算法判定出来的未送达消息列表。

19)SocketEvent.SOCKET_EVENT_MESSAGE_BE_RECIEVED事件通知:

  • 用途:消息已被对方收到的回调事件通知。
  • 说明 :目前,判定消息被对方收到是有两种可能:1) 对方确实是在线并且实时收到了;2) 对方不在线或者服务端转发过程中出错了,由服务端进行离线存储成功后的反馈(此种情况严格来讲不能算是“已被收到”,但对于应用层来说,离线存储了的消息原则上就是已送达了的消息:因为用户下次登陆时肯定能通过HTTP协议取到)。
  • 建议用途:应用层可通过回调中的指纹特征码找到原消息并可以UI上将其标记为“发送成功”以便即时告之用户。
  • 参数1:{String}:已被收到的消息的指纹特征码(唯一ID),应用层可据此ID找到原先已发的消息并可在UI是将其标记为”已送达“或”已读“以便提升用户体验。

五、如何引入SDK库文件

5.1方法一:源码形式

第一步:先将整个sdk源码module复制到您的鸿蒙工程中:

第二步:配置您的工程,确保正确引用了MobileIMSDK鸿蒙SDK的源码module:

 

5.2方法二:.har包形式

第一步:先将MobileIMSDK鸿蒙端SDK的.har包放入您的鸿蒙Next主module中(比如新建的libs目录下):

第二步:配置您的工程,确保正确引用了MobileIMSDK鸿蒙SDK的.har包:

六、如何调用SDK代码

6.1第一步:设置ws/wss连接URL

设置您自已部署的MobileIMSDK服务端IP或域名的示例详见Demo中的 IMClientManager.ets 文件):

提示:MobileIMSDK的服务端Demo部署指南请见 http://www.52im.net/thread-63-1-1.html

6.2第二步:初始化SDK

调用ClientCoreSDK中的init()方法进行初始化(示例详见Demo中的I MClientManager.ets 文件):

6.3第三步:注册框架事件

注册MobileIMSDK框架级的事件监听(示例详见Demo中的 IMClientManager.ets 文件):

6.4第四步:调用登录方法(框架内部会自动启动connect全过程)

调用登录方法(示例详见Demo中的 LoginPage.ets 文件):

提示:不同于其它IM框架,本框架的登录和连接高度封装在了一个sendLogin方法中,无需单独再去connect服务器,大大简化了SDK的使用。

七、Demo运行效果和功能说明

八、Demo运行方法

8.1重要说明

特别说明:MobileIMSDK的鸿蒙端工程(包括Demo代码),不依赖任何第3方库,也不存在任何Native代码混编,完全使用ArkTS、ArkUI官方标准API实现,所以你在拿到MobileIMSDK的鸿蒙端工程后直接开箱即可运行,切莫搞复杂、不要私自加戏!

8.2配置要连接的MobileIMSDK服务器IP

注意:下图中登陆连接的IP地址请设置为您自已的MobileIMSDK服务器地址哦。

友情提示: MobileIMSDK的服务端该怎么部署就不是本手册要讨论的内容了,你可以参见《即时通讯框架MobileIMSDK的Demo使用帮助:Server端》。

▲ 配置要连接的服务器IP(以上代码详见IMClientManager.ets文件

8.3启动模拟器

注意:如果没有新建模拟器可以自已新建一个。另外也可以使用支持鸿蒙Next的真机,打开“开发者模式”并插入USB线即可使用。

 

▲ 点击绿色箭头,立即启动模拟器!

8.4一键运行

如下图所示,点击绿色“运行”按钮后,将自动在模拟器或真机里显示自带的Demo界面了:

8.5运行效果

1)Demo的登陆界面运行截图:

2)Demo的主界面运行截图:

3)Demo运行的同时,可以查看详细的log输出(方便调试):

九、引用资料

[1] 鸿蒙Next官方开发资料

[2] MobileIMSDK开源框架的API文档

[3] MobileIMSDK开源IM框架源码Github地址点此

[4] MobileIMSDK-鸿蒙Next端发布公告

[5] MobileIMSDK-鸿蒙Next端详细介绍

[6] MobileIMSDK-鸿蒙Next端开发手册* 精编PDF版

[7] MobileIMSDK的Server端Demo使用帮助

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

     摘要: 本文的上篇我们讨论了在线实时消息的投递,如果接收方用户B不在线,系统是如何保证离线消息的可达性的呢?这就是本文要讨论的问题。  阅读全文

posted @ 2016-11-18 14:39 Jack Jiang 阅读(3125) | 评论 (0)编辑 收藏

     摘要: 虽然C10K问题已被妥善解决,但对于即时通讯应用(或其它网络编程方面)的开发者而言,研究C10K问题仍然价值巨大,因为技术的发展都是有规律和线索可循的,了解C10K问题及其解决思路,通过举一反三,或许可以为你以后面对类似问题提供更多可借鉴的思想和解决问题的实践思路。而这,也正是撰写本文的目的所在。  阅读全文

posted @ 2016-10-21 16:02 Jack Jiang 阅读(2695) | 评论 (0)编辑 收藏

     摘要: 本文将以新手的视角引导你阅读相关文章,以便为从零开发一个移动端IM做好方方面面的知识准备:包括但不限于网络编程基础、通信协议的选型、IM的架构设计等等。  阅读全文

posted @ 2016-08-29 17:42 Jack Jiang 阅读(3234) | 评论 (0)编辑 收藏

     摘要: 本文将简要介绍TeamTalk开源的过去和现在,为打算研究和采用TeamTalk的同行提供一定程度的参考。  阅读全文

posted @ 2016-08-09 17:25 Jack Jiang 阅读(2866) | 评论 (0)编辑 收藏

     摘要: 本文基于作者的实践以及相关资料的整理,总结了自已对Android进程和Service保活的理解,希望能为你的应用开发带来启发。  阅读全文

posted @ 2016-08-02 22:43 Jack Jiang 阅读(2594) | 评论 (0)编辑 收藏

     摘要: 本文将介绍如何在现有的技术基础上选择合适的方案开发一个“服务器推”(Comet技术)的应用,最优的方案还是取决于应用需求的本身。相对于传统的 Web 应用, 开发 Comet 应用具有一定的挑战性。  阅读全文

posted @ 2016-07-28 11:07 Jack Jiang 阅读(1530) | 评论 (0)编辑 收藏

     摘要: 本文对服务器推送技术(SSE)进行了详细的介绍,包含浏览器端和服务器端的相应实现细节,为在实践中使用该技术提供了指南  阅读全文

posted @ 2016-07-22 18:03 Jack Jiang 阅读(1229) | 评论 (0)编辑 收藏

     摘要: Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询、Comet技术、WebSocket技术、SSE(Server-sent Events)。本文将简要介绍这4种技术的原理,并指出各自的异同点、优缺点等。  阅读全文

posted @ 2016-07-15 15:08 Jack Jiang 阅读(1925) | 评论 (2)编辑 收藏

     摘要: Web端的IM应用,由于浏览器的兼容性以及其固有的“客户端请求服务器处理并响应”的通信模型,造成了要在浏览器中实现一个兼容性较好的IM应用,其通信过程必然是诸多技术的组合,本文的目的就是要详细探讨这些技术并分析其原理和过程。   阅读全文

posted @ 2016-07-12 15:59 Jack Jiang 阅读(5632) | 评论 (0)编辑 收藏

     摘要: 文演示的是一个Android客户端程序,通过UDP协议与两个典型的NIO框架服务端(分别用MINA2和Netty4来实现),实现跨平台双向通信的完整Demo。  阅读全文

posted @ 2016-06-30 16:57 Jack Jiang 阅读(785) | 评论 (0)编辑 收藏

     摘要: 本文将演示一个iOS客户端程序,通过UDP协议与两个典型的NIO框架服务端(将分别用MINA2和Netty4来实现),实现跨平台双向通信的完整Demo。  阅读全文

posted @ 2016-06-28 22:11 Jack Jiang 阅读(1417) | 评论 (0)编辑 收藏

     摘要: 本文是《NIO框架入门》系列文章中的第2篇,将演示的是一个基于MINA2的UDP服务端和一个标准UDP客户端(Java实现)双向通信的完整例子。  阅读全文

posted @ 2016-06-24 14:38 Jack Jiang 阅读(875) | 评论 (0)编辑 收藏

     摘要: 本文将演示的是一个基于Netty4的UDP服务端和一个标准UDP客户端(Java实现)双向通信的完整例子。实际上,Netty4的UDP例子非常难找,官方的代码演示里只有一个简单的UDP广播例子,不足以用于演示Netty4的UDP通信最佳实践。  阅读全文

posted @ 2016-06-20 14:48 Jack Jiang 阅读(1546) | 评论 (0)编辑 收藏

     摘要: MobileIMSDK是一套专为移动端开发的原创即时通讯框架:超轻量级、高度提炼,lib包50KB以内;完全基于UDP协议实现;客户端支持iOS、Android、标准Java平台;可应用于跨设备、跨网络的聊天APP、企业OA、消息推送等各种场景。  阅读全文

posted @ 2015-12-14 15:18 Jack Jiang 阅读(2801) | 评论 (0)编辑 收藏

     摘要: MobileIMSDK是专为移动端开发的原创即时通讯开源框架:超轻量级、高度提炼,lib包50KB以内;完全基于UDP协议实现;客户端支持iOS、Android、标准Java平台;可应用于跨设备、跨网络的聊天APP、企业OA、消息推送等各种场景。  阅读全文

posted @ 2015-12-01 16:06 Jack Jiang 阅读(3424) | 评论 (2)编辑 收藏

2025年12月8日

本文由腾讯技术团队颜勇分享,原题“腾讯新闻PUSH架构升级之路”,有修订和重新排版。

1、引言

68 万行代码精简到8.6 万;Golang 重写大部分 C++模块;解决过度微服务化问题…… 这是新闻 PUSH 架构团队取得的技术收益。

PUSH 是腾讯新闻精品资讯的重要分发途径,也是新闻 App 重要的促活手段。作为 PUSH 架构团队,我们一方面在积极支持好新闻护盘,同时也在对 PUSH 架构进行不断的升级与进化,以持续提升 PUSH 系统的稳定性与质量、研发效率,同时持续减少运营成本。

本文主要分享的是腾讯技术团队近年来对腾讯新闻消息推送PUSH系统做的架构优化和技术实践。

cover-opti

2、Push平台介绍

2.1 概述

PUSH 是腾讯新闻内容重要的分发渠道,新闻 PUSH 平台承担着将新闻资讯触达到新闻用户、满足用户及时获取精品资讯的需求。

1

总体上,新闻 PUSH 链路分为下面两部分。

2.2 PUSH触发

按触发方式的不同,新闻 PUSH 分为三类:

  • 1)人工 PUSH:运营在 push cms 系统指定要发送的文章、要触达的人群包,人工触发push发送;这类 PUSH 目前主要用于推送热点事件/热点资讯等;
  • 2)自动化 PUSH:周期性地给用户计算他可能感兴趣的内容,这类推送由后台自动触发;
  • 3)功能性 PUSH:由业务系统触发,主要是为了实现一些业务功能通知,比如评论通知、关注通知等。

2.3 PUSH下发

对于所有 PUSH 触发 的PUSH 进行调度(包括避让、打散和频控等)和触达(通过自有通道或厂商通道推送给用户)。

新闻业务对新闻 PUSH 平台最重要的要求是:

1)要保证精品咨讯触达的及时性:

新闻 PUSH 最重要的是要体现“新”,因为腾讯新闻用户有及时获取热点/突发资讯的诉求,用户经常有这样的体感,有热点突发事件时,所有 App 都会尝试第一时间向用户发起推送,用户大概率会点击收到的第一个推送。在了解了相关热点事件后,对于后续其它 App 的推送,对用户而言就没信息量了,大概率会被忽略,甚至可能会被用户视为一种打扰,影响用户体验。从我们实验数据来看,当P USH 下发延迟降低 50%,PUSH 点击量会提升 10%。

所以新闻 PUSH 一直以来的目标是:热点资讯需要第一时间触达给用户,要做到“全网首推”。

2)要保证推送的用户体验和较好的拉起效率:

PUSH 是新闻重要的促活手段,需要有较好的促活效率,这要求保证用户较好的推送体验,因为用户如果感觉推送体验不好,用脚投票,把 App 的 PUSH 系统开关给关了,这对 PUSH 而言就基本上就永远丧失了给这个用户推送的机会了。这就要求要尽量保证在合适的时间点给推送用户感兴趣的内容,推送要有合理的频次,相邻 PUSH 之间要有合理的时间间隔,推送内容要做合适的打散。

其实这两个要求其实在一定层面上是有冲突的:

  • a.如果要保证推送的及时性,就要求尽量减少计算,拿到消息消息后无脑推到消息通道,这个肯定最快;
  • b.如果要保证良好的推送用户体验,就需要做很多的判断、考量和计算,这些考虑越多就需要做更多的计算和 io 操作,会影响推送的及时性;最近几年,业务成本的考虑也是 PUSH 关注的重点,需要削减使用的机器和资源,就要求用更少的机器如何发得更快更好。

总结而言,之前新闻 PUSH 业务的突出问题主要有两个方面,请继续往下阅读。

3、Push平台问题1:推送速度慢

我们团队从 2022 年年中开始接手新闻 PUSH 平台。交接工作刚启动,就遇到了一次 S 级热点事件——一个国际级突发新闻。那天晚上,全网用户都在密切关注它的最新进展。

这个事件有两个特点:热度极高、且并非完全突发——早在一个月前就已经有明确预告,因此运营部门提前布置了应急预案。我们刚接手系统时,对整个下发链路还不够熟悉,只能凭直觉扩容机器,希望能抗住峰值。结果现实很快给了我们一记当头棒喝。

当晚,很多内部同事都装着多个新闻 App,一眼能看到谁家的推送更快。那晚我们的延迟问题非常明显,甚至有用户在热点过去一个多小时后才收到通知。事后有专门的评测团队做了分析,指出“PUSH 下发耗时过长,高活用户 P90 均值达 20 分钟”,报告还发到了高层群里——对我们来说,那无疑是一次刻骨铭心的教训。

4、Push平台问题2:开发效率和问题排查效率低

之前 PUSH 链路特别长,新闻 PUSH 内部有 30+ 个模块,同时还依赖其它两个跨业务团队。经常一个需求开发要改多个模块,要团队几个人一起开发,约定交互协议,开发后再联调测试,在多个模块起联合实验;然后还得给中台提需求,然后匹配中台的排期后,才能完成需求上线;这一系列操作就拉长了 push 需求的leadtime。

线上有 case 时,问题排查也需要串联多个模块,关联多个模块数据,甚至需要跨部门拉上其它这边来一起来排查,排查效率非常低。push case 非常多,比如用户为什么收到了/没收到某条 push 之类的典型 case,之前需要关联链路20来个模块的日志,还要联合中台一起排查,每次 case 排查时间都在天级;之前在case 排查上,每天都耗费我们大量的人力。

既要持续提升 PUSH 触达的及时性、又要持续提升推送的用户体验和拉活效率,还要持续降低运营成本,客观而言,在技术上是一个较大的挑战。本文主要详述,我们如何通过技术架构升级来支撑这个既要&又要&还要的目标。

5、老Push架构的问题梳理

5.1 模块链路过长,内耗过多

一条快速PUSH,从推送内容过审后,到最终发出去,最长要经过18个模块,另外还需要经过中台多个模块。一条待推送的数据最多要经历 17 次内部 rpc 转发,多个模块之间腾挪流转,各种网络 rpc,各种内耗,肯定发得慢。

一个最典型的例子:原架构有个模块叫scheduler,它主要负责决定一个push该不该发,直观上感觉它里面应该囊括了各种过滤策略,但是原架构做成了多个微服务。scheduler 模块里本身有一些过滤逻辑,另外有一个叫做 filter 的模块,专门负责品牌、开关等硬规则过滤;另外有一个叫做 policy 的模块,专门负责配额等软规则过滤;所有过滤规则都通过后,进入一个叫做 channer 模块,就决定下这次推送走哪个通道;然后又走到一个叫 worker 的模块里,而它只做对接下游中台的协议适配。

总体上看,原链路就是过度微服务化了:

  • 1)模块多会导致数据流转的低效,模块间网络 rpc 会浪费处理耗时;
  • 2)其次会影响迭代效率,模块数不是越多越好,因为经常一个需求需要改多个模块,做多次上线;
  • 3)同时模块过多也对联调&测试效率,影响线上 case 排查效率。

这就违反了“模块内高内聚,模块间低耦合”的架构设计原则,进而会影响业务迭代效率。

5.2 依赖服务有瓶颈

上文提到的 S 级热点事件时,我们将下发服务机器扩了一倍,但是下发速度并没有提升,说明瓶颈不在下发服务本身下,而是在依赖服务上;通过链路debug,我们定位到了链路瓶颈:号码包拉取。

在发送人工 push,运营会指定受众人群包(几百万到几亿不等),这时候需要分页拉取该号码包数据进行处理。

之前老架构使用了底层平台的人群包服务,新闻所有 push 人群包都上传到了该人群包服务,当发送指定人群包,需要请求平台侧接口分页拉取人群包数据,当时因为平台侧人群包功能实现比较复杂,能支持一些比较高级的能力,因此这个分页接口耗时比较长。但其实我们只用到了最简单的数据分页的功能,完全可以采用更简单的实现方案,以减少接口耗时。

5.3 链路稳定性不好

5.3.1)容错能力差:

之前链路基本无容错能力,发生了过一次因上游未按约定协议跟我们请求交互,导致我们服务挂了半天,是一次典型的 P0 级事故。

5.3.2)缺少节点自动故障转移:

scheduler 负责 push 调度,原架构为了提升处理效率,scheduler 里做了本地缓存;为了避免缓存失效,起了一个服务 dispatch 消费触发侧生产的待推送的消息,然后按照用户设备号一致性哈希来 sharding,通过 rpc 请求对应的 scheduler,scheduler接受到请求后,塞入到它本地的内存队列里,如果队列满了就直接丢弃。

它原来存在有这些问题:dispatch无脑往下游转发,sharding规则非常僵硬,一个用户的push一定要打到某个节点,未做故障转移;当某节点异常满载时,dispatch还是会往这个节点打,导致丢消息或者是 push发送得慢。而且当节点满载时,有限的cpu还需要耗费在rpc解包、无法插入内存队列而丢弃之类的无用消耗上。

5.4 链路处理无优先级区分

运营人工发的 PUSH 和自动化 PUSH 都使用同一个下发链路,热点突发事件资讯多由运营人工发送,而自动化 PUSH 多发一些用户可能感兴趣的内容,其实它对于推送速度并没那么敏感;当有人工推送的热点突发内容时,自动化 PUSH 会和它一起争抢有限的链路资源。

另外,在链路总吞吐量一定的情况下,其实处理顺序可以调整,让链路资源有限保证人工推送的热点突发内容的发送;

5.5 技术栈不统一

之前 push 下发链路有 C++/Go 两种技术栈,技术栈不统一不利于代码复用,影响需求迭代效率。push下发链路本质上是一个高 io 型的流程,其实可以完全可以统一到 Golang 技术栈。

5.6 链路测试效率低

push 链路业务逻辑比较多,在日常密集业务需求迭代中,新功能我们可以在线上通过构造对应的功能 case 来进行冒烟测试,但是比较难评估是否影响了线上已有的业务逻辑。

之前缺乏有效的回归测试手段,由于担心影响线上业务指标,为了验证是否影响线上已有业务逻辑,我们大的修改都会开比较长的小流量实验验证,比如我们在做调度架构升级时,开了一个近两个月的小流量实验,测试效率比较低也会导致需求迭代效率比较低。

6、新Push架构优化1:消息通道自建

之前新闻 PUSH 依赖于平台侧的消息通道,业务侧主要负责 PUSH 调度,即业务侧决定触发和过滤,平台侧负责 PUSH 触达给用户终端。

由于 PUSH 是新闻增长护盘的重点方向,有较频繁的业务迭代,对底层消息通道我们有较多的业务需求,在业务迭代过程中我们发现平台侧需求 leadtime 比较长,无法满足业务侧迭代效率的要求;在经平台侧这边商量且同意后,我们完成新闻push消息通道的自研,直接对接厂商推送并搭建了长链接通道,实现了 push 全链路在业务侧的全闭环。

我们在自建 push 消息通道时,对原来的架构做了重写:

1)精简链路,模块整合,减少系统复杂度:去掉我们不关心的无用功能,将原链路15个模块,代码 68 万行整合为了6个模块,代码共8.6万行;通过代码精简能减少系统复杂度,有助于提升业务迭代效率;同时能避免模块之间的rpc通信开销,提升链路处理效率。

2)客户端/服务端交互接口整合,提升数据通信成功率:以前 PUSH 注册依赖于注册&绑定&上报三个接口请求,任何一次请求出错,push 注册就会失败;我们在新流程里将注册&绑定&上报需要的所有数据,都一起传给新接口,由服务端在一个接口里实现注册、绑定和上报;将注册成功率从90%提升到了99.9%。

3)与新闻技术技术架构保持统一:将原架构发现/rpc技术栈的基础组件升级为腾讯新闻自用的基础组件,尽量使用我们熟练使用的技术栈,以提升业务开发&运维效率。

4)优化了原来链路一些不合理的地方:对原来链路的限流机制、通道选择策略做了优化,增加了必要的功能,比如小流量实验环境的支持。

7、新Push架构优化2:统一技术栈

之前 push 链路有 C++/Golang 两种技术栈,除了 push 推荐服务外, 其它 C++链路模块全部使用 Golang 模块进行了重写,以提升业务迭代效率和链路稳定性。

8、新Push架构优化3:链路整合升级,提升效率

一个架构如果如果过度微服务化了,会带来各种问题:

  • 1)模块间耦合严重,影响研发效率:本来是一个模块应该完成的工作,硬拆成了2个模块,有改动需要都需要改两个模块,需要模块间联调测试,影响需求迭代效率。
  • 2)架构效率低:拆成微服务后,函数本地调用变成了RPC网络调用,需要增加大量的拆包、解包的操作,资源白白浪费在这些无用的内耗上了。

对于频繁迭代的地方,单独抽成单独的微服务是有助于提升迭代效率的;但是我们review历史push需求,都比较分散,没有集中到一个特定的地方,我们按照“一个需求尽量只用改一个模块”的原则,对原来的push链路的所有模块进行了整合升级。

具体的升级内容是:

  • a. 触发侧合并为了1个模块:将原来触发侧的5个模块合并为1个模块;
  • b. 调度侧合并为了1个模块:将原来调度侧的5个模块合并为了1个模块;
  • c. 将消息通道侧模块做了整合:如上所述,我们将push消息通道原来15个模块合并为了5个。

经过链路整合后:以前一个 PUSH 消息最多要经过 18 个模块,17次内部链路rpc转发;升级后,只用经过 3 个模块,只用经过 2 次 rpc 转发;这样就显著提升了链路效率;而且模块减少后,业务需要迭代无需开发多个模块,避免模块之间联调和测试,提升了业务迭代效率;同时,线上 case 排查时,无需做多模块的日志 join,提升了 case 排查效率。

9、新Push架构优化4:自建号码包服务,提升号码包获取速度

如上文所述:之前号码包的拉取慢是系统的主要瓶颈所在,而在我们这个场景比较简单,因此我们考虑自建号码包服务,针对于我们自己的需求来定制开发,以提升服务性能。我们的需求只有一个,就是对离线包进行分页,并提供服务接口返回指定页的数据。

1)画像中台圈选兴趣包,并按页切成若干个小文件,每个兴趣包一个文件夹,并上传到cos,兴趣包里带着数据版本号;

2)构建包管理服务,提供获取指定兴趣包指定页数据的能力;包管理服务定期从cos上check是否有更新的数据(比较本地数据版本和cos最新的数据版本),如果有,则拉取最新的数据更新本地数据;当接收到拉取指定包指定页数据的请求后,则定位到对应文件夹读取对应页文件数据并返回;

3)集群有个数据一致性哨兵,定期检查集群节点的数据版本,当发现集群数据版本不一致时,给集群所有节点发信号,强制让每个节点同步cos上的最新数据,让集群所有节点数据跟最新数据保持一致。

2

10、新Push架构优化5:在线过滤改成离线预处理,避免在线处理耗时

运营在发PUSH时会选择受众人群包,同时会指定系统、品牌等筛选项,之前的处理流程是先把人群包一股脑发到链路里,然后在下发链路里根据用户画像数据,对数据进行实时过滤。在线过滤增加了链路下发的耗时。

其实系统&品牌过滤完全可以前置到离线侧,我们将号码包按品牌和系统维度进行了拆分,比如“社会”包按 android/ios、huawei/oppo/vivo/honor/xiaomi,拆成了13个包,当运营选择指定的筛选项时,直接拉取对应的号码包,这样就避免了在线过滤的耗时,减少了下发的延时。

11、新Push架构优化6:将单IO操作自动聚合成批量操作

push下发链路有大量io操作,比如获取用户维度的多路数据(比如用户系统、品牌、下发&曝光&点击历史等),获取文章维度的多路数据(文章正排数据等)。链路其实主要耗时还是在io部分,如果能提升io吞吐量,就能提升PUSH链路的吞吐量,减少下发延时;io操作批处理肯定能提升吞吐量。

但是在具体业务流程中,不同push类型、不用品牌用户,处理逻辑会有不同,因为每个push的处理流程可能都不一样,无法直接批处理。所以之前调度主链路流程是从队列里按单个消费进行处理的。

为了提升链路吞吐量,我们对每一类io操作做了一个类,对外暴露一个单个io请求接口,外部调用该接口后,将请求压入一个异步队列,同时开始等待结果的返回;这样该类io请求都会在该异步队列里进行了汇聚。

下层会开若干个处理协程,批量从异步队列消费出若干请求任务,拼成批量的io请求,然后拿到批量io结果,按序向上层返回io结果;

这样对上层而言,看到的还是单个的同步io接口,上层业务逻辑开发流程无需做改造,底层其实已经自动做了io的批量聚合,显著提升了链路吞吐量。

12、新Push架构优化7:优先推送热点突发内容,优先保证高价值用户及时性体验

在链路吞吐量一定的情况下,一个推送任务小到几百万,大到一两亿的发送量,都需要处理时间。这时候先处理比后处理的时延要少。

其实可以考虑对链路发送进行调度:

  • 1)链路优先保障热点突发PUSH的发送,我们建立了任务优先级队列,当有热点突发PUSH在发送时,其它PUSH延迟发送;
  • 2)同一个PUSH任务,对用户推送顺序也做了排序:活跃度高、历史push点击率高、预估商业化价值高、对push时延敏感的用户优先发送。

通过优先级调度,最大程度保障了热点突发内容和高价值用户的推送及时性的体感。

13、新Push架构优化8:增加自动故障恢复能力

为了提升链路吞吐量,调度节点进程通过 LRU cache 缓存了大量数据,所以在推送消息处理的 sharding 方式上采用了按设备号一致性哈希。

很多时候某个节点异常时,会出现慢而不死的情况:处理能力陡降,但是节点存活正常。北极星未能把它摘掉,相当一部分设备会打到该节点,即使该节点已经满载了,之前架构为了避免缓存失效而导致处理耗时增加,还是会一致性哈希将流量打往该节点,导致这部分用户处理耗时异常增加,甚至发送失败。

新架构对于推送任务sharding做了优化:在一致性哈希的基础上,每个节点计算出4个固定的backup;当某节点的失败率或处理耗时超过一定阈值时,将该节点的流量均匀低分给他的backup。通过这种方式就支持单节点异常时的自动故障恢复。

14、新Push架构优化9:构建push链路自动化测试能力

构建了接口自动化回归测试流程:

  • 1)case覆盖push链路的核心逻辑;
  • 2)合并master时自动触发回归测试流程的执行。

构建了自动化diff测试流程:

diff流程大体思路都类似,通过录制线上流量的真实请求和返回结果,在测试环境进行回放,观察同一请求下,返回结果是否会有差别;如果无差别,说明测试环境跟线上一样,上线不会引起线上数据异常;如果有差别,就需要分析这些差别是否是符合预期的。

diff测试基本能回归到线上所有业务逻辑分支,能弥补回归测试覆盖度有限的问题。

主要挑战:

push依赖的数据变化比较快,导致在同一时间,同一请求的返回结果会不同;比如push为了避免重复下发同一篇文章,会依赖于下发历史数据,线上录制了刚下发的某篇文章,在测试环境去回放肯定就不能下发了,因为线上刚把这篇文章写入到下发历史里,导致回放请求时返回结果是不能下发了,这样自然就产生了diff。

解决方案:

在流量录制时,除了录制请求之外,同时录制各个依赖数据,在回放时,依赖数据以依赖数据为准,通过这种方案就避免了依赖数据易变而引入diff的问题。

15、架构升级后的系统表现

1)push运营成本显著降低:通过持续的 push 架构优化,新闻 push 总运营成本下降70%;

2)PUSH链路性能(吞吐量)显著提升:通过持续的 push 架构优化,显著提升了 push 链路的性能,push推送量(出口)峰值吞吐量提升了3.5倍;

3)热点突发(全国/快速)PUSH全链路耗时下降明显:

  • a. 热点突发(全国/快速)PUSH内部链路耗时P90下降了90%;
  • b. 内部链路耗时指的是从push审核通过到推送给厂商的时间,即我们内部链路总的耗时时长;
  • c. 热点突发(全国/快速)PUSH全链路耗时(包括内部链路耗时和厂商链路耗时)下降了90%
  • d. 全链路耗时指的是从push审核通过到用户收到PUSH时间,即包括内部链路和厂商链路总的耗时时长.

我们完成一些架构升级后,还是评测团队对了评测,腾讯新闻的PUSH已经领先于竞品1~4分钟了。

4)提升了PUSH点击效果:

push推送速度提升后,push点击数据也能看到明显受益,热点突发PUSH点击pv提升了10%,push大盘点击UV也能看到显著的正向收益;

线上收不到PUSH的用户客诉也减少到25年H1 0 例,提升了用户产品体验。

5)稳定性良好:push链路主要重构完成后,PUSH链路稳定性&质量明显提升,2025.02以后 0 故障。

16、参考资料

[1] 极光推送系统大规模高并发架构的技术实践分享

[2] 魅族2500万长连接的实时消息推送架构的技术实践分享

[3] 专访魅族架构师:海量长连接的实时消息推送系统的心得体会

[4] 一个基于长连接的安全可扩展的订阅/推送服务实现思路

[5] 实践分享:如何构建一套高可用的移动端消息推送系统?

[6] Go语言构建千万级在线的高并发消息推送系统实践(来自360公司)

[7] 腾讯信鸽技术分享:百亿级实时消息推送的实战经验

[8] 百万在线的美拍直播弹幕系统的实时推送技术实践之路

[9] 京东京麦商家开放平台的消息推送架构演进之路

[10] 技术干货:从零开始,教你设计一个百万级的消息推送系统

[11] 长连接网关技术专题(四):爱奇艺WebSocket实时推送网关技术实践

[12] 喜马拉雅亿级用户量的离线消息推送系统架构设计实践

[13] 直播系统聊天技术(四):百度直播的海量用户实时消息系统架构演进实践

[14] 消息推送技术干货:美团实时消息推送服务的技术演进之路

[15] 揭秘vivo百亿级厂商消息推送平台的高可用技术实践

[16] 得物从零构建亿级消息推送系统的送达稳定性监控体系技术实践

[17] B站千万级长连接实时消息系统的架构设计与实践

[18] 转转千万级用户量消息推送系统的架构演进之路

[19] 企业级实时消息推送系统的架构设计,一文即懂!

技术交流:

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

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

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

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

2025年11月25日

本文由自字节跳动技术肖新蔚、赵彦奇分享,有修订和重新排版。

1、引言

本文要分享的是字节跳动团队针对火山HTTPDNS Cache2.0通过自研网段库与动态划分算法,将缓存粒度从“城市-运营商”细化为“网段”,解决了传统方案的城市级调度污染问题。配合缓存分级、预取等优化,在提升调度精准度的同时保证了高命中率,最终实现了服务端调度准确性提升和客户端性能优化。

cover-opti

技术交流:

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

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

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

2、系列文章

移动端弱网优化专题(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端弱网优化专题(二):史上最全移动弱网络优化方法总结

移动端弱网优化专题(三):现代移动端网络短连接的优化手段总结

移动端弱网优化专题(四):百度APP网络深度优化实践(DNS优化篇)

移动端弱网优化专题(五):百度APP网络深度优化实践(网络连接优化篇)

移动端弱网优化专题(六):百度APP网络深度优化实践(移动弱网优化篇)

移动端弱网优化专题(七):爱奇艺APP网络优化实践(网络请求成功率优化篇)

移动端弱网优化专题(八):美团点评的网络优化实践(大幅提升连接成功率、速度等)

移动端弱网优化专题(九):淘宝移动端统一网络库的架构演进和弱网优化实践

移动端弱网优化专题(十):爱奇艺APP跨国弱网通信的优化实践

移动端弱网优化专题(十一):美图APP的移动端DNS优化实践

移动端弱网优化专题(十二):得物自研移动端弱网诊断工具的技术实践

移动端弱网优化专题(十三):得物移动端常见白屏问题优化(网络优化篇)

移动端弱网优化专题(十四):携程APP移动网络优化实践(弱网识别篇)

移动端弱网优化专题(十五):字节跳动移动端网络HttpDNS优化实践》(☜ 本文

3、技术背景

在字节跳动的业务生态中,HTTPDNS 承担着为抖音、今日头条、西瓜视频等核心应用提供域名解析服务的重任。但目前我们所采用的业界主流缓存机制(火山Cache1.0),却存在着调度不准的问题。

这些问题主要是:

  • 1)业界主流缓存机制的问题;
  • 2)缓存粒度:城市-运营商;
  • 3)致命缺陷:当自身IP库与权威DNS服务器不同,易发生调度不准,可能影响用户体验。

4、主流HttpDNS调度修正机制的局限性

针对 HTTPDNS 调度不准风险,业界主流处置流程采用 “发现-定位-修复” 三步闭环机制.

具体如下:

  • 1)发现:通过监控告警、业务异常反馈等方式,识别存在调度偏差的解析场景;
  • 2)定位:结合访问日志、链路追踪数据等,定位调度不准的具体域名、源IP段和目标 IP 段;
  • 3)修复:通过技术手段修正解析结果。

针对上述第 3)点,核心修复方式包含以下两类(均存在显著局限性):

  • 1)地址库升级:基于外部供应商数据聚合构建的 IP 地址库,即使实时更新,仍难与外部 CDN 厂商的映射保持一致;
  • 2)临时劫持:手动配置解析劫持规则修正解析结果,不仅操作流程繁琐、耗时长,且需人工维护大量静态配置;若规则未得到及时维护,易引发解析结果异常。 
1

5、主流厂商的HttpDNS缓存粒度技术方案

缓存粒度设计直接影响 DNS 解析精准度,主流厂商的方案存在明显差异:

2

6、HttpDNS的缓存键精细化重构

我们综合考量调度精准度、工程复杂度以及成本,决定将缓存粒度由“城市+运营商”细化为“网段”。

6.1 传统方案(国内某厂商/火山Cache1.0)

3

  • 1)缓存粒度:城市+运营商;
  • 2)污染范围:整个城市运营商;
  • 3)调度准确性:低。

6.2 Cache2.0方案

4
  • 1)缓存粒度:网段;
  • 2)污染范围:单个网段;
  • 3)调度准确性:高。

6.3 网段自适应划分算法

背景:外部 CDN 厂商的调度结果会随网络拓扑和调度策略持续变化,而静态网段库划分方式固定,难以实时跟踪调度结果变化。

为解决这一问题,网段库动态划分算法通过“数据输入—一致性校验—网段调整—结果输出”的闭环流程,实现了网段库的自适应动态划分。

具体流程如下。

1)数据输入:

* 收集客户端IP—CDN IP映射数据:

  • a)数据来源:主动拨测结果;HTTPDNS 递归节点日志;
  • b)数据范围:主流CDN厂商的解析结果。

* 网段归属判断:

  • a)若相邻客户端IP的CDN IP 归属同一运营商,则该组CIP可合并为连续网段;
  • b)将合并后的连续网段输出,作为探测网段数据集。

2)一致性校验:

  • a)将探测网段数据集与存量CIDRDB网段库进行逐网段对比,检查 “映射一致性”;
  • b)若存在映射不一致,则触发网段调整流程。

3)网段调整:

  • a)合并:探测数据集的网段比现有库粗,合并为大网段;
  • b)拆分:探测数据集的网段比现有库细,拆分为小网段。

4)结果输出:

  • a)生成优化后的新CIDRDB网段库;
  • b)替换存量网段库,实现动态更新。

5)持续迭代:

  • a)重复上述流程,实现网段库的自适应动态划分。
5

7、HttpDNS的缓存策略优化

为解决缓存粒度细化可能导致的命中率下降问题,Cache2.0 引入了四重优化策略,最终实现了如下收益:

缓存命中率提高了15%,缓存量、CPU 使用和出网流量降低了约70%。

1)两级一致性哈希分流:

火山 HTTPDNS 的流量转发以一致性哈希思想为核心,将用户请求链路(用户→LB→缓存层→递归层)拆分为两级哈希调度:

  • a)一级调度(LB→缓存层):以“源 IP + 域名”为哈希键。使用LB的一致性哈希策略,将同一用户对同一域名的请求统一路由至固定的 HTTPDNS 节点,避免传统轮询导致的请求分散;
  • b)二级调度(缓存层→递归层):以“域名 + 网段” 为哈希键。以 “域名 + 客户端网段” 作为哈希键,与缓存粒度完全对齐,确保某一“域名 + 网段”对应的查询请求均定向到唯一的递归层节点。

两级哈希协同调度,解决了缓存的碎片化问题,同时单一节点故障影响范围极小。

6

 


 

2)缓存分级管理:

在 HTTPDNS 场景中,不同域名对解析精度的需求不同。高优先级域名(如API 调用、直播 / 点播流媒体分发)对解析精准性要求高,跨网可能导致访问延迟增加;而低精度需求域名(如302域名)采用过细缓存会浪费存储资源,频繁回源也会增加权威 DNS 压力。

为实现缓存资源的精细化分配,火山 HTTPDNS 将缓存体系划分为“网段缓存、城市 - 运营商缓存、全局缓存” 三级,各级缓存适配不同应用场景。

具体是:

1)网段缓存:作为最高精度层级,聚焦高优先级业务场景 :一方面适配高优域名(如抖音 API 调用、图片分发、点播 / 直播流媒体传输等对精准性敏感的域名),另一方面服务重点集群(如 ToB 企业 HTTPDNS 服务、ToB 专属公共 DNS 服务),通过网段级细粒度缓存确保解析结果与用户实际网络链路高度匹配,降低访问延迟;

2)城市 - 运营商缓存:定位中等精度层级,适配普通域名场景:针对调度精准度要求较低的域名,以 “城市 + 运营商” 为缓存单元,平衡缓存命中率与存储开销;

3)全局缓存:作为基础精度层级,专门适配非智能解析域名:针对不支持 CDN 动态调度、解析结果无地域 / 运营商差异的域名(如静态官网、通用工具类服务域名),采用全局统一缓存策略,所有用户查询共享同一缓存结果,最大化提升缓存命中率,降低回源请求压力。

7

3)缓存更新分级策略:

在 HTTPDNS 系统中,统一的主动刷新策略虽然能保证缓存命中率,但存在明显问题:对不需要精细调度的域名浪费了存储资源,增加了下游压力。

基于以上问题,火山 HTTPDNS引入 “主动刷新 + 被动刷新”分级策略,以域名优先级和业务需求为依据,将缓存更新机制分为两类。

具体是:

  • a)后台线程主动刷新机制:针对高优域名(白名单),保留后台线程主动刷新,确保缓存持续有效、用户请求直接命中最新数据;
  • b)用户请求被动刷新机制:针对普通域名或非智能解析域名,由请求触发缓存更新,按需刷新,无需常驻后台刷新线程,降低资源消耗。

通过这种分级更新策略,高优先级域名仍能保证低延迟和高命中率,同时普通域名的刷新开销显著降低。

4)缓存预取机制:

依托 “缓存空间局部性原理”,火山 HTTPDNS 设计了缓存预取机制。当某条缓存请求(如 A 网段域名解析)触发更新时,系统不仅刷新目标网段缓存,还会同步更新与其具有 “亲缘关系” 的网段缓存(“亲缘关系”指地理相邻、同运营商节点覆盖的网段)。这种 “单次请求触发批量预取” 的设计能够提前将关联网段缓存置于准备状态,提升后续请求的命中率。

以抖音直播域名的实际访问场景为例,预取机制的运作过程如下:

  • a)本网段更新:当用户 A(IP 归属北京联通 10.0.1.0/24 网段)发起直播域名解析请求时,系统首先刷新其所属的 10.0.1.0/24 网段缓存;
  • b)预取更新:系统同时刷新与 10.0.1.0/24 网段具有亲缘关系的网段缓存,例如北京联通下的相邻网段(10.0.2.0/24、10.0.3.0/24),确保这些网段缓存也处于准备状态。

随后,当用户 B(10.0.2.0/24)或用户 C(10.0.10.0/24)发起相同直播域名的解析请求时,由于对应网段缓存已提前预取,无需等待回源即可直接命中缓存,显著降低访问延迟。

8、HttpDNS优化后的实际效果

8

服务端调度精准度提高:借助网段级缓存,用户获取的 IP 地址更加精准。按服务端日志数据口径,调度不准比例从万分之六下降至万分之二,降幅 60%,有效缓解了传统粗粒度缓存导致的“城市级缓存污染”问题。

客户端性能优化:

  • 1)成功率:核心 feed 接口,在弱网+非连接复用场景下提升 1.15%;
  • 2)耗时:非连接复用场景耗时减少14ms。
9

用户体验提升:

  • 1)性能指标:首刷及启动耗时下降;
  • 2)用户指标:用户行为指标(send 与 click)正向,用户活跃度提升。

本方案通过服务端精准调度 → 客户端性能优化 → 用户体验提升,实现了全链路效能提升。

9、持续演进方向——共享缓存

目前,各机房的负载均衡策略与缓存策略未能完全对齐(部分采用随机转发,部分虽然使用一致性哈希但粒度不一致),导致同一数据在多个实例中被重复缓存,资源利用率偏低,缓存命中率也有待提升。

未来,我们计划构建一个分层共享的高可用缓存体系:

1)在同一机房内,实例通过一致性哈希协同分工,每台实例既是分片缓存,也能代理转发请求,从而减少重复存储并提升命中率;

2)在跨机房层面,按区域部署二级缓存节点,作为容量更大、延迟更低的共享中心,承接一级未命中的请求,降低跨区域访问和上游压力。与此同时,引入热点数据副本、请求合并和故障转移等机制,保证高并发和异常情况下的稳定性与可用性。

通过这一演进,整体架构将逐步升级为层次化、分布式且具备高可用能力的缓存网络,为业务的持续扩展提供坚实支撑。

10、参考资料

[1] TCP/IP详解 卷1:协议 - 第14章 DNS:域名系统

[2] 网络编程懒人入门(七):深入浅出,全面理解HTTP协议

[3] 网络编程懒人入门(十二):快速读懂Http/3协议,一篇就够!

[4] 从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路

[5] 脑残式网络编程入门(三):HTTP协议必知必会的一些知识

[6] 全面了解移动端DNS域名劫持等杂症:原理、根源、HttpDNS解决方案等

[7] 通俗易懂,理解移动网络的“弱”和“慢”

[8] 现代移动端网络短连接的优化手段总结

[9] 百度APP网络深度优化实践(DNS优化篇)

[10] 爱奇艺APP网络优化实践(网络请求成功率优化篇)

[11] 美团点评的网络优化实践(大幅提升连接成功率、速度等)

[12] 淘宝移动端统一网络库的架构演进和弱网优化实践

[13] 爱奇艺APP跨国弱网通信的优化实践

[14] 得物自研移动端弱网诊断工具的技术实践

[15] 携程APP移动网络优化实践(弱网识别篇)

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

posted @ 2025-11-25 10:45 Jack Jiang 阅读(31) | 评论 (0)编辑 收藏

2025年11月11日

本文来自转转技术李帅的原创分享,已进行修订和排版优化。

1、引言

在当今互联网时代,高效的用户服务是提升用户体验的关键。转转自研的客服IM聊天系统作为用户与客服沟通的桥梁,承担着传递信息、解决问题的关键角色。然而,消息数据的流转并非一帆风顺,本文将深入探讨IM系统在消息传递过程中遇到的问题和挑战,以及相应的技术解决方案。

如图是IM系统中一条消息的流转链路:

 1

相较于普通web系统,IM系统的消息数据流转链路更长、更复杂。从客户端到服务端,再从服务端到另一个客户端,任何一个环节的故障都可能导致消息延迟、丢失、乱序或重复,从而影响用户体验。

网络波动和客户端设备性能的不稳定性是影响IM系统性能的主要因素,这些因素可能导致消息的实时性、可靠性和完整性受到威胁。

技术交流:

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

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

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

2、关于作者

李帅:转转履约中台研发工程师,主要负责客服工单、IM等系统研发。

3、如何保证聊天消息的实时性

首当其冲的就是消息延迟问题:当一条消息发出后,我们的系统需要确保这条消息最快被接收人感知并获取到,并且保证资源消耗较少。

这里关键的点是:

  • 1)最快触达;
  • 2)耗费资源少。

方案1:长短轮询

在PC web早期,大部分应用都是采用“一问一答”的请求响应模式来获取数据,IM系统采用客户端轮询的方式,定期、高频轮询获取服务端的新消息。这种方式开发成本较低、容易实现,但是高频轮询很多请求是无用请求,客户端浪费流量和电量,服务端资源压力很大。

后来基于短轮询进化出长轮询模式,相较于前者,后者在请求时获取到新数据时不会立即返回,而是在服务端保持连接等待一段时间,如果等待期间有新消息就立即返回响应,长轮询仅仅解决了客户端的无用消耗,但是服务端资源高负载情况依然未能解决。

方案2:WebSocket

随着HTML5的出现,全双工的WebSocket成为解决这一问题的关键。基于WebSocket实现的IM服务,客户端和服务端只需要完成一次握手,就可以创建持久的长连接,并进行随时的双向数据传输。

2
经过比较转转客服IM系统采用了WebSocket协议,具体使用方式见《转转客服IM系统的WebSocket集群架构设计和部署方案》。当服务端接收到新消息时,可以通过建立的WebSocket连接,直接进行推送,保证了消息到达的实时性。

关于传统Web和现代Web的实时通信技术,可详读以下几篇:

  1. Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE
  2. 详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket
  3. 网页端IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket

4、什么是聊天消息的可靠性

如图是一条消息发送的核心步骤,整个过程中可以分为两个部分,消息由客户端发送到服务端(第1、2步),服务端将消息推送至另一个客户端(第3步),发送过程中任何一步出现问题都会导致消息发送失败。

3

PS:限于篇幅原因,本文不想深入探讨,有兴趣可详读《零基础IM开发入门(三):什么是IM系统的可靠性?》。

5、如何保证聊天消息触必达?

我们参考使用了TCP/IP协议中的ACK机制来实现防丢逻辑(《TCP/IP详解 - 第17章·TCP:传输控制协议》)。ACK机制是TCP/IP协议三次握手重要的一环(请详读《脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手》),用于确认对方发送信息无误。

ACK响应机制如下:

  • 1)发送者发送消息时会携带一个消息标识符(此处使用发送方id和消息发送时间戳)、并在本地维护一个“等待ACK消息列表”;
  • 2)接收者收到消息后对消息进行存储得到消息id;
  • 3)随后再将该标识回传给发送方(ACK消息);
  • 4)发送方收到ACK消息后将消息从“等待ACK消息列表”删除;
  • 5)当发送方没有在约定时间内收到ACK消息时,就需要执行失败消息处理逻辑:自动重发、客户端标记发送失败等。

服务端实现与客户端稍有不同,服务端需要要维护全量用户的消息,使用定时任务检查等待ACK消息列表效率比较低,此处通过mq的延迟消息来实现:

当消息发出时同时发送一个延迟mq,延迟消息被消费时对应的消息仍在等待ACK列表中,则表示消息未能在规定时间内被确认,需要进行重试发送。

如图为完整的ACK实现机制:

4

另外客户端也会在页面刷新、WebSocket重连时触发http接口重新拉取当前会话的所有消息进行渲染,保证消息不丢失。

PS:相关资料可进一步阅读:

  1. IM消息送达保证机制实现(一):保证在线实时消息的可靠投递
  2. 阿里IM技术分享(四):闲鱼亿级IM消息系统的可靠投递优化实践
  3. 融云技术分享:全面揭秘亿级IM消息的可靠投递机制
  4. 一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等

6、如何对聊天消息去重?

消息重推解决了消息丢失的问题,但是因为ACK消息本身就可能会丢失从而导致消息重复,因此我们需要保证推送消息和重推消息有相同且唯一的消息id,接收方可以根据该消息id进行数据去重。

具体是:

  • 1)发送方:客户端使用发送人id和消息发送时间戳作为唯一的ACK标识,传递给服务端;
  • 2)服务端:使用雪花算法接收到的消息生成消息id,将ACK标识与消息id建立映射关系;服务端再将消息id推送至发送方和接收方。

一个完整的消息发送流程如图所示:

5

7、心跳保活机制

IM系统中接收和发送消息都是使用长连接实现,但是如果连接断开,那发送和接收数据就会出现问题。在客服业务中,人工客服席位有限,系统需要可靠的机制保证人工客服资源有效利用。

为此我们在应用层设计心跳消息,使用该机制更新用户当前状态、保证会话有序退出。

心跳机制设计如下。

客户端:设置定时器,用户建立连接后,定时发送(30s)心跳消息给服务端。

服务端:

  • 1)接收心跳消息,更新心跳时间;
  • 2)设置定时任务,定时扫描在线用户上次心跳时间,执行以下逻辑;
  • 3)上次心跳时间超出30s,将其标记为离线状态,关闭连接,等待用户重连;
  • 4)上次心跳时间超出2分钟则认为用户已经彻底离开,执行会话关闭逻辑释放人工客服资源。

应用层心跳消息仅用于保活和状态更新,因此数据结构设计十分精简,不携带额外信息。

关于心跳保活这方面的资料,可以进一步阅读:

  1. 为何基于TCP协议的移动端IM仍然需要心跳保活机制?
  2. 一文读懂即时通讯应用中的网络心跳包机制:作用、原理、实现思路等
  3. 微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
  4. 融云技术分享:融云安卓端IM产品的网络链路保活技术实践
  5. 跟着源码学IM(五):正确理解IM长连接、心跳及重连机制,并动手实现
  6. 阿里IM技术分享(五):闲鱼亿级IM消息系统的及时性优化实践
  7. 万字长文:手把手教你实现一套高效的IM长连接自适应心跳保活机制

8、消息协议的设计

在IM系统中消息格式的设计也十分重要,良好的数据格式可以准确传递消息内容并具有极高的可读性。

我们根据消息类型和发送流向将消息数据格式大致分为如下几部分:

  • 1)消息类型:用于描述消息的用途、流向,如心跳消息、用户/客服消息、系统消息等;
  • 2)客服id:接收或者发送消息的客服标识;
  • 3)用户id:接收或者发送消息的用户标识;
  • 4)消息内容:实际的消息,与消息类型相关;
  • 5)消息格式:用于描述用户/客服消息格式,如文本、图片、视频、订单卡片、优惠券等;
  • 6)消息文本:消息的展示内容。
6

PS:IM协议设计相关资料可进一步阅读:

  1. 简述移动端IM开发的那些坑:架构设计、通信协议和客户端
  2. 理论联系实际:一套典型的IM通信协议设计详解
  3. APP与后台通信数据格式的演进:从文本协议到二进制协议
  4. IM通讯协议专题学习(一):Protobuf从入门到精通,一篇就够!

9、本文小结

转转客服IM系统通过引入WebSocket协议、ACK机制、消息重推和数据去重等策略,有效应保障了消息传递过程中的实时性、可靠性和完整性。这些技术的应用,不仅提升了用户与客服之间的沟通效率,也为转转平台提供了更加稳定、高效的服务支持。

在未来的发展中,我们将继续优化和完善,以应对不断变化的需求和用户期望,为用户提供更加优质的服务体验。

10、参考资料

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

[1] Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

[2] 详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket

[3] 网页端IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket

[4] Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?

[5] 简述移动端IM开发的那些坑:架构设计、通信协议和客户端

[6] IM消息送达保证机制实现(一):保证在线实时消息的可靠投递

[7] 阿里IM技术分享(四):闲鱼亿级IM消息系统的可靠投递优化实践

[8] 阿里IM技术分享(五):闲鱼亿级IM消息系统的及时性优化实践

[9] 融云技术分享:全面揭秘亿级IM消息的可靠投递机制

[10] 一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等

[11] 理解IM消息“可靠性”和“一致性”问题,以及解决方案探讨

[12] 微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗

[13] 阿里IM技术分享(七):闲鱼IM的在线、离线聊天数据同步机制优化实践

[14] IM群聊消息如此复杂,如何保证不丢不重?

[15] 开发IM是自己设计协议用字节流好还是字符流好?

[16] 零基础IM开发入门(一):什么是IM系统?

[17] 零基础IM开发入门(二):什么是IM系统的实时性?

[18] 零基础IM开发入门(三):什么是IM系统的可靠性?

[19] 零基础IM开发入门(四):什么是IM系统的消息时序一致性?

[20] 脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手

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

posted @ 2025-11-11 19:49 Jack Jiang 阅读(50) | 评论 (0)编辑 收藏

2025年10月30日

1、前言

经常发现有开发者将密钥硬编码在Java代码、文件中,这样做会引起很大风险。

信息安全的基础在于密码学,而常用的密码学算法都是公开的,加密内容的保密依靠的是密钥的保密,密钥如果泄露,对于对称密码算法,根据用到的密钥算法和加密后的密文,很容易得到加密前的明文;对于非对称密码算法或者签名算法,根据密钥和要加密的明文,很容易获得计算出签名值,从而伪造签名。

密钥硬编码在代码中,而根据密钥的用途不同,这导致了不同的安全风险,有的导致加密数据被破解,数据不再保密,有的导致和服务器通信的加签被破解,引发各种血案,本文主要借用乌云上已公布的几个APP漏洞来讲讲这其中的潜在风险和危害。

技术交流:

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

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

2、风险案例(一):某互联网金融APP加密算法被破解导致敏感信息泄露

某P2P应用客户端,用来加密数据的DES算法的密钥硬编码在Java代码中,而DES算法是对称密码算法,既加密密钥和解密密钥相同。

反编译APP,发现DES算法:

1

发现DES算法的密钥,硬编码为“yrdAppKe”,用来加密手势密码:

2

将手势密码用DES加密后存放在本地LocusPassWordView.xml文件中:

3

知道了密文和加密算法以及密钥,通过解密操作,可以从文件中恢复出原始的手势密码。或者使用新的生成新的手势密码,而与服务器通信时接口中的Jason字段也用了DES算法和密钥硬编码为“yRdappKY”:

4

5

和服务器通信采用http传输,没有使用https来加密通信,如果采用中间人攻击或者路由器镜像,获得流量数据,可以破解出用户的通信内容。

3、风险案例(二):某租车APP加密算法被破解导致一些列风险

某租车APP与服务器通信的接口采用http传输数据,并且有对传输的部分参数进行了加密,加密算法采用AES,但是密钥硬编码在java代码中为“shenzhoucar123123”,可被逆向分析出来,导致伪造请求,结合服务器端的漏洞,引起越权访问的风险,如越权查看其它用户的订单等。

和服务器通信时的数据为:

6

q字段是加密后的内容。逆向APP,从登录Activity入手:

7

分析登录流程:

v1是用户名,v2是密码,v3是PushId,在用户名和密码不为空并且长度不小于11情况下,执行LoginOperate相关操作,追踪LoginOperate的实现,发现继承自BaseOperate,继续追踪BaseOperate的实现。

8

在BaseOperate的initUrl()方法中,找到了APP是怎么生成请求数据的:

9

继续追踪上图中的initJsonUrl()方法,发现其调用了AES加密:

10

继续追踪aes.onEncrypt()函数:

11

在onEncrypt()函数中调用了encrypt()函数用来加密数据,追踪encrypt()函数的实现:

发现其使用AES算法,并且密钥硬编码在java代码中为“shenzhoucar123123”。

12

构造{“id”:”11468061”}的请求:

到现在请求中的数据加密如何实现的就清晰了,另外由于服务器权限控制不严,就可以构造订单id的请求,达到越权访问到其他用户的订单。

13

其中uid设置为你自己的uid即可,可以成功看到其他人的订单:

14

攻击者完全可以做到使用其他脚本重新实现相同的加密功能并拼接出各个接口请求,批量的刷取订单信息和用户其他信息。

4、风险案例(三):某酒店APP加签算法被破解导致一系列风险

某酒店APP和服务器通信时接口采用http通信,数据进行了加密,并且对传输参数进行签名,在服务器端校验签名,以检查传输的数据是否被篡改,但是加签算法和密钥被逆向分析,可导致加签机制失效,攻击者可任意伪造请求包,若结合服务器端的权限控制有漏洞,则可引发越权风险等。

APP和服务器通信的原始包如下图,可以看到有加签字段sign:

15

逆向APP定位到加密算法的逻辑代码,com.htinns.biz.HttpUtils.class,其实现逻辑为:

16

原始数据是unSignData,使用RC4算法加密,密钥为KEY变量所代表的值,加密后的数据为signData,传输的数据时的data字段为signData。 加签字段signd的生成方法是用unsignData拼接时间戳time和resultkey,然后做md5,再进行base64编码。时间戳保证了每次请求包都不一样。 sendSign()算法是用c或c++写的,放入了so库,其他重要算法都是用java写的。

可以使用IDA逆向分析so库,找到sendSign()方法:

17

而乌云漏洞提交者采用的是分析sign和getSign(sign)的数据,做一个算法破解字典。其实还有种方法直接调用此so库,来生成字典。签名破解以后,就可以构造发送给服务器的数据包进行其他方面的安全测试,比如越权、重置密码等。

5、总结及建议

通过以上案例,并总结下自己平时发现密钥硬编码的主要形式有:

  • 1)密钥直接明文存在sharedprefs文件中,这是最不安全的。
  • 2)密钥直接硬编码在Java代码中,这很不安全,dex文件很容易被逆向成java代码。
  • 3)将密钥分成不同的几段,有的存储在文件中、有的存储在代码中,最后将他们拼接起来,可以将整个操作写的很复杂,这因为还是在java层,逆向者只要花点时间,也很容易被逆向。
  • 4)用ndk开发,将密钥放在so文件,加密解密操作都在so文件里,这从一定程度上提高了的安全性,挡住了一些逆向者,但是有经验的逆向者还是会使用IDA破解的。
  • 5)在so文件中不存储密钥,so文件中对密钥进行加解密操作,将密钥加密后的密钥命名为其他普通文件,存放在assets目录下或者其他目录下,接着在so文件里面添加无关代码(花指令),虽然可以增加静态分析难度,但是可以使用动态调式的方法,追踪加密解密函数,也可以查找到密钥内容。

保证密钥的安全确是件难事,涉及到密钥分发,存储,失效回收,APP防反编译和防调试,还有风险评估。可以说在设备上安全存储密钥这个基本无解,只能选择增大攻击者的逆向成本,让攻击者知难而退。而要是普通开发者的话,做妥善保护密钥这些事情这需要耗费很大的心血。

产品设计者或者开发者要明白自己的密钥是做什么用的,重要程度怎么样,密钥被逆向出来会造成什么风险,通过评估APP应用的重要程度来选择相应的技术方案。

6、参考资料

[1] https://www.zhihu.com/question/35136485/answer/84491440

[2] 传输层安全协议SSL/TLS的Java平台实现简介和Demo演示

[3] 理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)

[4] 微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解

[5] 来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享

[6] 简述实时音视频聊天中端到端加密(E2EE)的工作原理

[7] 移动端安全通信的利器——端到端加密(E2EE)技术详解

[8] Web端即时通讯安全:跨站点WebSocket劫持漏洞详解(含示例代码)

[9] 通俗易懂:一篇掌握即时通讯的消息传输安全原理

[10] IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token

[11] 快速读懂量子通信、量子加密技术

[12] 一分钟理解 HTTPS 到底解决了什么问题

[13] 一篇读懂HTTPS:加密原理、安全逻辑、数字证书等

[14] 基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等

[15] 手把手教你为基于Netty的IM生成自签名SSL/TLS证书

[16] 微信技术分享:揭秘微信后台安全特征数据仓库的架构设计

[17] 即时通讯初学者必知必会的20个网络编程和通信安全知识点

[18] 零基础IM开发入门(五):什么是IM系统的端到端加密?

7、IM安全系列文章

本文是IM通讯安全知识系列文章中的第 3 篇,总目录如下:

即时通讯安全篇(一):正确地理解和使用Android端加密算法

即时通讯安全篇(二):探讨组合加密算法在IM中的应用

即时通讯安全篇(三):常用加解密算法与通讯安全讲解

即时通讯安全篇(四):实例分析Android中密钥硬编码的风险》(☜ 本文)

即时通讯安全篇(五):对称加密技术在Android上的应用实践

即时通讯安全篇(六):非对称加密技术的原理与应用实践

即时通讯安全篇(七):用JWT技术解决IM系统Socket长连接的身份认证痛点

即时通讯安全篇(八):如果这样来理解HTTPS原理,一篇就够了

即时通讯安全篇(九):你知道,HTTPS用的是对称加密还是非对称加密?

即时通讯安全篇(十):为什么要用HTTPS?深入浅出,探密短连接的安全性

即时通讯安全篇(十一):IM聊天系统安全手段之通信连接层加密技术

即时通讯安全篇(十二):IM聊天系统安全手段之传输内容端到端加密技术

即时通讯安全篇(十三):信创必学,一文读懂什么是国密算法

即时通讯安全篇(十四):网络端口的安全防护技术实践

即时通讯安全篇(十五):详解硬编码密码的泄漏风险及其扫描原理和工具


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

posted @ 2025-10-30 11:24 Jack Jiang 阅读(42) | 评论 (0)编辑 收藏

2025年10月23日

本文由宅小年分享,感谢原作者,下文有修订和重新排版。

1、引言     

你有没有想过,为什么 ChatGPT 能够像人类聊天一样,一个字一个字地"蹦"出来回答你的问题?为什么股票软件能够实时更新价格,而不需要你疯狂刷新页面?

答案就藏在今天我们要聊的技术里——SSE(Server-Sent Events)!

本文将带你快速认识SSE实时通信协议,包括它的技术原理、常见使用场景、与同类技术的对比以及简单的示例代码等。

cover_opti

技术交流:

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

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

2、AI大模型实时通信技术专题

技术专题系列文章目录如下,本文是第 4 篇:

全民AI时代,大模型客户端和服务端的实时通信到底用什么协议?

大模型时代多模型AI网关的架构设计与实现

通俗易懂:AI大模型基于SSE的实时流式响应技术原理和实践示例

ChatGPT如何实现聊天一样的实时交互?快速读懂SSE实时“推”技术 》(☜ 本文)

《AI大模型时代爆火的SSE技术到底是什么?一文读懂SSE技术的方方面面(下期发布!)》

3、什么是SSE?

我们用一个饭店的比喻来解释:

1)轮询:你点了菜之后,每隔一会儿就跑去问服务员:“我的菜好了没?”

2)SSE:你点了菜,安心坐着。饭做好了,服务员主动来告诉你:“上菜啦!”

3)WebSocket:你和服务员之间装了个对讲机,随时可以互相说话;

4)SSE(Server-Sent Events):一种基于HTTP的单向通信协议,允许服务器主动向浏览器推送数据。它就像一根从服务器连到浏览器的“数据水管”,打开后服务器可以随时通过这根管子“浇水”(推送数据)。

SSE核心技术特点:

1)单向通信:服务器 → 浏览器(像广播电台)

2)基于HTTP:无需特殊协议

3)自动重连:网络中断会自动恢复

4)轻量级:原生浏览器支持,无需额外库

5)低延迟:数据实时到达(毫秒级)。

4、SSE与其他实时通信技术的对比

我们来看一张直观的对比表:


 

场景选择指南:

1)选SSE:当只需要服务器单向推送时(如新闻推送、监控仪表盘),SSE 是最简单省事的选择。

2)选WebSocket:需要双向实时通信(如在线游戏),那就请 WebSocket 登场。

3)选轮询/长轮询:如果只是偶尔有数据变化,使用轮询也许更简单粗暴。

精妙比喻:

1)SSE 像收音机(只能接收信号)

2)WebSocket 像电话(双向通话)

3)轮询 像不断翻信箱查信

4)长轮询 像守在信箱旁等邮差

关于SSE跟其它Web端实时通信技术的详细介绍,可以深入学习以下文章:

Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

使用WebSocket和SSE技术实现Web端消息推送

详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket

使用WebSocket和SSE技术实现Web端消息推送

一文读懂前端技术演进:盘点Web前端20年的技术变迁史

网页端IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket

搞懂现代Web端即时通讯技术一文就够:WebSocket、socket.io、SSE

5、SSE技术原理

我们用一个图来简单描绘 SSE 的工作过程:


 

关键要素解析

1)HTTP 请求头:客户端发送 Accept: text/event-stream 告诉服务器"我要接收事件流"

2)响应格式:服务器返回 Content-Type: text/event-stream,然后持续发送数据

3)事件格式:每个事件以 data: 内容\n\n 结束,两个换行符表示事件结束

4)自动重连:连接断开后,浏览器会自动发起新的连接请求

6、SSE的常见应用场景

SSE 已经在很多产品中落地,以下是几个典型场景.

ChatGPT 的回答显示机制:


 

ChatGPT 在回答你问题时,是一句一句“打字式”输出的,没错!就是用了 SSE 来流式传输生成的内容。

后台系统消息提醒,比如:

1)有新的订单;

2)用户提交了新评论;

3)后台工单更新了状态。

4)这些提醒都可以用 SSE 来实时推送。

实时数据面板:

1)股票价格变动

2)区块链交易动态

3)设备温湿度更新

4)只需要后端每隔几秒推送一次,前端就能不断展示最新数据。

7、示例代码(前端+后端)

前端代码(浏览器 JS):

<script>

  const eventSource = new EventSource('/sse/stream');

 

  eventSource.onmessage = function(event) {

    console.log('收到消息:', event.data);

    // 可更新到页面上

  };

 

  eventSource.onerror = function(err) {

    console.error('连接出错', err);

    // 可以展示连接断开的提示

  };

</script>

后端代码示例(Java,使用 Spring Boot 示例):

@RestController

publicclass SseController {

    privatestaticfinal Map<string, sseemitter=""> emitters = new ConcurrentHashMap<>();

 

    // 浏览器连接入口

    @GetMapping("/sse-connect")

    public SseEmitter connect(@RequestParam String userId) {

        SseEmitter emitter = new SseEmitter(30 * 60 * 1000L); // 30分钟超时

        emitters.put(userId, emitter);

 

        // 发送欢迎消息

        try {

            emitter.send(SseEmitter.event()

                    .name("welcome")

                    .data("🎉 连接成功!欢迎使用 SSE 服务"));

        } catch (IOException e) {

            System.err.println("发送欢迎消息失败: " + e.getMessage());

        }

 

        emitter.onCompletion(() -> emitters.remove(userId));

        emitter.onTimeout(() -> emitters.remove(userId));

 

        return emitter;

    }

 

    // 模拟推送服务

    @Scheduled(fixedRate = 2000)

    public void pushData() {

        emitters.forEach((userId, emitter) -> {

            try {

                String json = String.format(

                        "{\"time\": \"%s\", \"value\": %.2f}",

                        LocalTime.now(), Math.random() * 100

                );

 

                // 构建符合SSE格式的消息

                emitter.send(SseEmitter.event()

                        .id(UUID.randomUUID().toString())

                        .name("system-metrics")

                        .data(json));

            } catch (IOException e) {

                emitters.remove(userId);

            }

        });

    }

}

curl --location 'localhost:18500/sse-connect?userId=1' \

--header 'Key: Accept' \

--header 'Value: text/event-stream'


 

8、本文小结

SSE 就像一个贴心的"消息推送员",让服务器能够主动把最新消息送到你面前,而不需要你频繁地去"敲门询问"。它简单易用,特别适合那些需要服务器主动推送数据的场景。

虽然 SSE 没有 WebSocket 那么"全能"(不能双向通信),但正是这种专一性让它在特定场景下变得格外实用。就像专门的快递员虽然只负责送货,但在送货这件事上做得特别专业一样。

如果你正在开发一个需要实时推送但通信不需要太复杂的应用,SSE 是一个轻量又可靠的选择,特别适合现代网页、后台系统、数据展示等场景。

写在最后:Web 开发永远不止一种解决方案。选择最合适的技术,而不是最“酷”的技术,才是工程师的智慧体现。

9、参考资料

[1] Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

[2] SSE技术详解:一种全新的HTML5服务器推送事件技术

[3] 使用WebSocket和SSE技术实现Web端消息推送

[4] 详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket

[5] 使用WebSocket和SSE技术实现Web端消息推送

[6] 一文读懂前端技术演进:盘点Web前端20年的技术变迁史

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

[8] 网页端IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket

[9] 搞懂现代Web端即时通讯技术一文就够:WebSocket、socket.io、SSE

[10] 大模型时代多模型AI网关的架构设计与实现

[11] 全民AI时代,大模型客户端和服务端的实时通信到底用什么协议?

[12] 通俗易懂:AI大模型基于SSE的实时流式响应技术原理和实践示例

[13] Web端实时通信技术SSE在携程机票业务中的实践应用

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

posted @ 2025-10-23 10:33 Jack Jiang 阅读(43) | 评论 (0)编辑 收藏

2025年10月16日

1、MobileIMSDK开源工程

1

MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持UDP 、TCP 、WebSocket 三种协议,支持iOS、Android、H5、小程序、Uniapp、标准Java平台,服务端基于Netty编写。

工程同步开源地址:

2、关于RainbowChat

RainbowChat是一套基于开源IM即时通讯聊天框架 MobileIMSDK 的产品级移动端IM系统RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题。RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP、WebSocket三种通信协议的IM产品。与姊妹产品RainbowTalkRainbowChat-Web 技术同源,历经考验。

APP_Store_v10.2

3、v10.2 更新内容

此版更新内容更多历史更新日志):

  • 1)[优化] 修改了首页中网络断开提示ui的显示方式;
  • 2)[优化] 修改了世界频道中“免打扰”按钮;
  • 3)[优化] 修改了首页中“一键已读按钮”;
  • 4)[优化] 将世界频道改为首页列表中显示而不是独立的浮动层;
  • 5)[优化] 解决了iOS 26下聊天界面中因topLayoutGuide.length返回值异常导致的ui问题;
  • 6)[优化] 解决了iOS 26下聊天界面下方更多面板显示时会多出一个17像素的系统自带的圆角效果;
  • 7)[优化] 优化了iOS 26下聊天界面中的消息列表顶部会多出10个像素的空白;
  • 8)[优化] 给各种按钮增加了iOS 26液态玻璃点击效果;
  • 9)[优化] 其它适配iOS 26的各种细节优化。

v10.2_vs_v10

4、iOS 26上的运行效果概览

v10.2_ios26

5、iOS 26上的真机实拍概览

5

6、部分功能运行截图预览

(☞ 更多截图点此查看 ☜)

v10.2拼合总图-pct75-size50

posted @ 2025-10-16 10:54 Jack Jiang 阅读(52) | 评论 (0)编辑 收藏

2025年10月15日

     摘要: 本文来自小白debug的原创分享,原题“【修正版】动图图解!代码执行send成功后,数据就发出去了吗?”,下文有修订和排版优化。1、引言回复过很多IM初学者关于MobileIMSDK  通信层代码的疑问,最基础的问题就是“明明用的是TCP协议,而TCP协议也被称为可靠的通信协议,那为什么TCP代码中明确能知道数据是否发送成功,为什么仍然需要应...  阅读全文

posted @ 2025-10-15 14:59 Jack Jiang 阅读(46) | 评论 (0)编辑 收藏

2025年9月25日

1、引言

平时开发工作中,我们会经常接触加密、解密的技术。尤其在今天移动互联网时代,越来越多的用户会将数据存储在云端,或使用在线的服务处理信息。这些数据有些涉及用户的隐私,有些涉及用户的财产,要是没有一套的方案来解决用户的数据安全问题的话,这将是一个多么可怕的事儿。

作为开发者,也会经常遇到用户对数据安全的需求,当我们碰到了这些需求后如何解决,如何何种方式保证数据安全,哪种方式最有效,这些问题经常困惑着我们。52im社区本次着重整理了常见的通讯安全问题和加解密算法知识与即时通讯/IM开发同行们一起分享和学习。

技术交流:

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

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

2、通讯安全性威胁

一般的,我们在网络中传输的数据,都可以认为是存在这潜在的风险的。用一句话来概括就是:“任何在网络中传输的明文数据都存在安全性威胁。

下面就列举下我们通信中面临的四种威胁:

  • 1)中断:攻击者有意破坏和切断他人在网络上的通信,这是对可用性的攻击;
  • 2)截获:属于被动攻ji,攻击者从网络上qie听他人的通信内容,破坏信息的机密性;
  • 3)篡改:攻击者故意篡改网络上传送的报文,这是对完整性的攻击;
  • 4)伪造:攻击者伪造信息在网络传送,这是对真实性的攻击。
1

我们经常说加密解密算法是数据安全领域里的“剑”,是一种主动的防护,对数据进行必要的加密处理,以保证其在数据传输、存储中的安全。接下来讲着重讲解加解密算法知识。

3、Base64算法介绍

3.1 原理

严谨的说,base64并不是加密算法,这里提到他是因为他的实现比较简单,通过他的实现,我们可以更好的理解加密解密的过程。

下面看下他是如何“加密”的。假设我们要对“BC”字符串进行加密。现将其转换为二进制表达方式,并连起来:01000010 01000011,接下来对二进制按6位分组,不够6位补0,得到010000、100100、001100(最后两位补0)。下面查表,找到对应的值“QKM”。那么“QKM”就是“BC”用base64“加密”后的值了。

2

从上面的base64算法,我们可以窥视部分加密的本质:将一段有意义的信息,通过某种方式,映射为一段看不懂的信息。

使用函数表达即为:

public Ciphertext encrypted(Plaintext text);

值得注意的是:base64里有一张映射表,如果改变映射表的顺序,最终得到的结果就会跟着改变。有点类似烹调,在相同原料、相同烹调方式下,我们改变加入的调料,最终做出的东西将会也不一样。这里的映射表,我们叫之为“密钥”。

3.2 小结

通过base64算法可以看出,一个加密算法会有两部分组成:

  • 1)密钥;
  • 2)算法。

两者不能都公开,都公开的话,就可以被人逆向运算,进行解密。

一般的:我们将密钥进行保密,将算法进行公开。算法的公开,有利于算法的推广,普及,更有利于寻找算法中的漏洞。也就是因为base64同时公开了算法、密钥,所以我们说他并不是真正的加密算法。当然如果你调整了上面映射表,那么也能做到加密算法的目的,不过base64加密的强度比较差,所以不建议在实际应用中作为加密算法使用。

4、摘要算法介绍

4.1 基本

我们在平时的工作中经常听到MD5算法。比如在一些下载页面里会给出一个md5的作为文件验证串,在迅雷下载中作为文件的唯一标识。

这类算法严格上来说也不是加密算法,是一种叫做摘要算法的算法,不过在平时的使用中,我们经常将摘要算法混合使用,所以在广义上来说也可以将他叫为加密算法。

4.2 摘要长度

摘要算法的特点是可以将任意长度的字符串,给转换为定长的字符串。

可以意料的是,在这个转换过程中,一定是一共单向的过程。打个比方,我们将一个256长度的字符串转换为128长度的字符串,转换前有N^256种可能,转换后有N^128种可能,这一定不可能是1对1的对应关系。

所以我们只要保证摘要串(转换后的串)位数只够的长,使得“给定一个字符串A,经过摘要算法处理后的串B,很难找到一个字符串C,其摘要后的串和串B相同” 即可。所以目前主流的摘要算法MD/SHA的摘要串长度都在128位以上。而正是出于这个原因,美国还对长摘要串的加密算法进行了出口的限制。

4.3 通讯模型

摘要算法在平时的使用中,经常以如下的形式进行:

假设客户端需要传输一段信息data给服务器端,为了data在网络中数据的完整性,或者说防止信息data被恶意的用户篡改,可以始终这种安全通信模型:客户端与服务器端实现确定了加密密钥key,一段任意的字符串,客户端将key与数据data拼接在一起,进行摘要得到摘要串C,将data、C传给服务器端,服务器端得到data和C后,同样使用与客户端相同的方法,计算摘要串S,如果S等于C的话,就说明A在传输中,没有被人篡改。

流程如下图:

3

对于我们在通信的面临的四种威胁,摘要算法是否能防范呢:

  • 1)截获:由于网络中传输的数据依然的明文的,对于攻击者来说暴露无遗,所以摘要算法对于这种威胁,没什么办法。
  • 2)中断:摘要算法,是对数据的验证,对整个网络的可用性方面的攻击,无法防范。
  • 3)篡改:客户端发出的数据,中途被攻击者进行了修改,由于攻击者并不知道密钥key,将无法生成正确的摘要串。所以,摘要算法可以防范篡改威胁。
  • 4)伪造:攻击者伪造成客户端,给服务器端发数据,但由于拿不到密钥key,伪造不出摘要串。所以,在这种情况下,摘要算法是有一定的防范作用的。但是,在伪造威胁中,还有一种是重放攻击,攻击者事先将客户端发给服务器端的包截下来,然后重复发送。例如:客户端发给服务器端密码时,被攻击者记录了下来,当下次,服务器端再向客户端询问密码时,攻击者只需将记录下来的包发给服务器端即可。所以摘要算法对于伪造威胁的防范是不彻底的,其只可以辨别伪造的内容,不能辨别伪造的发送方。
4

常见的摘要算法有MD5/MD4/SHA-1/SHA-2等,其摘要串长度也不尽相同。现在MD4/MD5/SHA-1等一些摘要串长度128比特的摘要算法已不再安全,山东大学的王小云教授已经证明MD4/MD5/SHA-1已经可以快速生成“碰撞”。所以在真正的对安全性要求极高的场所还是使用长摘要串的摘要算法来的靠谱一些。

5

5、对称加密算法介绍

5.1 基本

理论上说对称加密算法,才是我们真正说的加密算法。

所谓对称加密算法,通俗的讲,就是使用密钥加密,再使用密钥解密的加密算法的总称。也就是平时我们说到加密算法,脑子里第一个跳出来的加密方式一般都是对称加密算法。上面将的base64其实也是一种“对称加密算法”,只是其密钥公开了而已。

5.2 通讯模型

同样的场景:客户端要将数据data发给服务器端。客户端对使用密钥key,对数据data加密,生成加密串C,通过网络将C传输为服务器端,服务器端,使用密钥key对C解密,获取数据data,做自己的业务逻辑。

6

简单直接的一种加密方式,与摘要算法不同的地方是,加密过程其是双向的,C由data加密而来,同样可以解密获得data,前提条件是加密解密时的key相同。而摘要算法无法从C解密得到data。

加密过程简单,那么其在对抗通信中面临的四种威胁的作用有怎么样呢:

  • 1)截获:这么在网络中传输的内容为密文,即使攻击者截获了报文,由于没有密钥,也无法解析。所以,这次对称加密算法在防范截获威胁方面有这很大的优势;
  • 2)中断:和摘要算法一样,无法防范;
  • 3)篡改:由于数据是密文传输的,攻击者,无法解析,更无法伪造了。所以,可以防范;
  • 4)伪造:对于数据的伪造,和摘要算法一样,可以防范,但对于伪造的发送方,对称加密算法和摘要算法一样,比较的无力。
7

5.3 算法优缺点

对称加密算法有着很多的好处,比较加密速度快,算法简单,安全模型的安全性较高等,但在正式中使用时,却不得不解决一个问题:密钥如何传递。如果将密钥在网络中传递,势必有被截获的风险。由于这个问题的存在,导致单纯的使用对称加密算法的通讯模型,并不是一个通用的模型,只在一些特殊的场合中使用,例如:客户端/服务器端为同一端点,或者线下合作的场景——双方将密钥写入合同中,线下传递。

不过对于密钥,还是建议经常的更换,密钥的po解是一个耗时的过程,长时间不变的密钥,无遗对攻击者创造了po解的机会,当有一天攻击者po解了密钥,灭顶之灾也就来到。

说了这么多的对称加密算法,还没有说对称加密算法有哪些,比较常用的对称加密算法有DES/3DES/AES/IDEA/RC4/RC2等。其加密强度,可以从其支持的密钥长度看出,密钥越长,加密强度越好;同时,加密过程越慢。

8

6、非对称加密算法介绍

6.1 基本

对称加密算法指加密解密用同一密钥,那么非对称加密就是加密解密用不同的密钥。

加密算法一次生成两个密钥,一个叫做公钥,一个较为密钥。公钥加密的数据,用密钥解密;密钥加密的数据,用公钥来解密(有些非对称加密算法,只能用密钥加密,公钥解密,或只能用密钥加密,公钥解密)。

非对称加密算法的确神奇,其理论的基础来自于数论。例如RSA算法建立在数论中的“大数分解和素数检测”的理论基础上。而ElGamal和ECC算法基于的则是数论中的“离散对数问题”。数学中的最后一个未找到应用场景的分支学科——数论,终于在加密学领域,找到了应用场景,这不得不说是个奇迹。

非对称加密算法的加入,使得加密算法得以真正的完整,他有这举足轻重的作用。他很好的解决了对称加密算法的缺陷。

6.2 通讯模型

客户端要将数据data发送给服务器端,客户端向服务器端发起对话请求,服务器端生成一对密钥——公钥Gkey和私钥Skey。将Gkey发送给客户端,客户端使用Gkey对数据data进行加密,获得密文C,将C发给服务器端,服务器端使用自己的Skey解密,获得数据data,完成后续业务逻辑。

9

从上面的通讯模型中可以看到,在网络中传输的只有密文C、和公钥Gkey。而私钥Skey不会在网络中传输,攻击者只能获取到公钥,无法对解密密文C,也就保证了数据的安全性。

详细的分析下通讯中面临的四种威胁:

  • 1)截获:同样网络中传输的是密文,即时被截获,攻击者没有私钥,也无法解析密文。所以可以很好的防范截获威胁;
  • 2)中断:对于针对可用性的攻击,由于一般都是基于底层协议的攻击,所以一般很难防范;
  • 3)篡改:由于数据是密文传输的,攻击者没有私钥,无法解析,更无法伪造了;
  • 4)伪造:对于数据的伪造,和摘要算法一样,可以防范,但对于伪造的发送方,对称加密算法和摘要算法一样,比较的无力。
10

和对称加密算法一样,只能对通信中的截获、篡改有防范作用,对其他两个中断、伪造威胁都无法防范。而由于非对称加密算法,很好的解决了对称加密算法中密钥交换的问题,所以其有着很不错的应用场景,可以说是一种通用的加密模型。

6.3 算法优缺点

那么非对称加密算法就没有缺点吗?

也不是。首先,我们看上面的通讯模型,他比对称加密算法的通讯模型来的复杂,存在着两次请求/响应。此外,非对称加密算法的计算可能会很慢,比对称加密算法来慢得多。所以,非对称加密算法在解决了对称加密算法的缺陷后,存在着一些性能问题,比较通用的解决办法是将两种加密算法进行结合——先使用非对称加密算法传递临时的对称加密算法的密钥,密钥传递完成后,再使用更快的对称加密算法来进行真正的数据通信。

典型的非对称加密算法有RSA/ElGamal/ECC算法,除了这两个算法外,还有一个DH算法,其比较的另类,其设计的初衷就是解决对称加密算法中密钥安全交换的问题。

其通讯模型如下:

所有客户端生成一堆公钥CGkey和私钥CSkey,将AGkey发给服务器端。服务器端通过AGkey生成服务器端的公钥SGkey和私钥SSkey,并将SGkey发还给客户端。客户端通过CSkey与SGkey生成对称加密算法的密钥key,服务器端通过CGkey和SSkey生成相同的密钥key。后续客户端和服务器端都是用各自的密钥key来通信。

11

不得不说,这又是一个多么神奇的算法。但是他的确存在。并且早于其他的非对称加密算法。

7、数字签名介绍

7.1 基本

以上三种算法都有防篡改的功能,但摘要算法、和对称加密算法若要防篡改,则需要交换密钥,这又是一件麻烦事儿。所以一般在单纯的防篡改的需求上,都是使用非对称加密算法。但若是对整个明文进行加密的话,加密过程势必消耗大量时间,所以就诞生了数字签名。

数字签名,本质上就是非对称加密算法,但出于解密运行效率的考虑,并是不对明文进行加密,而是对明文的摘要加密,生成“数字串”,并将“数字串”附在明文之后。

数字签名实际上是非对称加密算法的一个妥协方案,为了提高加解密的效率,舍弃了非对称加密算法对截获威胁的优势。

7.2 通讯模型

先来看非对称加密算法的第一种通讯模型,由客户端生成一堆密钥——公钥Gkey和私钥Skey,并使用Skey对明文data进行加密,获得密文C。将C与Gkey发送给服务器端,服务器端使用Gkey对C进行解密。

12

这种通讯模型,只需要一次请求/响应过程,但却无法防范截获威胁,由于最后的密文C的解密用的是公钥Gkey,而Gkey在通过网络传递,所以攻击者可以很方便的对数据进行截获、解密,获得明文data。但这种通讯模型,对于数字签名的场景正合适,数字签名的场景并不准备防范“截获”威胁。

那么下面来看下完整的数字签名的通讯模型:服务器端生成一堆密钥,公钥Gkey和私钥Skey,在将明文data进行摘要,获得摘要串Z1,使用私钥对Z1加密,获得密文C,将C,data,Gkey发给服务器端,服务器端使用Gkey解密后获得Z1,重新根据data计算出摘要Z2,通过比较Z1是否等于Z2来判断数据是否被篡改。

13

以上的模型主要由两个步骤组成,摘要与非对称加密算法的应用。

平常我们经常用到的签名算法,也是这两种算法的组合,比如:

  • 1)SHA1wthRSA,使用SHA1来做摘要,RSA做未对称加密;
  • 2)MD5withRSA,使用MD5做摘要算法,RSA做未对称加密;
  • 3)SHA1withDSA,DSA是ElGamal算法的一种改进。

8、数字证书介绍

8.1 基本

上面说了这么多算法,又是摘要算法,又是对称加密算法,又是非对称加密算法的。但是对于通讯中的四种威胁——截获、中断、篡改、伪造最多也就只能解决其中的两个,对于中断、和伪造威胁,只能干瞪眼。难道,就没有其他办法了吗。

对于中断,一般是网络拓扑或协议级别要解决的问题,已经超出了我们的范畴,暂时不表,我们只能做到的是当网络不可用时,传输的数据出现丢包或异常时可以进行及时的建设,这里就需要用到数据完整性的验证了。

至于,要对付攻击者“伪造”的威胁,这不仅仅是单一算法层面可以解决的问题了。

8.2 通讯模型

正如上面几节所说,伪造分为两种,一种是数据伪造,只要做好防篡改的工作,数据伪造都可以很好的防范。另外一种是伪装成某一网站,与用户进行交互,盗取用户的一些信。比较常见的如钓yu网站、黑代理服务器等。

哪非对称加密算法的通讯模型来举个例子。客户端A在获得给自己公钥时,并没有怀疑与公钥发出方的身份,客户端A以为发给他的依然B,实际上,B发出的公钥已经被攻击者C拦截并丢弃了,C重新生成公钥伪装为B发给了客户端,后续的流程实际上都是攻击者C在于客户端A通讯,而客户端A则以为与自己通讯的是服务器B。

14

这个伪造的过程在平时我们的生活中也经常会碰见,比如:在实名制以前,张三买到火车票后,半路被人da劫,车票被抢。这就有点类似于遭遇了攻击者的攻击,攻击者抢走了张三的火车票(公钥Gkey),并伪造了一张可以以将乱真的车票,(重新生成公钥Gkey)使用这张车票上火车。整个过程看似天衣无缝,攻击者获得了一张免费的车票,张三损失了一张火车票。

当然,现在这种火车票qiang劫的事件已经不太会发生了,因为已经实行了实名制。实名制的引入,给我们解决上面的“伪造”威胁提供了一个方案。火车票实名制,使用了身份证作为验证用户身份的一个证明。那么我们在网络通讯中是否也可以引入这么个“网站身份证”呢。回答是肯定的,目前也正是这么做的,我们叫他“数字证书”。

8.3 CA

正如我们身份证是由可信任的gong an 局办发。数字证书也是由权威机构签发,我们叫做CA,CA会保证证书的确是发给了应该得到该证书的的人。CA也属于一个机构,他也有被人伪造的风险。所以CA一般是分级的,顶层的叫做RootCA,由他保证下面的CA的身份。

所以我们的机器里,保存着有限的几个RootCA的机构的公钥。打个比方,张三有个数字证书,是由A这个CA机构颁发的,A的身份由RootCA来保证。当浏览器与张三的网站进行通讯时,获取到了张三的数字证书,实际上这个数字证书是个嵌套的证书,里面包含着两个子证书:RootCA颁发给A的证书,和A颁发给张三网站的证书。在浏览器中保存着有限个着RootCA的公钥。使用RootCa的公钥对A证书进行验证,验证通过,使用A证书里的公钥对张三网站的证书进行验证,只有再次验证通过后,才能说张三网站的证书得到了确认。

整个验证过程是一个信任链。

15

数字证书里主要包含着两样东西:数字证书所有者的身份信息,数字证书所有者的公钥。为了保证证书在网络中通信不被篡改,证书里会带上这些信息的数字签名。那么对数字证书的验证就是对数字签名的验证,这就是上图中每次证书的验证都要使用到公钥的原因了。

9、参考资料

[1] 传输层安全协议SSL/TLS的Java平台实现简介和Demo演示

[2] 理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)

[3] 微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解

[4] 来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享

[5] 简述实时音视频聊天中端到端加密(E2EE)的工作原理

[6] 移动端安全通信的利器——端到端加密(E2EE)技术详解

[7] Web端即时通讯安全:跨站点WebSocket劫持漏洞详解(含示例代码)

[8] 通俗易懂:一篇掌握即时通讯的消息传输安全原理

[9] IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token

[10] 快速读懂量子通信、量子加密技术

[11] 一分钟理解 HTTPS 到底解决了什么问题

[12] 一篇读懂HTTPS:加密原理、安全逻辑、数字证书等

[13] 基于Netty的IM聊天加密技术学习:一文理清常见的加密概念、术语等

[14] 手把手教你为基于Netty的IM生成自签名SSL/TLS证书

[15] 微信技术分享:揭秘微信后台安全特征数据仓库的架构设计

[16] 即时通讯初学者必知必会的20个网络编程和通信安全知识点

[17] 零基础IM开发入门(五):什么是IM系统的端到端加密?

10、IM安全系列文章

本文是IM通讯安全知识系列文章中的第 3 篇,总目录如下:

即时通讯安全篇(一):正确地理解和使用Android端加密算法

即时通讯安全篇(二):探讨组合加密算法在IM中的应用

即时通讯安全篇(三):常用加解密算法与通讯安全讲解》(本文)

即时通讯安全篇(四):实例分析Android中密钥硬编码的风险

即时通讯安全篇(五):对称加密技术在Android上的应用实践

即时通讯安全篇(六):非对称加密技术的原理与应用实践

即时通讯安全篇(七):用JWT技术解决IM系统Socket长连接的身份认证痛点

即时通讯安全篇(八):如果这样来理解HTTPS原理,一篇就够了

即时通讯安全篇(九):你知道,HTTPS用的是对称加密还是非对称加密?

即时通讯安全篇(十):为什么要用HTTPS?深入浅出,探密短连接的安全性

即时通讯安全篇(十一):IM聊天系统安全手段之通信连接层加密技术

即时通讯安全篇(十二):IM聊天系统安全手段之传输内容端到端加密技术

即时通讯安全篇(十三):信创必学,一文读懂什么是国密算法

即时通讯安全篇(十四):网络端口的安全防护技术实践

即时通讯安全篇(十五):详解硬编码密码的泄漏风险及其扫描原理和工具


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

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

2025年9月18日

本文由腾讯云架构师技术同盟策划,作者章为忠,原题“如何设计一个企业级消息推送系统架构?”,下文有修订和重新排版。

1、引言

想象一下这样的场景:随着企业规模扩大,业务系统日益增多,而几乎每个系统都包含消息通知的功能模块。此时,各业务系统不得不重复开发消息推送功能,不仅耗费大量人力与时间成本,功能质量也难以统一保障。更麻烦的是,邮件、短信、企业微信等推送渠道各自为战,推送效果参差不齐不说,还让管理工作陷入混乱。加之不同渠道的消息分散在各处,员工稍不留意就可能错过重要通知,影响工作效率与决策及时性。

如果你是技术负责人,该如何搭建一套能解决这些问题的企业级统一消息推送平台?今天我们就从核心挑战出发,拆解一套可落地的统一推送服务架构方案。

1

技术交流:

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

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

2、面临的技术挑战

在动手画图做方案之前,我们必须先明确设计一个消息推送系统面临哪些核心挑战。

这些是架构设计的关键所在:

1)多渠道集成难题:邮件、短信、企业微信等渠道的接口规范和推送逻辑存在较大差异,如何将它们完美集成?这背后需要解决接口适配、协议转换等底层问题。

2)高并发与高性能要求:随着业务的增长或是促销活动期间,消息量可能从日均 10 万飙升至 100 万,系统必须能够扛住高并发,保证 “推得快、不卡顿”,同时要具备足够大的吞吐量和足够低的延迟。

3)可靠性与可用性要求:核心消息(订单提醒、会议通知等)一旦丢失或重复发送都会造成严重问题,因此必须确保100% 送达;系统还需实现 7×24 小时不间断运行,杜绝单点故障。

4)灵活的模板与个性化推送:不同的业务需要配置不同的消息模版(营销活动需要活泼的模板,财务通知则需要严谨的格式);此外,还要能够根据用户偏好进行推送(例如用户只查看企业微信消息),以提高触达效果。

5)易于集成与扩展:各业务系统要能够 “即插即用” 地接入推送服务;而且,未来新增渠道、新业务时,需要确保无需对平台进行大规模修改就能快速支持。

在深入了解当前消息推送工作中存在的各类问题与潜在挑战之后,我们再来梳理一条消息从发送到接收都经历了哪些过程和处理?推送系统在企业整体架构中处于什么位置?请接着往下读。。。

3、系统架构核心流程解析(消息推送的全链路步骤)

2

消息推送从发起至接收的核心流程步骤如下:

第1步:在各应用系统发送通知内容到消息网关;既可以单条推送,也可以支持批量推送;例如常见的订单通知和支付通知。

第2步:接下来,由消息网关转发到消息分发服务,在这一层,将会对消息进行验证、确定好优先级、套用格式模板(这里对应在后台维护一个模板库)和确定发送的时间。

第3步:进入到消息路由,也就是技术上常说的异步消息队列。

第4步:通过各个消息渠道,进行具体的消息发送,如:APP站内通知/邮件通知/短信通知/社交账号通知/办公群通知等。

第5步:通知的发送记录和状态,以及统计分析(例如同一个账号同一天发送多少条)。

第6步:就是整体的推送统计,例如:每周总共发送多少次、触达多少用户、打开阅读量有多少、转化多少,从而不断提升你产品的用户体验。

4、推送系统在全局系统架构中的位置

从架构结构来看,一个复杂业务平台通常涵盖表现层、接入层、应用层、服务层(含中台)及基础层等核心模块。作为业务系统中不可或缺的组成部分,推送服务并不直接面向终端用户,而是支撑各类应用稳定运行的基础性服务。

它在整体架构中的具体位置如下所示:

3

(▲ 图中红色部分为统一消息推送平台)

5、 推送系统整体架构设计

5.1 概述

接下来将正式启动并着手设计一套更为完整、系统且具备可扩展性的统一消息推送架构体系。平台采用「接入层 - 业务层 - 服务层 - 数据存储」的四层架构,通过各层协同实现消息推送的标准化与高效化。

具体架构如下图所示:

4

上图展示了统一推送平台的整体架构。每一层的功能和作用将在下面的小节中分别介绍。

5.2 接入层

作为外部请求进入系统的第一道关口,接入层核心作用是「过滤无效请求,筑牢系统安全防线」。

这一层通过 API 网关集中管理所有推送请求,重点完成三项管控:

1)身份验证:仅授权业务系统凭有效凭证调用,阻断非法访问。

2)权限校验:按规则限定不同系统的推送渠道,比如 A 系统可用短信、B 系统仅开放企业微信,避免越权。

3)流量控制:设置阈值(如单系统每秒最多发 1000 条)实现削峰,防范攻击或突发流量压垮系统。

举例来说:营销系统调用推送接口时,API 网关会先验 token 有效性,确认其有短信和邮件权限后,再限制请求频率,确保消息推送节奏在系统承载范围内,从接入环节保障流程安全稳定。

5.3 业务层

负责解析请求、做核心决策,是业务规则的集中处理中心。

收到请求后,先解析内容:要推给谁?用什么模板?什么时候推?优先级高不高?

比如:收到订单系统「订单支付成功」的推送请求,会先匹配「支付通知」模板,确定接收人,设为消息推送的优先级「高」(必须立即推),再判断发送渠道,调用对应的消息推送服务。

5.4 服务层

集成所有推送渠道,把统一格式的消息「翻译」成各渠道能识别的格式。

核心是「适配器模式」:每个渠道对应一个适配器(如短信适配器、企业微信适配器),适配器负责格式转换和接口调用。

比如:企业微信适配器,会把业务逻辑层生成的消息,按企业微信 API 要求的格式组装(加签名、填应用 ID),再调用企业微信的接口发送。需要接入新渠道时,只需开发一个对应的适配器即可,不用改其他层,扩展性拉满。

5.5 数据存储层

数据存储层主要是对全流程数据、消息进行系统化管理。

即存储原始消息内容、推送参数等业务数据,也记录各环节的处理日志、渠道反馈结果与用户交互行为数据。

通过统一的数据模型与存储规范,为后续的推送效果分析、业务优化与数据追溯提供可靠的数据支撑,形成 “接入 - 处理 - 分发 - 存储” 的闭环管理体系。

6、推送系统技术架构设计

6.1 应用集成架构

业务系统(ERP、OA、CRM、IM聊天、客服系统等)通过接口方式接入统一消息平台,能够接入短信、邮件、站内信、企业微信等多种信息渠道,支持以操作界面形式实现统一消息发送。可通过平台界面,编辑消息内容或引用消息模板,实现信息的多渠道统一发送。

平台应用集成架构如下图所示:

5

6.2 平台技术架构

我们将整个平台系统拆解为多个关键服务模块,比如:

  • 1)消息融合接收服务;
  • 2)消息处理分发服务;
  • 3)消息模版服务;
  • 4)渠道发送服务;
  • 5)后台管理服务等。

这些服务模块全面覆盖从请求接入到消息推送、再到后续分析的全流程。

完整的技术架构图如下:

6

7、 本文小结

企业级统一基础推送服务,是一个通用特性,适用于所有现代分布式应用,无论采用何种编程语言和技术。通过统一推送服务解决分散推送的痛点,避免了开发重复造轮子,消息更精准、渠道更符合偏好、关键消息不丢失、系统不宕机。让消息真正成为业务运转的助力而非负担。

不过在实际落地时,需结合企业规模灵活调整:若企业仅部署少数几个业务系统,单独搭建完整的推送系统反而可能造成资源浪费,此时选择轻量化的集成方案会更具性价比。

8、 参考资料

[1] 极光推送系统大规模高并发架构的技术实践分享

[2] 魅族2500万长连接的实时消息推送架构的技术实践分享

[3] 专访魅族架构师:海量长连接的实时消息推送系统的心得体会

[4] 一个基于长连接的安全可扩展的订阅/推送服务实现思路

[5] 实践分享:如何构建一套高可用的移动端消息推送系统?

[6] Go语言构建千万级在线的高并发消息推送系统实践(来自360公司)

[7] 腾讯信鸽技术分享:百亿级实时消息推送的实战经验

[8] 百万在线的美拍直播弹幕系统的实时推送技术实践之路

[9] 京东京麦商家开放平台的消息推送架构演进之路

[10] 解密“达达-京东到家”的订单即时派发技术原理和实践

[11] 技术干货:从零开始,教你设计一个百万级的消息推送系统

[12] 长连接网关技术专题(四):爱奇艺WebSocket实时推送网关技术实践

[13] 喜马拉雅亿级用户量的离线消息推送系统架构设计实践

[14] 微信直播聊天室单房间1500万在线的消息架构演进之路

[15] 百度直播的海量用户实时消息系统架构演进实践

[16] 消息推送技术干货:美团实时消息推送服务的技术演进之路

[17] 揭秘vivo百亿级厂商消息推送平台的高可用技术实践

[18] 得物从零构建亿级消息推送系统的送达稳定性监控体系技术实践

[19] B站千万级长连接实时消息系统的架构设计与实践

[20] 转转千万级用户量消息推送系统的架构演进之路


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

posted @ 2025-09-18 14:05 Jack Jiang 阅读(62) | 评论 (0)编辑 收藏

2025年9月16日

1、基本介绍

RainbowChat是一套基于开源IM即时通讯聊天框架 MobileIMSDK 的产品级移动端IM系统RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题。RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP两种通信协议的IM产品。与姊妹产品RainbowTalkRainbowChat-Web 技术同源,历经考验。

 详细介绍:http://www.52im.net/thread-19-1-1.html
 版本日志:http://www.52im.net/thread-2735-1-1.html
 运行截图:iOS端全部运行截图 (另:Android端运行截图 点此查看
 下载体验:App Store安装地址 (另:Android端下载体验 点此查看

app_store

2、MobileIMSDK开源工程

2

MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持UDP 、TCP 、WebSocket 三种协议,支持iOS、Android、H5、小程序、Uniapp、标准Java平台,服务端基于Netty编写。

工程同步开源地址:

3、v10.0 版更新内容

此版更新内容更多历史更新日志):

  • 1)[新增] 新增了短信验证码的注册和登录功能;
  • 2)[新增] 新增了“发现”页面;
  • 3)[新增] 增加了聊天界面中未读消息数ui的显示;
  • 4)[bug] 解决了iOS18.5中查看图片会导致APP崩溃的问题;
  • 5)[bug] 解决了两个表情占位符重复的问题;
  • 6)[bug] 解决了某些情况下删除表情导致APP崩溃的问题;
  • 7)[bug] 解决了搜索聊天记录的关键字英文字母时因大小写导致高亮不显示的问题;
  • 8)[bug] 解决了转发消息完成后,总是自动滚动到最后一行的问题;
  • 9)[优化] 现在不能删除首页列表中的“确认提醒”这个item了;
  • 10)[优化] 优化了存在多条置顶消息消息的情况下,没有按置顶时间而是消息时间排序的问题;
  • 11)[优化] 登录和退出登录接口中废弃了osType字段;
  • 12)[优化] 只有好友才能查看对方的注册和登录时间;
  • 13)[优化] 优化了聊天记录分页加载逻辑,在大量消息情况下提升性能;
  • 14)[优化] 优化了极端情况下聊天记录加载时同一秒内收发的消息存在顺序问题;
  • 15)[优化] 群聊中优化了消息发送者昵称的显示;
  • 16)[优化] 优化了在iOS18模拟器上从相册选择图片时相册是空的问题;
  • 17)[优化] 查找好友时不再显示在线状态;
  • 18)[优化] 根据当前主流审美潮流优化了诸多界面的UI细节。

4、部分功能运行截图预览

(☞ 更多截图点此查看 ☜)

4.1 登陆和注册等:6_logins

4.2 首页等主要界面:

7_main_tabs

4.3 “我的”、“个人中心”等页面:

8_my_profiles

4.4 好友关系等:

9_sns

4.5 陌生人聊天:

10_chat_guest

4.6 好友聊天:

11_chat_friend

4.7 世界频道聊天(相当于在线聊天):

12_bbs

4.8 群聊:

13_chat_group

4.9 大文件消息:

14_big_file

4.10 短视频消息:

4.11 名片消息:

16_contact

4.12 位置消息:

17_location

4.13 “扫一扫”功能:

18_scan

4.14 “搜索”功能:

19_search

4.15 “群名片”功能:

20_group_card

4.16 “消息转发”功能:

21_forward

4.17 “消息引用”功能:

24_quote

4.18 “@”功能:

23_at

4.19 “消息撤回”功能:

25_revoke

posted @ 2025-09-16 12:51 Jack Jiang 阅读(47) | 评论 (0)编辑 收藏

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