基于公共信箱的全量消息实现

news2024/11/14 15:03:43

在这里插入图片描述

作者 | 百度消息中台团队

导读

消息中台为百度App以及厂内百度系产品提供即时通讯的能力,提供包括私聊、群聊、聊天室、直播弹幕等用户沟通场景,并帮助业务通过消息推送触达用户。百度App存在需要以『低用户打扰』的形式触达全量用户的场景,而现有基于用户『私有信箱』通知拆分的机制,很难低成本、高时效的满足该场景诉求。基于上述问题,本文介绍了现有消息系统的主要组成,对比多种实现方案的差异,提出以『公有信箱』通知读扩散的方式,低成本、高时效的实现全量用户通知推送。

全文5515字,预计阅读时间14分钟。

01 全量消息提出背景

百度App存在需要触达全量用户的诉求,比如:2022年12月7日解除疫情管控结束后,将经过筛选的官方政策解读、专题汇总、知识科普、实用工具类介绍等信息,通过官方号『百度小助手』下发触达到百度App用户,来有效体现人文关怀,提高用户粘性。

1.1 全量消息诉求

在以消息服务进行全量触达(即全量消息)时,期望能够满足:

图片

在触达范围上,希望尽量扩大用户触达范围,包括百度App月活用户、以及非月活用户但是近期新注册或登录的用户(根据2022年12月对外公开数据,百度App月活6亿+用户);在时效上,一次全量触达,希望短时间内完成(比如小时级、甚至分钟级),抢占时效性;在用户打扰方面,消息触达不能给用户带来较大的打扰,每次消息下发,只触达一次,不能重复打扰用户,但是需要保留回访入口,满足用户二次查看的诉求。

1.2 现有技术痛点

我们现有IM(即时通讯)服务中,每个IM用户对应一个用户信箱。基于现有服务,如果想完成全量用户的消息触达,需要把消息推送到每个用户的信箱。完成6亿+的消息写入(假定每条占用存储4KB,每秒写入2W条消息),在消息写入时效性,以及存储资源消耗上,都是很难接受的。且现有的基于用户私有信箱的方案,在同时支持多条全量消息的场景下,扩展性也较差。

基于上述背景和技术痛点,我们抽象基于公共信箱的全量消息实现:在特定业务场景下通过消息服务,低成本、高时效的给全量用户推送内容一致的通知消息。

02 现有消息系统介绍

在介绍基于公共信箱(信箱的实现方式,该信箱为IM用户公有)的全量消息实现之前,先介绍一下目前消息系统的现状,包括消息系统的组成、通知拉取模式、用户信箱等。

2.1 消息系统组成

普通用户的直观体验上看,一个IM系统可以包括如下几个元素:用户主体、用户账号、账号关系、聊天会话、聊天消息。『用户主体』具有『用户账号』,『用户主体』具有头像、昵称等用户属性,『用户主体』通过『用户账号』登录IM系统,进行聊天;账号之间的关注、屏蔽、免打扰等构成『用户关系』;通过用户之间的互动环节可以产生『聊天消息』;聊天记录构成了一个『聊天会话』。

图片

集成消息服务的业务方角度看,一个IM系统可以包括消息客户端(消息客户端UI组件、消息SDK)和消息服务端。IM消息可以作为一种服务,嵌入到各业务系统中,为业务系统提供『实时交互』能力。业务通过集成IM服务,提升其用户体验。如下为一个集成了IM SDK的业务架构图。业务App集成IM SDK,通过IM SDK与IM Server交互,完成用户上行通讯能力。业务App Server通过与IM Server交互,完成通知下行触达用户。

图片

使用场景来看,消息包括『私信消息』(包括用户上下行消息)、『通知消息』(业务方给用户推送的下行消息)、『群聊』、『聊天室』、『直播间弹幕』等。

2.2 消息的通知拉取模式

IM消息系统,采用**通知拉取(notify-pull)模式来感知新消息、拉取新消息。IM SDK登录时,与IM 服务端建立长连接(LCS, Long Connect Service),用户有新的消息时,通过长连接下发notify,实时通知用户的IM SDK。实时notify不写用户信箱,因为noitfy不是消息,而可以理解为提醒在线用户有新消息的信号,IM SDK根据这个信号,来服务端拉取消息。业务方server或者其他用户给该用户发送消息后,经过IM业务处理模块,把消息写入接收者信箱,IM Server会根据用户的登录和路由信息,给消息接收者(私信场景下也包括『消息发送者』,用于消息的多端同步)发送新消息notify,接收到notify的IM设备,通过IM SDK来IM Server端拉取(pull)**消息。

2.3 用户信箱介绍

为了暂存尚未拉取到IM SDK本地的离线消息,需要对消息进行服务端存储,而消息的离线存储通过消息信箱服务完成。目前IM用户消息信箱主要包括用户私有信箱、群公共信箱(非下文提到的用户公共信箱)、直播间弹幕mcast等。用户信箱通过『消息所属应用』+『IM标识用户的唯一ID』来标识。就一条消息而言,消息参与者有『消息发送者』和『消息接收者』,消息收发双方的信箱都是相互独立的(假设发送方删除了自己信箱的某一条消息,不会影响消息接受者信箱的消息)。对于有查看历史消息诉求的一方来说,消息需要入该方的信箱:比如用户之间的私信(点对点聊天)消息需要入发送者和接收者的信箱,而对于全量通知场景,消息不需要存储发送者信箱,而只需要存接收者的信箱。而用户的信箱排序,是基于信箱Timeline,即消息在信箱内部基于时间线存储,每条消息对应一个unix 微秒时间戳(如第一条消息1679757323320865),用户进行信箱拉取时,基于时间范围正序或者逆序拉取,如下为信箱timeline的示例:

图片
△信箱timeline

用户信箱中的每一条消息记录都包含『消息ID』、『消息用户标识』、『消息通用属性』、『消息业务属性』四个主要部分。消息ID为unix微秒时间戳,不需要全局唯一,只需要特定用户信箱范围内唯一即可。消息用户标识包括from_uid、to_uid、contacter。消息通用属性包括create_time、expire、is_read。消息业务属性包括category、type、priority、business_type、app_id、msgkey、content等。如下为一条消息记录示例:
图片
△消息记录示例

03 全消息实现

3.1 全量消息推送方案分析

目前消息推送机制中,主要支持:单播(消息推送方式,每次给一个用户推送一条消息)、批量单播(每次给小范围用户推送消息,比如30个)、广播(基于关注关系的推送,如给全量粉丝推送),上述三种消息推送机制推送的消息,均需要存储服务端的用户私有信箱。为了完成百度App 6亿+月活用户(月活数据来源:2022年12月百度App公开月活数据, https://baijiahao.baidu.com/s?id=1758522783976467912&wfr=spider&for=pc )的消息推送,有几种可选的方案。

3.1.1 全流程从通知入口推送

①该种方式下,需要获取全量的月活用户列表,经过IM Server推送入口,给每一个用户推送疫情相关通知。该通知写入到用户信箱,若用户在线,在实时拉取该通知;若用户离线,再下次登录IM服务时,拉取离线通知。该种方案下,推送行为会覆盖IM的全流程,推送的通知会进入每个月活用户的私有信箱,服务压力大。其中增量用户不会收到通知推送(这里增量用户指的是不在月活用户列表的用户)。

3.1.2 跳过通知入口直接写信箱

②跳过IM消息推送流程中的中间环节,直接把通知消息写入用户信箱。由于跳过了中间流程,直接写入信箱,通知写入速度主要取决于信箱底层存储的压力承受情况。该种方案下,同①方案一样,无法给用户发送实时通知,依赖用户IM SDK的主动消息拉取(断链后重新登录/新消息提醒拉取),无法给增量用户发送通知。该方案由于跳过中间环节直接写信箱,风险较大,无法直接提供给业务方使用,不建议如此操作。

3.1.3 公有信箱实现机制

③公有信箱机制,把通知消息写入『公共信箱』,在用户消息拉取时,合并『用户私信信箱』+『公共信箱』的消息。

3.1.4 三种方案比较

图片

方案①②都是写扩散方式,基于现有『用户私有信箱』的机制,把通知消息写入每个接收通知的用户私有信箱。方案②与方案①的差别主要是跳过了消息中间流程,可以避免因为中间环节负载瓶颈导致整体消息写入速度过低。方案③是读扩散方式,消息不用再写入接收通知的用户私有信箱,而只需要在公共信箱存储一份,在用户拉取消息时,实时拉取公共信箱的消息。方案③中可以采用内存缓存方案,解决对公共信箱的读压力。本质上来说,方案③与方案①②相比,是用读成本(CPU)换写成本(存储)。

3.2 基于公有信箱的全量消息实现

基于上述方案③的思路,我们进行基于公有信箱的全量消息设计与实现。该种方案中,包含两个主要流程:『全量消息的管理』和『用户私有+公有信箱的拉取』。

3.2.1 全量消息的管理

全量消息管理主要分为运营O端操作平台(复用运营消息平台),以及全量消息处理服务(复用IM服务的连接层、逻辑处理层、信箱代理、信箱处理)。运营O端平台为运营同学提供可视化界面,可以对全量消息进行编辑、预发布、发布、修改、停止、撤回等操作;接入层对接运营O端,进行参数校验、转发IM后端逻辑处理模块;逻辑处理层进行全量消息的创建、修改、停止、删除、撤回等逻辑操作;信箱代理层复用IM服务的信箱CRUD操作;信箱存储层公共信箱的底层存储。

图片
△全量消息管理流程

3.2.1 用户信箱拉取

用户通过IM SDK,以长连接的方式,在逻辑处理层进行消息拉拉取。在用户拉取信箱消息时,需要对『用户个人信箱』和『公有信箱』进行合并。由于每次用户信箱拉取,都需要进行信箱的合并拉取。

公共信箱内存缓存机制

百度App的IM用户,在IM SDK登录时需要拉取信箱中的消息。每次消息拉取时,需要检查公共信箱中是否有消息。因此,公共信箱需要能抗住日常和峰值流量(拉取峰值为4.7Wqps)。为了防止流量击穿,流量打到底层的持久化公共信箱MYSQL存储,我们设计了基于内存的公共信箱缓存机制。同时公共信箱内容变化时,也要实时(或者在能容忍的范围内做到准实时)变更内存缓存信箱中的消息,我们采用Bthread定期轮询持久化公共信箱,更新内存公共信箱,轮询间隔可配置(比如设置1秒)。

分级发布机制

同时,在逻辑层实现白名单机制,支持全量消息在『预发布』状态下,仅对白名单用户可见,从而达到分级验证的效果。白名单的用户列表通过逻辑处理成的配置加载,也支持通过CURL请求动态修改白名单的配置。

图片

3.3 基于公有信箱的全量消息实现需要解决的问题

以公有信箱的方案实现全量消息,需要解决如下问题:

图片

04 全量消息公共信箱实现的优缺点

以公共信箱的方式,实现全量消息分发,具有:**『分发速度快』、『资源成本低』**的特点。

图片

公共信箱的方式也存在一定的局限性:

1、不适用于个性化要求高的场景:由于消息在公共信箱只存储一份,下发消息内容固定,无法很大程度下,下发个性化消息(当然也不是一定无法下发个性化的消息,可以通过在公共信箱存储消息模板,根据拉取消息的用户ID获取个性化信息,在消息拉取时,临时拼装消息,这样就增大了消息拉取时的代价)。

2、不适用于实时消息提醒场景

①从业务场景上看,全量消息优先级低,不需要在全量生效的瞬间让用户感知;

②从实现上看,全量消息实时消息提醒成本高(因为实时消息提醒Notify,需要以类似单播的形式实时通知用户。和单播的区别是,Notify不用触达离线用户,也就是不用写用户信箱,只需实时触达在线用户);

③从系统压力看,全量在线用户均收到实时新消息提醒,会带来信箱拉取请求的瞬时流量(手百IM SDK长连接峰值在线1550W,假定新消息提醒在瞬间下发,同时在线用户信箱拉取请求,会把db打挂的)。

05 全量消息的应用

全量消息目前已经在百度App得到应用,包括:重大通知的下发,百度App功能更新介绍通知,消息的撤回,后续将推广到其他的矩阵App的全量通知推送场景。

22年Q4宣布疫情解封时,利用全量消息推送,低成本、高时效的完成3条『疫情解封专项』全量消息下发。

主题

有效期

到达

个人如何做好预防

12.09-12.13

2亿+

阳了的应对措施

12.16-12.19

2亿+

新冠辟谣&三年抗疫

12.23-12.26

2亿+

备注:三次全量消息下发,到达数据在2亿+,该值小于月活的6亿+,主要因为几个原因:

①本次全量消息有效期仅3天左右,全量消息有效期内登录IM SDK的用户才有机会拉到全量消息;

②本次下发使用了新的消息展示模板,所以限制了拉取全量消息的百度App版本,只有高版本百度App可以拉到;

③本次全量消息,限制了仅有百度App登录用户拉取。

06 展望

前文介绍了现有消息系统,通过公有信箱低成本、高分发速度完成全量消息下发的设计、实现与应用。在全量消息应用方面,除了业务上的使用,后续也可以用于广播消息、批量单播消息的撤回。比如由于误操作发送了广播消息,用户已经把广播消息拉到了端,并持久化到端,这是可以『以全量消息的方式,下发删除指令』,删除已经缓存到端的垃圾消息。

希望,通过消息系统持续不断优化,为更多的业务提供低成本、高稳定性的即时通讯能力。

——END——

推荐阅读:

百度APP iOS端包体积50M优化实践(二) 图片优化

浅论分布式训练中的recompute机制

剖析多利熊业务如何基于分布式架构实践稳定性建设

百度工程师的软件质量与测试随笔

百度APP iOS端包体积50M优化实践(一)总览

基于FFmpeg和Wasm的Web端视频截帧方案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/467417.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AcWing第 96 场周赛

竞赛 - AcWing 一、完美数 4876. 完美数 - AcWing题库 1、题目 如果一个正整数能够被 2520 整除,则称该数为完美数。 给定一个正整数 n,请你计算 [1,n]范围内有多少个完美数。 输入格式 一个整数 n。 输出格式 一个整数,表示 [1,n] 范…

C++:Article : 链接器(三):库与可执行文件的生成

链接器:库与可执行文件 1. 静态库1.1 静态链接下,可执行文件如何生成 2. 动态库2.1 动态库特点以及与静态库使用方式差异2.2 动态库和静态库使用时间 3. load-time dynamic linking(加载时动态链接)3.1:阶段一&#xf…

【工具】FFmpeg|超大视频本地有损压缩,500MB变25MB(支持 Windows、Linux、macOS)

参考: 如何将一分钟长的1080p视频压缩至5MB以内?-知乎-滔滔清风近期HEVC扩展备用安装方法-B站-悲剧天下 总共三个步骤,安装FFmpeg、运行指令、打开视频。 亲测 500MB 变 25MB。 1 安装FFmpeg 对于不需要看教程可以自行完成安装的同学们&am…

MySQL基础案例——数据表的基本操作:创建表和修改表

目录 案例目的: 创建表: 创建offices: 创建employees表: 修改表: 将 employees 的 mobile 字段移动到 officeCode 字段后: 将 birth 字段名称改为 employee_birth: 修改 sex 字段,数据类…

TryHackMe-Looking Glass(boot2root)

Looking Glass 穿过镜子。仙境挑战室的续集。 端口扫描 循例nmap 又是一堆ssh,跟之前的玩法一样 找到正确的ssh端口之后后给了一段密文,要求输入secret才能进入ssh 这看起来非常像凯撒密码 唯一可识别的信息是Jabberwocky,我们找到了它 它…

IDA简单使用

今天来简单介绍一下逆向中常用到的另一个静态分析工具IDA,还是昨天那个打印demo(64位): #include #include char a[] "https://www.vultop.com/"; int main(int argc, char* argv[]) { printf("%s", a)…

什么是微服务

目录 一、微服务介绍 1. 什么是微服务 2. 微服务由来 3. 为什么需要微服务? 3.1 最期的单体架构带来的问题 3.2 微服务与单体架构区别 3.3 微服务与SOA区别 4. 微服务本质 5. 什么样的项目适合微服务 6. 微服务折分与设计 6.1 微服务设计原则 7. 微服务…

linux gcc + openocd + stlink + cubeMX + cortex Debug

文章目录 运行环境:1.1 gcc1)下载并解压gcc2)环境配置 2.1 openocd1)下载并解压openocd2)环境配置(没有权限就加sudo) 3.1 stlink1)下载并双击安装stlink 4.1 cubeMX1)下载并解压cubeMX2)生成makefile工程 5.1 cortex Debug1)setting设置2)la…

冷链物流运转 3D 可视化监控,助力大数据实时监控

智慧物流是以信息化为依托并广泛应用物联网、人工智能、大数据、云计算等技术工具,在物流价值链上的 6 项基本环节(运输、仓储、包装、装卸搬运、流通加工、配送)实现系统感知和数据采集的现代综合智能型物流系统。随着冷链信息化、数字化发展…

史上最全! 瑞芯微RK3568核心板评估板资源分享!

▎瑞芯微RK3568芯片 高性能处理器:采用四核A55架构CPU,G52 GPU;内置NPU,可提供1T算力 高可靠性设计:支持DDR及CPU Cache全链路ECC 内置自研ISP图像处理器:8M30fps处理能力,强大的HDR功能&#…

Springboot Netty 实现自定义协议

Netty是由JBOSS提供的一个java开源框架,现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。 也就是说,Netty 是一个基于NIO的客户、服务器端的编程框架&…

《编程思维与实践》1039.字符组合

《编程思维与实践》1039.字符组合 题目 思路 先将字符串去重排序(保证每个组合中的字符按字典序),然后枚举出所有组合的情形,最后再进行字典序排序即可. 其中字符串的去重排序可以利用ASCII码值进行桶排序,关键在于如何枚举所有组合的情形. 每个位置有两种可能(选或不选),但至…

MongoDB 聚合管道的输出结果到集合($out)及合并结果到集合($merge)

上一篇文章,我们介绍了使用聚合管道完成文档之间的关联查询、以及如果将两个管道中的文档进行合并,如果需要进一步了解可以参考:MongoDB 聚合管道的文档关联查询($lookup)及管道合并($unionWith)https://blog.csdn.net/m1729339749/article/d…

ES索引管理

ES官方博客:https://elasticstack.blog.csdn.net/?typeblog 一、rolloverAPI https://elasticstack.blog.csdn.net/article/details/102728987 1.1 rollover命令 POST /log_alias/_rollover { "conditions":{ "max_age":"…

Node 09 MongoDB的使用

MongoDB 简介 Mongodb 是什么 MongoDB 是一个基于分布式文件存储的数据库,官方地址 https://www.mongodb.com/ 数据库是什么 数据库(DataBase)是按照数据结构来组织、存储和管理数据的 应用程序 数据库的作用 数据库的主要作用就是 管理…

jsp家庭农场投入品信息管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 jsp家庭农场投入品信息管理系统是一套完善的java web信息管理系统 serlvet dao bean 开发,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发…

如何理解PCB布线3W规则

我们平时在PCB布线的时候,对于比较重要的信号都要做特殊处理,比如包地或者时“3W”,所谓3w指的是线与线之间的间距要满足三倍的线宽,那么我们怎么理解这个3W原则呢,他是如何降低信号之间的串扰的呢? 我们要…

连网介质及设备详解

文章目录 一、网卡1. 有线网卡2. 无线网卡3. 光纤网卡 二、网线1. 双绞线2. 光缆 三、交换机1. 什么是交换机2. 交换机分类 一、网卡 网卡分为三类:有线网卡、无线网卡、光纤网卡 1. 有线网卡 多数台式计算机自带,采用 RJ-45 制式接口 通过双绞线传输…

Hive2安装Tez计算引擎

一、Tez介绍 ApacheTEZ项目旨在构建一个应用程序框架,该框架允许使用复杂的有向无环图来处理数据。 它当前构建在Apache Hadoop YARN之上。 Tez的2个主要设计主题是: 通过以下方式增强最终用户的能力: 富有表现力的数据流定义API 灵活的输入…

ICV:车载毫米波雷达中国市场有望在2025年实现30亿美元的市场规模

近日,专注于前沿科技领域的国际咨询机构ICV发布了全球车载毫米波雷达的市场研究报告,汽车毫米波(mmWave)雷达基于频率为77 GHz的电磁波,具有高精度和准确性,可用于目标检测。这种技术有着广泛的应用&#x…