Jack Jiang

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

2022年5月5日

本文由作者jhon_11分享,有大量修订和改动。

1、引言

如何设计一款高性能、高并发、高可用的im综合消息平台是很多公司发展过程中会碰到且必须要解决的问题。比如一家公司内部的通讯系统、各个互联网平台的客服咨询系统,都是离不开一款好用且维护的方便im综合消息系统。

那么,我们应该怎么样来设计一款三高特性的im系统,并能同时支持各个业务线的接入(比如:内部OA通讯、客服咨询、消息推送等等功能)有呢?

下面就由我来介绍一下我所负责的公司IM综合消息系统所经历的架构设计历程,以及架构设计过程中的一些思路和总结,希望能给你带来启发。

学习交流:

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

2、初版IM架构

2.1 概述

im第一版设计的初衷是公司需要一款im消息中间件用于支撑客服咨询业务。

但是,考虑到为了方便日后其他业务线也能接入消息沟通平台,所以一开始就将整个消息中心的能力需求给到中间件团队进行开发,以便除客服外的各业务线接入综合消息中心,从而实现多元的消息实时触达能力。

2.2 初版架构介绍

初版架构图如下图所示:

针对上面的架构图,我们逐个解释一下各模块的作用。

1)存储端:

在初版的架构下,存储端我们使用tidb、redis作为主要存储:

  • [1] redis用于存储消息已读未读,缓存连接信息等功能;
  • [2] tidb作为开源的分布式数据库,选择它是为了方便消息的存储。

2)mq消息总线:

我们使用rocketmq来实现消息总线(PS:即分布式情况下,不同im实例间通过MQ进行消息交互)。

消息总线是整个im的核心,使用rocketmq能支持十万级别的tps。基本所有服务都要从消息总线中消费消息进行业务处理。

3)zookeeper注册中心:各个服务会注册到zk中,方便服务之间内部进行调用,同样也可以暴露服务给外部进行调用。

4)link服务:

link服务主要用于接收客户端的ws(WebSocket协议)、tcp、udp等协议的连接。

同时调用用户服务进行认证,并投递连接成功的消息给位置服务进行消费,存储连接信息。

ws(WebSocket协议)过来的消息先到link再投递到消息总线。

5)消息分发服务:

消息分发服务主要用于接收消息总线推过来的消息进行处理,按照im内部消息协议构造好消息体后,又推送到消息总线中(比如会推给会话服务、消息盒子、link服务)。

6)位置服务:

存储link的(WebSocket协议)连接、tcp连接等信息,并使用redis进行缓存(key为userId),方便根据UserId查询到该用户所登录的客户端连接在哪个link上。

一个用户在相同设备只能登录一个,但可以支持多端登录。

7)用户服务:用于存储所有用户,提供认证查询接口。

8)消息盒子:存储所有消息,提供消息查询、消息已读未读、消息未读数、消息检索等功能。

9)会话服务:管理会话、群聊会话、单聊会话等功能。

2.3 整体时序图

整体架构的时序图如下:

3、初版IM架构存在的问题及思考

在上节的架构设计介绍中,我们详细分享了初版IM系统架构的设计思路以及具体流程。

那么在初版IM架构设计中还存在什么样的问题,又该如何优化呢?我们一条条来看看。

3.1 使用MQ消息总线的问题

正如上节所分享的那样,我们初版IM架构中,link服务到消息分发服务的消息使用的MQ消息总线。

初版架构设计中,link服务将消息下推给消息分发服务进行处理时,使用的是mq消息总线(通俗了说,IM集群内不同IM实例间的通信是依赖于MQ进行的消息传递),而mq消息总线必然做对有一定的时延(而且时延受制于MQ本身的系统实现和技术策略)。

举个例子:

当两个处于不同IM实例的客户端A和B聊天时,A用户发送消息到link --> 消息总线 --> 消息分发服务 --> 消息总线 --> link --> B用户。

正如上面这个例子,im消息投递流程太长了,并且这样也会大大降低系统的吞吐量。

3.2 消息落库为写扩散的问题

其实现阶段我们使用的是跟微信一样的写扩散策略(详见《企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等》)。

那么为啥微信使用写扩散不是缺陷,而对于我们的IM架构来说确是缺陷呢?

微信的技术特性:

  • 1)微信号称没有存储用户的聊天记录,全是实时推送;
  • 2)微信聊天记录全部会在我们手机端存储一份,两台手机终端上的聊天记录并不互通,并且互不可见。

我们的IM综合消息中心技术特性:

  • 1)综合消息中心是会有拉取历史聊天记录(服务端拉取)的功能,存储了全量消息;
  • 2)综合消息中心的客户端,需要支持网页版本。

综上所述:

  • 1)写扩散对微信这样有移动端的富客户端版本的即时通讯产品十分友好,每个消息在消息分发的时候给处于这个会话(单聊,群聊)下的所有用户所在客户端先推送消息,没找到连接就针对这个用户写一个离线缓存消息,那么下次该用户登录进来,可以从缓存中拉取到该消息,并且清掉缓存;
  • 2)写扩散对于我们这类通用综合消息平台并不友好,由于接入方大部分是网页版的客户端,所以没有缓存消息的能力,浏览器刷新就没有了任何消息,所以需要实时去服务端拉取历史消息。假设我是写扩散,在一个群聊中有五百个用户,针对这五百个用户在这个会话,我需要去写五百条消息,大大的增加了写io,并且还不能写缓存(得写数据库)。

3.3 tidb存在不稳定性和事务并发的问题

tidb是目前主流的开源分布式数据库,查询效率高、无需分库分表。

但同样的,tidb存在一些隐藏的问题:

  • 1)tidb在高并发情况下,并发事务会导致事务失败,具体原因不知;
  • 2)tidb排错成本高,公司很少有tidb专业运维,经常遇到不走索引的情况。

3.4 群聊、单聊冗余在同一个服务的问题

在我们初版的IM架构设计中,单聊和群聊是冗余在会话服务中的,并且冗余在同一张表的。

其实单聊、群聊从数据角度来说,还是会有些不同(比如业务属性)虽然都是会话,我们还是需要将这两个服务拆分开,细粒度的服务拆分能更好的把控整体的逻辑。

4、升级版IM架构

4.1 初始架构问题

正如前面两节分享的那样,渐渐的我们发现初版im架构有很大的不足之处。

在生产上暴露出了以下问题:

  • 1)tps没达到预期,吞吐量不能满足公司业务的发展;
  • 2)使用的存储中间件难以维护(主要是tidb),试错成本高,经常在生产暴露问题,并且速度越来越慢;
  • 3)消息写扩散没有太大必要,并大大增加了系统io次数(原因见上一节);
  • 4)一些特性无法支持,比如消息图文检索,消息已读未读。

4.2 升级版im架构介绍

本次升级后的im架构如下图所示:

如上图所示,改版后的各模块情况如下:

  • 1)存储端:存储端我们改用了mysql,针对消息服务单独使用了主从mysql集群(主节点用于写消息、从节点用于消息检索)——;
  • 2)mq消息总线:与第一版相比没有改动;
  • 3)link服务:与第一版相比,改动了link服务到消息分发服务的消息推送方式(由MQ总线方式变更为tcp实时推送);
  • 4)消息分发服务:集成了消息处理能力、路由能力,每台消息分发服务拥有所有link服务的tcp连接;
  • 5)单聊服务:负责单聊会话的管理能力;
  • 6)群聊服务:负责群聊会话的管理能力;
  • 7)用户服务:提供用户认证,登录\注册能力。

5、详细对比针对初版IM架构的改动

升级版的IM架构,对比初始初始,具体主要是下面这些改动。

5.1 改进了不同im实例间的消息分发方式

针对初版MQ消息总结的问题,升级版架构中,我们将link到消息分发服务改为tcp实时连接,百万客户端连接同一台link机器,消息实时触达能力tps达到16万。

link到消息分发服务的改版是本次设计的亮点之一,完全消除了mq推送的时延性,并且路由简单,几乎实时触达。

举个例子:当两个处于不同IM实例的客户端A和B聊天时

  • 1)初版架构中是:A用户发送消息到link --> 消息总线 --> 消息分发服务 --> 消息总线 --> link --> B用户;
  • 2)升级版架构是:用户A --> link --> 消息分发 --> link --> 用户B。

而且:link服务到消息分发服务集群的消息推送使用轮询负载均衡的方式,保证公平,不会导致个别机器负载过高。

5.2 取消了位置服务

取消了位置服务(这里的位置不是指的IM消息里的地理位置消息哦),消息分发服务集成位置服务的能力。

消息分发服务本身业务简单,不需要再单独划分位置服务,因为会增加网络io,并且消息分发服务直连link,而让它负责路由则更加方便。

5.3 存储由tidb改成了mysql

存储端由tidb改成了mysql,增强了可维护性,消息服务使用mysql主从读写分离方式,提高了消息落库速度与检索速度的同时,也减轻数据库压力。

前面有提到过使用tidb这样维护成本高,排查问题难的分布式数据库是一件很痛苦的事情。

而我们使用mysql更加稳定,大家对mysql的学习成本相对较低。针对消息服务使用读写分离的方式,能大大提高消息的吞吐量。

5.4 实现了初版无法实现的特性功能

升级版架构中,我们实现了初版无法实现的特性功能,比如消息已读未读、红包推送、商品链接推送等功能。

新版综合消息中心加入了消息已读未读、发送红包、链接推送等功能,但这些功能带有一定的业务特性,毕竟不是所有Im都需要,可通过配置取消这些功能。

5.5 消息由写扩散改为读扩散

升级版IM架构中,消息存储由写扩散改为了读扩散。

前面我们有提到写扩散和读扩散的利弊,对于网页端IM我们更适合使用读扩散,只需要落一条消息,大大提高消息服务的吞吐量.

5.6 增加了门面服务

升级版IM架构中,我们增加门面服务 im-logic,用于暴露给第三方业务线接口调用。

初版架构中,都是im的各个服务各自暴露接口给到外部进行调用, 而升级版架中我们统一使用logic服务暴露给外部调用。

在logic服务针对调用可以做一些处理,这样不会影响到整体im的通用,不会增加im底层代码的复杂度,从而将业务逻辑与底层进行解耦。

6、优化后的效果对比

针对升级版和初版IM架构,我们也做了一些对比测试,具体的测试过程就是详细展开了。

以下是测试结果:

7、业务线接入im综合消息系统的业务划分思考

7.1 到底该如何设计高性能通用im综合消息系统

关于业务线接入im综合消息系统的业务划分,我也做了一些总结和思考,为了更形象和易于理解,我这里以客服系统以及企业微信为例来进行分析。

假如我开发了一款通用的im综合消息系统,现在有很多业务方需要接入我们,我们该如何进行业务域的清晰划分就显得尤为重要,需要在妥协与不妥协中进行平衡。

就像当前市面上开源的im消息平台来说,存在的问题主要是:要么是集成了很多的业务逻辑,要么就只是一款单纯的客服系统,再或者就是一款IM好友聊天系统,中间的业务划分并不明确。当然,这也有好处,拿来就能用,并不需要进行二次业务封装。

那么,到底如何将im设计为一款真正的高性能通用im综合消息系统呢?

通用的综合消息消息平台只需要有通用的底层能力:

以下案例假设在我已经按照上述架构设计了一版im综合消息中心。

7.2 以客服系统为例

客服系统:

客服系统不光需要实现自身业务,还需要整合im的消息能力(消费im的消息),来进行场景分析,实现会话变更、信令消息推送等逻辑。

客服系统内部需要根据im的底层支持能力进行相应的业务封装以及客服系统的客服用户池,c端用户池如何初始化到im的用户中心这些问题都是需要考虑进去的。

7.3 内部OA通信为例

内部OA通信:

 

员工内部OA通信系统需要集成IM好友功能,需要根据im的用户中心封装组织架构,用户权限等功能。

同时,内部通信系统需要根据im实现消息已读未读,群聊列表,会话列表拉取等功能。

8、本文小结

im的综合消息平台是一款需要高度结合业务的中间件系统,它直接与业务打交道,跟普通的中间件有根本的区别。

一款好用的im综合消息平台,直接取决于你的通用性,可扩展性以及系统吞吐能力。

希望这篇文章所分享的内容,能对大家开发im时候的思路有所启迪。

9、参考资料

[1] 从零到卓越:京东客服即时通讯系统的技术架构演进历程

[2] 从游击队到正规军(一):马蜂窝旅游网的IM系统架构演进之路

[3] 瓜子IM智能客服系统的数据架构设计(整理自现场演讲,有配套PPT)

[4] 阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处

[5] 新手入门一篇就够:从零开发移动端IM

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

[7] 基于实践:一套百万消息量小规模IM系统技术要点总结

[8] 一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等

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

[10] 从新手到专家:如何设计一套亿级消息量的分布式IM系统

[11] 企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等

[12] 阿里IM技术分享(三):闲鱼亿级IM消息系统的架构演进之路

[13] 一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践

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

posted @ 2022-06-28 10:40 Jack Jiang 阅读(41) | 评论 (0)编辑 收藏

关于MobileIMSDK

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

工程开源地址是:

关于RainbowChat

► 详细产品介绍:http://www.52im.net/thread-19-1-1.html
► 版本更新记录:http://www.52im.net/thread-1217-1-1.html
► 全部运行截图:Android端iOS端
► 在线体验下载:专业版(TCP协议)专业版(UDP协议)      (关于 iOS 端,请:点此查看

 

RainbowChat是一套基于开源IM聊天框架 MobileIMSDK 的产品级移动端IM系统。RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题(可自行下载体验:专业版下载安装)。

* RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP两种通信协议的IM产品(通信层基于开源IM聊天框架  MobileIMSDK 实现)。

v8.2 版更新内容

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

(1)Android端主要更新内容新增“扫一扫”等功能及优化!】:

  • 1)[bug]解决了客户端被踢掉后,再次登陆时提示socket错误的问题;
  • 2)[优化]优化了扫码加群界面中,群头像加载失败时的默认显示样式;
  • 3)[优化]优化了切换账号和被踢时跳转到登陆界面的切换性能;
  • 4)[优化]重构了主要类代码,更方便集成;
  • 5)[新增]搜索功能(支持好友、群聊、聊天记录搜索(与微信逻辑一样));
  • 6)[新增]“聊信信息”界面中新增“查找聊天记录”功能;
  • 7)[新增]“群聊信息”界面中新增“查找聊天记录”、“清空聊天记录”功能。

(2)服务端主要更新内容:

  • 1)[优化][服务端]升级了MobileIMSDK至v6.2beta(改动了onUserLoginout方法参数);
  • 2)[优化][服务端]解决了log4j2的两个jar包冲突导致在linux下不能正常输出log的问题.

此版主要新增功能运行截图更多截图点此查看):

posted @ 2022-06-25 22:37 Jack Jiang 阅读(37) | 评论 (0)编辑 收藏

     摘要: 本文由字节跳动技术团队开发工程师王浩分享,即时通讯网收录时有较多修订。1、引言对于移动互联网时代的用户来说,短视频应用再也不是看看视频就完事,尤其抖音这种头部应用,已经是除了传统IM即时通讯软件以外的新型社交产品了。对于中国人一年一度最重的节日——春节来说,红包是必不可少的节日特定社交元素,而抖音自然不会被错过。在2022年的春节活动期间,抖音将视频和春节红包相结合,用户可...  阅读全文

posted @ 2022-06-20 17:12 Jack Jiang 阅读(50) | 评论 (0)编辑 收藏

本文由B站微服务技术团队资深开发工程师周佳辉原创分享。

1、引言

如果你在 2015 年就使用 B 站,那么你一定不会忘记那一年 B 站工作日选择性崩溃,周末必然性崩溃的一段时间。

也是那一年 B 站投稿量激增,访问量随之成倍上升,而过去的 PHP 全家桶也开始逐渐展露出颓势,运维难、监控难、排查故障难、调用路径深不见底。

也就是在这一年,B 站开始正式用 Go 重构 B 站,从此B站的API网关技术子开始了从0到1的持续演进。。。

* 补充说明:本次 API 网关演进也以开源形式进行了开发,源码详见本文“12、本文源码”。

PS:本文分享的API网关涉及到的主要是HTTP短连接,虽然跟长连接技术有些差异,但从架构设计思路和实践上是一脉相承的,所以也就收录到了本《长连接网关技术专题》系列文章中。

学习交流:

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

2、关于作者

周佳辉:哔哩哔哩资深开发工程师。始终以简单为核心的技术设计理念,追求极致简单有效的后端架构。

2017 年加入 B 站,先后从事账号、网关、基础库等开发工作。编码 C/V 技能传授者,技术文档背诵者。开源社区爱好者,安全技术爱好者,云计算行业活跃用户,网络工程熟练工。史诗级 bug 生产者,熟练掌握 bug 产生的各类场景。

3、专题目录

本文是专题系列文章的第8篇,总目录如下:

4、正式用Go重构B站

鉴于引言中所列举的各种技术问题,也是在2015年,财队开始正式用 Go 重构 B 站。

B站第一个 Go 项目——bilizone,由冠冠老师(郝冠伟)花了一个周末时间编码完成。

commit 4ccb1497ca6d94cec0ea1b2555dd1859e6f4f223

Author: felixhao <g******[url=mailto:1@gmail.com]1@gmail.com[/url]>

Date:   Wed Jul 1 18:55:00 2015 +0800

    project init

commit 6e338bc0ee638621e01918adb183747cf2a9e567

Author: 郝冠伟 <h*******@bilibili.com>

Date:   Wed Jul 1 11:21:18 2015 +0800

    readme

▲ 郝冠伟:哔哩哔哩主站技术中心架构师

bilizone 其实还是一个大而全的应用,bilizone 在当时重构的主要意义是将谁也理不清的 PHP 逻辑梳理成了一个比较标准的 Go 应用。

bilizone 在当时最大的意义就是为用户终端提供了基本稳定的数据结构、相对可靠的接口和比较有效的监控。

但因 bilizone 依旧是一个单体应用,所以它依旧继承了单体应用所具有的缺点:

  • 1)代码复杂度高:方法被滥用、超时设置混乱、牵一发而动全身;
  • 2)一挂全挂:最常见的比如,超时设置不合理、goroutine 大量堆积、雪崩;
  • 3)测试及维护成本高:小改动都需要测试所有 case,运维发布胆战心惊。

所以此时B站的崩溃频率虽然已经有所降低,但一炸全炸的问题依旧是一个心腹大患。

5、基于微服务的B站架构初具雏形

鉴于bilizone所面临的单体应用技术缺点,接下来的一次重构,让B站基于微服务的全局架构面貌就将初具雏形。

为了实现微服务模式下的 bilibili,我们将一个 bilizone 应用拆分成多个独立业务应用,如账号、稿件、广告等等,这些业务通过 SLB 直接对外提供 API。

当时的调用模式如下图所示:

但是随着功能拆分后,我们对外暴露了一批微服务,但是因为缺乏统一的出口而面临了不少困难。

这些困难主要是:

  • 1)客户端与微服务直接通信,强耦合;
  • 2)需要多次请求,客户端聚合数据,工作量巨大,延迟高;
  • 3)协议不利于统一,各个部门间有差异,反而需要通过客户端来兼容;
  • 4)面向“端”的 API 适配,耦合到了内部服务;
  • 5)多终端兼容逻辑复杂,每个服务都需要处理;
  • 6)统一逻辑无法收敛,比如安全认证、限流。

6、基于BFF模式的微服务架构

基于上节的初阶微服务架构带来的技术问题,以及我们想要将对端的处理进行内聚的想法,我们自然的而然的就想到在客户端与后端服务之间加一个 app-interface 的组件,这就是接下来的 BFF(Backend for Frontend)模式。

app-interface 的工作模式如下图所示:

有了这个 BFF 之后,我们可以在该服务内进行大量的数据聚合,按照业务场景来设计粗粒度的 API。

这样,后续服务的演进也带来了很多优势:

  • 1)轻量交互:协议精简、聚合;
  • 2)差异服务:数据裁剪以及聚合、针对终端定制化 API;
  • 3)动态升级:原有系统兼容升级,更新服务而非协议;
  • 4)沟通效率提升:协作模式演进为移动业务和网关小组。

BFF 可以认为是一种适配服务,将后端的微服务为客户端的需要进行适配(主要包括聚合裁剪和格式适配等逻辑),向终端设备暴露友好和统一的 API,方便无线设备接入访问后端服务,在其中可能还伴随有埋点、日志、统计等需求。

然而,这个时期的 BFF 还有一个致命的一个问题是——整个 app-interface 属于 single point of failure,严重代码缺陷或者流量洪峰可能引发集群宕机所有接口不可用。

7、基于多套BFF模式的微服务架构

针对上节中BFF模式下架构的技术问题,于是我们在上述基础上进一步迭代,将 app-interface 进行业务拆分。

进而多套 BFF 的模式横空出世:

由此模式开始,基本确定了 B 站微服务接口的对接模式,这套模式也随之在全公司内推广开来。

8、垂直BFF模式时代(2016年至2019年)

接上节,当 B 站网关的架构发展为多套垂直 BFF 之后,开发团队围绕该模式平稳迭代了相当长的一段时间。

而后随着B站业务的发展,团队人员的扩充和几次组织架构调整,此时开始出现直播、电商等独立业务,这些业务的发展我们之后再细说。

而在这些调整之后,有一个团队的职责越来越清晰:主站网关组。

主站网关组的主要职责就是维护上述各类功能的 BFF 网关,此时 bilibili 的主要流量入口为粉板 App。这里可以简单细说一下粉板 App 上的所有业务组成。

主站业务:

  • 1)网关组维护的 BFF,如推荐、稿件播放页等;
  • 2)业务层自行维护的 BFF,如评论、弹幕、账号等。

独立业务:

  • 1)电商服务;
  • 2)直播服务;
  • 3)动态服务。

主站业务的 BFF 其实被分为两类:

  • 1)一类是由网关组负责的 BFF;
  • 2)另一类是业务自行维护的 BFF。

而这两类 BFF 的技术栈其实基本一致,基本功能职责也相差不多。如此划分的原因是让网关组可以更专注于迭代客户端特性功能,免去理解部分独立业务场景的接口,如登陆页应该让对安全更专业账号的同学自行维护。

在这里我们也可以简述一下,一个新需求应该如何决定参与的 BFF :

  • 1)如果这个功能能由业务层的业务 BFF 独立完成,则网关组不需介入;
  • 2)如果该功能是一个客户端特性需求,如推荐流等复合型业务,需要对接公司大量部门时,则由网关同学参与开发 BFF。

当时主站技术部的后端同学遵循以上两个规则,基本能够满足业务的快速开发和迭代。

我把这段时间称为垂直 BFF 时代,因为基本主站每个业务或多或少都有各种形式的网关存在,大家通过这个网关向外提供接口,该网关和 SLB 进行直接交互。

9、基于业务的统一API网关架构

接上节,我们再来谈一谈几项重要的业务:电商、直播和动态。

电商和直播其实并不是同一时期衍生的,直播在主站 PHP 时期就诞生了,而电商相对更晚一些。

当时直播的技术栈组成有 C++、PHP、Go,其中早期大部分业务逻辑由 PHP 和 C++ 实现,稍晚一些也开始逐步试用主站的 Go 实现部分业务逻辑。其中 PHP 负责对终端提供接口,C++ 主要实现核心业务功能。因此我们可以简单理解为直播使用由 PHP 编写的 BFF 网关。

动态团队其实派生自直播团队,因此技术栈和直播当时基本一致,这里可以简单省略。

而众所周知,大部分电商团队的技术栈都是 Java 和 Spring 或 Dubbo。

因这几个业务实现上几乎没有相似的地方,且大家对 gRPC 协议逐渐地认同,因此技术栈上大家基本没有大一统的想法,互相能调通即可。

而随着 B 站团队进一步的壮大、流量持续的增长,进而经历了诸多线上故障、事故分析之后,大家慢慢发现了这套架构下的各种问题。

这些问题主要是:

  • 1)单个复杂模块也会导致后续业务集成的高难度,根据康威法则,复杂聚合型 BFF 和多团队之间就出现不匹配问题,团队之间沟通协调成本高,交付效率低下;
  • 2)很多跨横切面逻辑,比如安全认证,日志监控,限流熔断等。随着时间的推移,功能的迭代,代码变得越来越复杂,技术债越堆越多。

此时:我们可能还需要一个能协调横跨切面的组件,将路由、认证、限流、安全等组件全部上提,能够统一更新发布,把业务集成度高的 BFF 层和通用功能服务层进行分层,进而大家开始引入基于业务的“统一API网关”架构(如下图所示)。

在新的架构中:统一网关承担了重要的角色,它是解耦拆分和后续升级迁移的利器。

在统一网关的配合下:单块 BFF 实现了解耦拆分,各业务线团队可以独立开发和交付各自的微服务,研发效率大大提升。

另外:把跨横切面逻辑从 BFF 剥离到网关上去以后,BFF 的开发人员可以更加专注业务逻辑交付,实现了架构上的关注分离(Separation of Concerns)。

10、从基于业务的多网关到全局统一网关(2022年至今)

在这两三年的时间里,各个业务团队或多或少都有自己业务网关组建独立的维护团队,也为网关的功能作出过相当多的投入。

但随着 B 站业务的发展,公司级中间件功能的不断更替演进,如果将对接各个中间件的工作在每个网关上都实现一次的话带来的人力投入和沟通成本会相当巨大,且实现标准不统一、运营方式不统一无法起到 API 网关所带来的最佳收益。

因此微服务团队开发了一款 B 站内部意义上的标准 API 网关(全局统一API网关),该 API 网关汇集以往各型网关中流量治理的优秀经验,对相关功能做出完善设计改进。

该 API 网关的目前的主要功能除了常规的限流、熔断、降级、染色外,还会基于这些基础功能和公司各类中间件的基础上,提供各种额外能力。

这些额外进阶型AP 质量治理的相关功能主要是:

  • 1)全链路灰度;
  • 2)流量采样分析、回放;
  • 3)流量安全控制;
  • ...

业务团队在接入 API 网关后都可以一并获得这些功能,为业务的迅速迭代做出力所能及的保障。

11、不仅仅是 API 网关

在开发 API 网关的同时,我们也会更进一步关注业务团队开发、对接 API 时的体验,我们将以网关作为统一标准 API 规范的起点,为业务团队提供更有效的 API 开发生态。

这些API 开发生态可能是:

  • 1)规划 API 业务域,简化 SRE 运维;
  • 2)标准 API 元信息平台;
  • 3)精确的 API 文档和调试工具;
  • 4)类型安全的 API 集成 SDK;
  • 5)API 兼容性保障服务。

API 网关是我们 API 治理生态中的一个标志性里程碑,我们希望在 API 网关的开发中能够多多倾听大家的意见,希望能有更多的声音来帮助我们理清思路。

本次 API 网关演进也以开源形式进行了开发,在这里欢迎大家指导(本次源码详见本文“12、本文源码)。

12、本文源码

主地址:https://github.com/go-kratos/gateway

备地址:https://github.com/52im/gateway

或从原文链接中下载附件:http://www.52im.net/thread-3941-1-1.html

13、参考资料

[1] 喜马拉雅自研亿级API网关技术实践

[2] 手淘亿级移动端接入层网关的技术演进之路

[3] 从100到1000万高并发的架构演进之路

[4] 一文读懂大型分布式系统设计的方方面面

[5] 零基础理解大型分布式架构的演进历史、技术原理、最佳实践

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

posted @ 2022-06-14 11:56 Jack Jiang 阅读(81) | 评论 (0)编辑 收藏

本文引用了文章“月活 12.8 亿的微信是如何防止崩溃的?”和论文“Overload Control for Scaling WeChat Microservices”的内容,有大量改动、优化和修订。

1、引言

微信是一款国民级的即时通讯IM应用,月活用户早就超过10亿,而且经常过年过节会遇到聊天消息量暴增的情况,服务是很容易出现过载的,但事实是微信的后台服务一直比较稳定,那么他们是怎么做到的呢?

本文以微信发表的论文《Overload Control for Scaling Wechat Microservices》 为基础(论文PDF原文下载见文末附件),分享了微信基于大规模微服务架构的后台过载管控和保护策略,以及微信根据IM业务特点的一些独特的架构设计做法,其中很多方法很有借鉴意义,值得一读。

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

2、微信所面临的并发压力

截止论文《Overload Control for Scaling Wechat Microservices》发表前,微信后端有超过3000多个服务(包括即时聊天、社交关系、移动支付和第三方授权等),占用20000多台机器(随着微信的广泛普及,这些数字仍在不断增加)。

面向前端请求的入口服务每天需要处理10亿到100亿级别的请求,而每个这样的请求还会触发更多内部的关联服务,从整体来看,微信后端需要每秒处理数亿个请求。

随着微信的不断发展,这些服务子系统一直在快速进行更新迭代。以2018 年的3月到5月为例,在短短的两个月时间里,微信的各服务子系统平均每天发生近千次的变更,运维压力可想而之。

另外:微信每天请求量的分布很不平均,高峰期请求量能达到平时的3倍。而在特殊日子里(比如过年的时候),高峰期的流量能飙升到平时的10倍。有时朋友圈里有什么刷屏的活动,流量肯定也会突增。由此可见,微信后端系统的并发压力相当之大。

而且:微信后端的这些服务所处的环境也是不断变化的,包括硬件故障、代码bug、系统变更等,都会导致服务可承受的容量动态变化。

3、微信的后端服务架构

微信后端采用的也是微服务架构。说是微服务,其实我理解就是采用统一的 RPC 框架搭建的一个个独立的服务,服务之间互相调用,实现各种各样的功能,这也是现代服务的基本架构。毕竟谁也不希望看到我朋友圈崩了,导致跟我聊天也不行了,这也是微信的典型好处。

微信后端的微服务架构一般分为3层:

如上图所示,这3层服务分别是:

  • 1)“入口跳板”服务(接收外部请求的前端服务);
  • 2)“共享跳板”服务(中间层协调服务);
  • 3)“基础服务”(不再向其他服务发出请求的服务,也就是充当请求的接收器)。

微信后端的大多数服务属于“共享跳板”服务,“入口跳板”服务比如登录、发送聊天消息、支付服务等。“基础服务”也就是日常最好理解的这些信息数据接口类,比如账户数据、个人信息、好友/联系人信息等。

按照微信后端服务的请求量(每日在十亿到百亿之间),入口协议触发对“共享跳板”服务和“基础服务”更多的请求,核心服务每秒要处理上亿次的请求,也就是显而易见的了。

4、什么是过载保护

1)什么是服务过载?

服务过载就是服务的请求量超过服务所能承受的最大值,从而导致服务器负载过高,响应延迟加大。

用户侧表现就是无法加载或者加载缓慢,这会引起用户进一步的重试,服务一直在处理过去的无效请求,导致有效请求跌 0,甚至导致整个系统产生雪崩。

2)为什么会发生服务过载?

互联网天生就会有突发流量、秒杀、抢购、突发大事件、节日甚至恶意攻击等,都会造成服务承受平时数倍的压力,比如微博经常出现某明星官宣结婚或者离婚导致服务器崩溃的场景,这就是服务过载。

3)过载保护的好处

过载保护主要是为了提升用户体验,保障服务质量,在发生突发流量时仍然能够提供一部分服务能力,而不是整个系统瘫痪。

系统瘫痪就意味着用户流失、口碑变差、夫妻吵架,甚至威胁生命安全(假如腾讯文档崩溃,这个文档正好用于救灾)。

而微信团队在面对这种量级的高并发请求挑战,做法是精细化的服务过载控制。我们继续往下学习。

5、微信面临的过载控制技术挑战

过载控制对于大规模在线应用程序来说至关重要,这些应用程序需要在不可预测的负载激增的情况下实现 24×7 服务可用性。

传统的过载控制机制是为具有少量服务组件、相对狭窄的“前门”和普通依赖关系的系统而设计的。

而微信这种现代即时通讯im应用的全时在线服务特性,在架构和依赖性方面正变得越来越复杂,远远超出了传统过载控制的设计目标。

这些技术痛点包括:

  • 1)由于发送到微信后端的服务请求没有单一的入口点,因此传统的全局入口点(网关)集中负载监控方法并不适用;
  • 2)特定请求的服务调用图可能依赖于特定于请求的数据和服务参数,即使对于相同类型的请求也是如此(因此,当特定服务出现过载时,很难确定应该限制哪些类型的请求以缓解这种情况);
  • 3)过多的请求中止浪费了计算资源,并由于高延迟而影响了用户体验;
  • 4)由于服务的调用链极其复杂,而且在不断演化,导致有效的跨服务协调的维护成本和系统开销过高。

由于一个服务可能会向它所依赖的服务发出多个请求,并且还可能向多个后端服务发出请求,因此我们必须特别注意过载控制。我们使用一个专门的术语,叫作“后续过载”,用于描述调用多个过载服务或多次调用单个过载服务的情况。

“后续过载”给有效的过载控制带来了挑战。当服务过载时随机执行减载可以让系统维持饱和的吞吐量,但后续过载可能会超预期大大降低系统吞吐量 …

即:在大规模微服务场景下,过载会变得比较复杂,如果是单体服务,一个事件只用一个请求,但微服务下,一个事件可能要请求很多的服务,任何一个服务过载失败,就会造成其他的请求都是无效的。如下图所示。

 比如:在一个转账服务下,需要查询分别两者的卡号, 再查询 A 时成功了,但查询 B 失败,对于查卡号这个事件就算失败了。比如查询成功率只有 50%, 那对于查询两者卡号这个成功率只有 50% * 50% = 25% 了, 一个事件调用的服务次数越多,那成功率就会越低。

6、微信的过载控制机制

微信的微服务过载控制机制叫“DAGOR”(因为微信把它的服务间关系模型叫“directed acyclic graph ”,简称DAG)。

显然这种微服务底层的机制必须是和具体的业务实现无关的。DAGOR还必须是去中心化的,否则的话在微信这么大且分布不均的流量下,过载控制很难做到实时和准确。同时也无法适应微服务快速的功能迭代发布(平均每天要发生近1000次的微服务上下线)。

此外,DAGOR还需要解决一个问题:服务调用链很长,如果底层服务因为过载保护丢弃了请求,上层服务耗费的资源全浪费了,而且很影响用户体验(想想进度条走到99%告诉你失败了)。所以过载控制机制在各服务之间必须有协同作用,有时候需要考虑整个调用链的情况。

首先我们来看怎么检测到服务过载。

7、微信如何判断过载

通常判断过载可以使用吞吐量、延迟、CPU 使用率、丢包率、待处理请求数、请求处理事件等等。

微信使用在请求在队列中的平均等待时间作为判断标准。平均等待时间就是从请求到达,到开始处理的时间。

为啥不使用响应时间?因为响应时间是跟服务相关的,很多微服务是链式调用,响应时间是不可控的,也是无法标准化的,很难作为一个统一的判断依据。

那为什么也不使用 CPU 负载作为判断标准呢? 因为 CPU 负载高不代表服务过载,因为一个服务请求处理及时,CPU 处于高位反而是比较良好的表现。实际上 CPU 负载高,监控服务是会告警出来,但是并不会直接进入过载处理流程。

腾讯微服务默认的超时时间是 500ms,通过计算每秒或每 2000 个请求的平均等待时间是否超过 20ms,判断是否过载,这个 20ms 是根据微信后台 5 年摸索出来的门槛值。

采用平均等待时间还有一个好处是:独立于服务,可以应用于任何场景,而不用关联于业务,可以直接在框架上进行改造。

当平均等待时间大于 20ms 时,以一定的降速因子过滤调部分请求,如果判断平均等待时间小于 20ms,则以一定的速率提升通过率,一般采用快降慢升的策略,防止大的服务波动,整个策略相当于一个负反馈电路。

 

8、微信的过载控制策略

微信后台一旦检测到服务过载,就需要按照一定的过载保户策略对请求进行过滤控制,来决定哪些请求能被过载服务处理,哪些是需要丢弃的。

前面我们分析过,对于链式调用的微服务场景,随机丢弃请求会导致整体服务的成功率很低。所以请求是按照优先级进行控制的,优先级低的请求会优先丢弃。

那么从哪些维度来进行优化级的分级呢?

8.1 基于业务的优先级控制

对于微信来说,不同的业务场景优先级是不同的, 比如:

  • 1)登录场景是最重要的业务(不能登录一切都白瞎);
  • 2)支付消息比普通im聊天消息优先级高(因为用户对金钱是更敏感的);
  • 3)普通消息又比朋友圈消息优先级高(必竟微信的本质还是im聊天)。

所以在微信内是天然存在业务优先级的。

微信的做法是,预先定义好所有业务的优先级并保存在一个Hash Table里:

没有定义的业务,默认是最低优先级。

业务优先级在各个业务的入口服务(Entry Services)中找到请求元信息里。由于一个请求成功与否依赖其下游服务所有的后续请求,所以下游服务的所有后续请求也会带上相同的业务优先级。当服务过载时,会处理优先级更高的请求,丢弃优先级低的请求。

然而,只用业务优先级决定是否丢弃请求,容易造成系统颠簸,比如:

  • 1)支付请求突然上涨导致过载,消息请求被丢弃;
  • 2)丢弃消息请求后,系统负载降低了,又开始处理消息请求;
  • 3)然而,处理消息请求又导致服务过载,又会在下一个窗口抛弃消息请求。

这样反复调整服务请求管制,整体体验非常不好。所以微信需要更精细化的服务请求管制。

PS:微信尝试过提供API让服务提供方自己修改业务优先级,后来在实践中发现这种做法在不同的团队中极难管理,且对于过载控制容易出错,最终放弃了。

8.2 基于用户的优先级控制

很明显,正如上节内容所述,只基于业务优先级的控制是不够的:

  • 1)首先不可能因为负载高,丢弃或允许通过一整个业务的请求,因为每个业务的请求量很大,那一定会造成负载的大幅波动;
  • 2)另外如果在业务中随机丢弃请求,在过载情况下还是会导致整体成功率很低。

为了解决这个问题,微信引入用户优先级。

微信在每个业务优先级内按用户ID计算出的128个优先级:

首先用户优先级也不应该相同,对于普通人来说通过 hash 用户唯一 ID计算用户优先级(这个hash函数每小时变一次,让所有用户都有机会在相对较长的时间内享受到高优先级,保证“公平”)。跟业务优先级一样,单个用户的访问链条上的优先级总是一致的。

这里有个疑问:为啥不采用会话 ID 计算优先级呢?

从理论上来说采用会话 ID 和用户 ID 效果是一样的,但是采用会话 ID 在用户重新登录时刷新,这个时候可能用户的优先级可能变了。在过载的情况下,他可能因为提高了优先级就恢复了。

这样用户会养成坏习惯,在服务有问题时就会重新登录,这样无疑进一步加剧了服务的过载情况。

于是,因为引入了用户优先级,那就和业务优先级组成了一个二维控制平面。根据负载情况,决定这台服务器的准入优先级(B,U),当过来的请求业务优先级大于 B,或者业务优先级等于 B,但用户优先级高于 U 时,则通过,否则决绝。

下图就是这个“优先级(B,U)”控制逻辑(我们会在后面再具体讨论):

8.3 自适应优先级调整

在大规模微服务场景下,服务器的负载变化是非常频繁的。所以服务器的准入优先级是需要动态变化的,微信分了几十个业务优先级,每个业务优先级下有 128 个用户优先级,所以总的优先级是几千个。

如何根据负载情况调整优先级呢?

最简单的方式是从右到左遍历:每调整一次判断下负载情况。这个时间复杂度是 O(n), 就算使用二分法,时间复杂度也为 O(logn),在数千个优先级下,可能需要数十次调整才能确定一个合适的优先级,每次调整好再统计优先级,可能几十秒都过去了,这个方法无疑是非常低效的。

微信提出了一种基于直方图统计的方法快速调整准入优先级:服务器上维护者目前准入优先级下,过去一个周期的(1s 或 2000 次请求)每个优先级的请求量。当过载时,通过消减下一个周期的请求量来减轻负载。假设上一个周期所有优先级的通过的请求总和是 N,下一个周期的请求量要减少 N*a,怎么去减少呢?每提升一个优先级就减少一定的请求量,一直提升到 减少的数目大于目标量,恢复负载使用相反的方法,只不是系数为 b ,比 a 小,也是为了快降慢升。根据经验值 a 为 5%,b 为 1%。

为了进一步减轻过载机器的压力,能不能在下游过载的情况下不把请求发到下游呢?否则下游还是要接受请求、解包、丢弃请求,白白的浪费带宽,也加重了下游的负载。

为了实现这个能力:在每次请求下游服务时,下游把当前服务的准入优先级返回给上游,上游维护下游服务的准入优先级,如果发现请求优先级达不到下游服务的准入门槛,直接丢弃,而不再请求下游,进一步减轻下游的压力。

9、实验数据

微信的这套服务过载控制策略(即DAGOR)在微信的生产环境已经运作多年,这是对它的设计可行性的最好证明。

但并没有为学术论文提供必要的图表,所以微信同时进行了一组模拟实验。

下面的图表突出显示了基于排队时间而非响应时间的过载控制的好处。在发生后续过载的情况下,这些好处最为明显(图右)。

10、小结一下

微信的整个过载控制逻辑流程如下图所示:

针对上面这张图,我们来解读一下:

  • 1)当用户从微信发起请求,请求被路由到接入层服务,分配统一的业务和用户优先级,所有到下游的字请求都继承相同的优先级;
  • 2)根据业务逻辑调用 1 个或多个下游服务,当服务收到请求,首先根据自身服务准入优先级判断请求是接受还是丢弃(服务本身根据负载情况周期性的调整准入优先级);
  • 3)当服务需要再向下游发起请求时,判断本地记录的下游服务准入优先级(如果小于则丢弃,如果没有记录或优先级大于记录则向下游发起请求);
  • 4)下游服务返回上游服务需要的信息,并且在信息中携带自身准入优先级;
  • 5)上游接受到返回后解析信息,并更新本地记录的下游服务准入优先级。

微信的整个过载控制策略有以下三个特点:

  • 1)业务无关的:使用请求等待时间而不是响应时间,制定用户和业务优先级,这些都与业务本身无关;
  • 2)高效且公平: 请求链条的优先级是一致的,并且会定时改变 hash 函数调整用户优先级,过载情况下,不会总是影响固定的用户;
  • 3)独立控制和联合控制结合:准入优先级取决于独立的服务,但又可以联合下游服务的情况,优化服务过载时的表现。

11、写在最后

微信团队的分享只提到过载控制,但我相信服务调用方应该还有一些其他机制,能够解决不是因为下游服务过载,而是因为网络抖动导致的请求超时问题。

微信的这套微服务过载控制机制(即DAGOR)提供的服务无关、去中心化、高效和公平等特性很好地在微信后端跑了很多年。

最后,微信团队还分享了他们设计和运维DAGOR宝贵经验:

  • 1)大规模微服务架构中的过载控制必须在每个服务中实现分散和自治;
  • 2)过载控制应该要考虑到各种反馈机制(例如 DAGOR 的协作准入控制),而不是仅仅依赖于开环启发式;
  • 3)应该通过分析实际工作负载来了解过载控制设计。

12、参考资料

[1] Overload Control for Scaling WeChat Microservices

[2] 罗神解读“Overload Control for Scaling WeChat Microservices”

[3] 2W台服务器、每秒数亿请求,微信如何不“失控”?

[4] DAGOR:微信微服务过载控制系统

[5] 月活 12.8 亿的微信是如何防止崩溃的?

[6] 微信朋友圈千亿访问量背后的技术挑战和实践总结

[7] QQ 18年:解密8亿月活的QQ后台服务接口隔离技术

[8] 微信后台基于时间序的海量数据冷热分级架构设计实践

[9] 架构之道:3个程序员成就微信朋友圈日均10亿发布量[有视频]

[10] 快速裂变:见证微信强大后台架构从0到1的演进历程(一)

[11] 一份微信后台技术架构的总结性笔记

13、论文原文

论文PDF请下载此附件:

因无法上传附件,请从此链接:http://www.52im.net/thread-3930-1-1.html文末的“参考资料”附件中下载

论文PDF全部内容概览:

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

posted @ 2022-06-06 16:31 Jack Jiang 阅读(436) | 评论 (0)编辑 收藏

本文由蘑菇街前端开发工程师“三体”分享,原题“蘑菇街云端直播探索——启航篇”,有修订。

1、引言

随着移动网络网速的提升与资费的降低,视频直播作为一个新的娱乐方式已经被越来越多的用户逐渐接受。特别是最近这几年,视频直播已经不仅仅被运用在传统的秀场、游戏类板块,更是作为电商的一种新模式得到迅速成长。

本文将通过介绍实时视频直播技术体系,包括常用的推拉流架构、传输协议等,让你对现今主流的视频直播技术有一个基本的认知。

学习交流:

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

2、蘑菇街的直播架构概览

目前蘑菇街直播推拉流主流程依赖于某云直播的服务。

云直播提供的推流方式有两种:

  • 1)一是通过集成SDK的方式进行推流(用于手机端开播);
  • 2)另一种是通过RTMP协议向远端服务器进行推流(用于PC开播端或专业控台设备开播)。

除去推拉流,该云平台也提供了云通信(IM即时通讯能力)和直播录制等云服务,组成了一套直播所需要的基础服务。

3、推拉流架构1:厂商SDK推拉流

如上题所示,这一种推拉流架构方式需要依赖腾讯这类厂商提供的手机互动直播SDK,通过在主播端APP和用户端APP都集成SDK,使得主播端和用户端都拥有推拉流的功能。

这种推拉流架构的逻辑原理是这样的:

  • 1)主播端和用户端分别与云直播的互动直播后台建立长连接;
  • 2)主播端通过UDT私有协议向互动直播后台推送音视频流;
  • 3)互动直播后台接收到音视频流后做转发,直接下发给与之建立连接的用户端。

这种推拉流方式有几点优势:

  • 1)只需要在客户端中集成SDK:通过手机就可以开播,对于主播开播的要求比较低,适合直播业务快速铺开;
  • 2)互动直播后台仅做转发:没有转码,上传CDN等额外操作,整体延迟比较低;
  • 3)主播端和用户端都可以作为音视频上传的发起方:适合连麦、视频会话等场景。

4、推拉流架构2:旁路推流

之前介绍了通过手机SDK推拉流的直播方式,看起来在手机客户端中观看直播的场景已经解决了。

那么问题来了:如果我想要在H5、小程序等其他场景下观看直播,没有办法接入SDK,需要怎么处理呢?

这个时候需要引入一个新的概念——旁路推流。

旁路推流指的是:通过协议转换将音视频流对接到标准的直播 CDN 系统上。

目前云直播开启旁路推流后,会通过互动直播后台将音视频流推送到云直播后台,云直播后台负责将收到音视频流转码成通用的协议格式并且推送到CDN,这样H5、小程序等端就可以通过CDN拉取到通用格式的音视频流进行播放了。

目前蘑菇街直播旁路开启的协议类型有HLS、FLV、RTMP三种,已经可以覆盖到所有的播放场景,在后续章节会对这几种协议做详细的介绍。

5、推拉流架构3:RTMP推流

随着直播业务发展,一些主播逐渐不满足于手机开播的效果,并且电商直播需要高保真地将商品展示在屏幕上,需要通过更加高清专业的设备进行直播,RTMP推流技术应运而生。

我们通过使用OBS等流媒体录影程序,对专业设备录制的多路流进行合并,并且将音视频流上传到指定的推流地址。由于OBS推流使用了RTMP协议,因此我们称这一种推流类型为RTMP推流。

我们首先在云直播后台申请到推流地址和秘钥,将推流地址和秘钥配置到OBS软件当中,调整推流各项参数,点击推流以后,OBS就会通过RTMP协议向对应的推流地址推送音视频流。

这一种推流方式和SDK推流的不同之处在于音视频流是直接被推送到了云直播后台进行转码和上传CDN的,没有直接将直播流转推到用户端的下行方式,因此相比SDK推流延迟会长一些。

总结下来RTMP推流的优势和劣势比较明显。

优势主要是:

  • 1)可以接入专业的直播摄像头、麦克风,直播的整体效果明显优于手机开播;
  • 2)OBS已经有比较多成熟的插件,比如目前蘑菇街主播常用YY助手做一些美颜的处理,并且OBS本身已经支持滤镜、绿幕、多路视频合成等功能,功能比手机端强大。

劣势主要是:

  • 1)OBS本身配置比较复杂,需要专业设备支持,对主播的要求明显更高,通常需要一个固定的场地进行直播;
  • 2)RTMP需要云端转码,并且本地上传时也会在OBS中配置GOP和缓冲,延时相对较长。

6、高可用架构方案:云互备

业务发展到一定阶段后,我们对于业务的稳定性也会有更高的要求,比如当云服务商服务出现问题时,我们没有备用方案就会出现业务一直等待服务商修复进度的问题。

因此云互备方案就出现了:云互备指的是直播业务同时对接多家云服务商,当一家云服务商出现问题时,快速切换到其他服务商的服务节点,保证业务不受影响。

直播业务中经常遇到服务商的CDN节点下行速度较慢,或者是CDN节点存储的直播流有问题,此类问题有地域性,很难排查,因此目前做的互备云方案,主要是备份CDN节点。

目前蘑菇街整体的推流流程已经依赖了原有云平台的服务,因此我们通过在云直播后台中转推一路流到备份云平台上,备份云在接收到了直播流后会对流转码并且上传到备份云自身的CDN系统当中。一旦主平台CDN节点出现问题,我们可以将下发的拉流地址替换成备份云拉流地址,这样就可以保证业务快速修复并且观众无感知。

7、视频直播数据流解封装原理

介绍流协议之前,先要介绍我们从云端拿到一份数据,要经过几个步骤才能解析出最终需要的音视频数据。

如上图所示,总体来说,从获取到数据到最终将音视频播放出来要经历四个步骤。

第一步:解协议。

协议封装的时候通常会携带一些头部描述信息或者信令数据,这一部分数据对我们音视频播放没有作用,因此我们需要从中提取出具体的音视频封装格式数据,我们在直播中常用的协议有HTTP和RTMP两种。

第二步:解封装。

获取到封装格式数据以后需要进行解封装操作,从中分别提取音频压缩流数据和视频压缩流数据,封装格式数据我们平时经常见到的如MP4、AVI,在直播中我们接触比较多的封装格式有TS、FLV。

第三步:解码音视频。

到这里我们已经获取了音视频的压缩编码数据。

我们日常经常听到的视频压缩编码数据有H.26X系列和MPEG系列等,音频编码格式有我们熟悉的MP3、ACC等。

之所以我们能见到如此多的编码格式,是因为各种组织都提出了自己的编码标准,并且会相继推出一些新的议案,但是由于推广和收费问题,目前主流的编码格式也并不多。

获取压缩数据以后接下来需要将音视频压缩数据解码,获取非压缩的颜色数据和非压缩的音频抽样数据。颜色数据有我们平时熟知的RGB,不过在视频的中常用的颜色数据格式是YUV,指的是通过明亮度、色调、饱和度确定一个像素点的色值。音频抽样数据通常使用的有PCM。

第四步:音视频同步播放。

最后我们需要比对音视频的时间轴,将音视频解码后的数据交给显卡声卡同步播放。

PS:如果你对上述流程还不太理解,建议进一步阅读以下系列文章:

  1. 移动端实时音视频直播技术详解(一):开篇
  2. 移动端实时音视频直播技术详解(二):采集
  3. 移动端实时音视频直播技术详解(三):处理
  4. 移动端实时音视频直播技术详解(四):编码和封装
  5. 移动端实时音视频直播技术详解(五):推流和传输
  6. 移动端实时音视频直播技术详解(六):延迟优化

另外:有关音视频编解码技术的文章,也可以详细学习以下文章:

  1. 视频编解码之:《理论概述》、《数字视频介绍》、《编码基础》、《预测技术介绍
  2. 认识主流视频编码技术H.264
  3. 如何开始音频编解码技术的学习
  4. 音频基础及编码原理入门
  5. 常见的实时语音通讯编码标准
  6. 实时视频编码H.264的特点与优势》、《视频编码H.264、VP8的前世今生
  7. 详解音频编解码的原理、演进和应用选型》、《零基础,史上最通俗视频编码技术入门

8、视频直播传输协议1:HLS

首先介绍一下HLS协议。HLS是HTTP Live Streaming的简写,是由苹果公司提出的流媒体网络传输协议。

从名字可以明显看出:这一套协议是基于HTTP协议传输的。

说到HLS协议:首先需要了解这一种协议是以视频切片的形式分段播放的,协议中使用的切片视频格式是TS,也就是我们前文提到的封装格式。

在我们获取TS文件之前:协议首先要求请求一个M3U8格式的文件,M3U8是一个描述索引文件,它以一定的格式描述了TS地址的指向,我们根据M3U8文件中描述的内容,就可以获取每一段TS文件的CDN地址,通过加载TS地址分段播放就可以组合出一整段完整的视频。

使用HLS协议播放视频时:首先会请求一个M3U8文件,如果是点播只需要在初始化时获取一次就可以拿到所有的TS切片指向,但如果是直播的话就需要不停地轮询M3U8文件,获取新的TS切片。

获取到M3U8后:我们可以看一下里面的内容。首先开头是一些通用描述信息,比如第一个分片序列号、片段最大时长和总时长等,接下来就是具体TS对应的地址列表。如果是直播,那么每次请求M3U8文件里面的TS列表都会随着最新的直播切片更新,从而达到直播流播放的效果。

HLS这种切片播放的格式在点播播放时是比较适用的,一些大的视频网站也都有用这一种协议作为播放方案。

首先:切片播放的特性特别适用于点播播放中视频清晰度、多语种的热切换。比如我们播放一个视频,起初选择的是标清视频播放,当我们看了一半觉得不够清晰,需要换成超清的,这时候只需要将标清的M3U8文件替换成超清的M3U8文件,当我们播放到下一个TS节点时,视频就会自动替换成超清的TS文件,不需要对视频做重新初始化。

其次:切片播放的形式也可以比较容易地在视频中插入广告等内容。

在直播场景下,HLS也是一个比较常用的协议,他最大的优势是苹果大佬的加持,对这一套协议推广的比较好,特别是移动端。将M3U8文件地址喂给video就可以直接播放,PC端用MSE解码后大部分浏览器也都能够支持。但是由于其分片加载的特性,直播的延迟相对较长。比如我们一个M3U8有5个TS文件,每个TS文件播放时长是2秒,那么一个M3U8文件的播放时长就是10秒,也就是说这个M3U8播放的直播进度至少是10秒之前的,这对于直播场景来说是一个比较大的弊端。

HLS中用到的TS封装格式,视频编码格式是通常是H.264或MPEG-4,音频编码格式为AAC或MP3。

一个ts由多个定长的packtet组成,通常是188个字节,每个packtet有head和payload组成,head中包含一些标识符、错误信息、包位置等基础信息。payload可以简单理解为音视频信息,但实际上下层还有还有两层封装,将封装解码后可以获取到音视频流的编码数据。

9、视频直播传输协议2:HTTP-FLV

HTTP-FLV协议,从名字上就可以明显看出是通过HTTP协议来传输FLV封装格式的一种协议。

FLV是Flash Video的简写,是一种文件体积小,适合在网络上传输的封包方式。FlV的视频编码格式通常是H.264,音频编码是ACC或MP3。

HTTP-FLV在直播中是通过走HTTP长连接的方式,通过分块传输向请求端传递FLV封包数据。

在直播中,我们通过HTTP-FLV协议的拉流地址可以拉取到一段chunked数据。

打开文件后可以读取到16进制的文件流,通过和FLV包结构对比,可以发现这些数据就是我们需要的FLV数据。

首先开头是头部信息:464C56转换ASCII码后是FLV三个字符,01指的是版本号,05转换为2进制后第6位和第8位分别代表是否存在音频和视频,09代表头部长度占了几个字节。

后续就是正式的音视频数据:是通过一个个的FLV TAG进行封装,每一个TAG也有头部信息,标注这个TAG是音频信息、视频信息还是脚本信息。我们通过解析TAG就可以分别提取音视频的压缩编码信息。

FLV这一种格式在video中并不是原生支持的,我们要播放这一种格式的封包格式需要通过MSE对影视片的压缩编码信息进行解码,因此需要浏览器能够支持MSE这一API。由于HTTP-FLV的传输是通过长连接传输文件流的形式,需要浏览器支持Stream IO或者fetch,对于浏览器的兼容性要求会比较高。

FLV在延迟问题上相比切片播放的HLS会好很多,目前看来FLV的延迟主要是受编码时设置的GOP长度的影响。

这边简单介绍一下GOP:在H.264视频编码的过程中,会生成三种帧类型:I帧、B帧和P帧。I帧就是我们通常说的关键帧,关键帧内包括了完整的帧内信息,可以直接作为其他帧的参考帧。B帧和P帧为了将数据压缩得更小,需要由其他帧推断出帧内的信息。因此两个I帧之间的时长也可以被视作最小的视频播放片段时长。从视频推送的稳定性考虑,我们也要求主播将关键帧间隔设置为定长,通常是1-3秒,因此除去其他因素,我们的直播在播放时也会产生1-3秒的延时。

10、视频直播传输协议3:RTMP

RTMP协议实际可以与HTTP-FLV协议归做同一种类型。

他们的封包格式都是FlV,但HTTP-FLV使用的传输协议是HTTP,RTMP拉流使用RTMP作为传输协议。

RTMP是Adobe公司基于TCP做的一套实时消息传输协议,经常与Flash播放器匹配使用。

RTMP协议的优缺点非常明显。

RTMP协议的优点主要是:

  • 1)首先和HTTP-FLV一样,延迟比较低;
  • 2)其次它的稳定性非常好,适合长时间播放(由于播放时借用了Flash player强大的功能,即使开多路流同时播放也能保证页面不出现卡顿,很适合监控等场景)。

但是Flash player目前在web端属于墙倒众人推的境地,主流浏览器渐渐都表示不再支持Flash player插件,在MAC上使用能够立刻将电脑变成烧烤用的铁板,资源消耗很大。在移动端H5基本属于完全不支持的状态,兼容性是它最大的问题。

11、视频直播传输协议4:MPEG-DASH

MPEG-DASH这一协议属于新兴势力,和HLS一样,都是通过切片视频的方式进行播放。

他产生的背景是早期各大公司都自己搞自己的一套协议。比如苹果搞了HLS、微软搞了 MSS、Adobe还搞了HDS,这样使用者需要在多套协议封装的兼容问题上痛苦不堪。

于是大佬们凑到一起,将之前各个公司的流媒体协议方案做了一个整合,搞了一个新的协议。

由于同为切片视频播放的协议,DASH优劣势和HLS类似,可以支持切片之间多视频码率、多音轨的切换,比较适合点播业务,在直播中还是会有延时较长的问题。

12、如何选择最优的视频直播传输协议

视频直播协议选择非常关键的两点,在前文都已经有提到了,即低延时和更优的兼容性。

首先从延时角度考虑:不考虑云端转码以及上下行的消耗,HLS和MPEG-DASH通过将切片时长减短,延时在10秒左右;RTMP和FLV理论上延时相当,在2-3秒。因此在延时方面HLS ≈ DASH > RTMP ≈ FLV。

从兼容性角度考虑:HLS > FLV > RTMP,DASH由于一些项目历史原因,并且定位和HLS重复了,暂时没有对其兼容性做一个详尽的测试,被推出了选择的考虑范围。

综上所述:我们可以通过动态判断环境的方式,选择当前环境下可用的最低延迟的协议。大致的策略就是优先使用HTTP-FLV,使用HLS作为兜底,在一些特殊需求场景下通过手动配置的方式切换为RTMP。

对于HLS和HTTP-FLV:我们可以直接使用 hls.js 和 flv.js 做做解码播放,这两个库内部都是通过MSE做的解码。首先根据视频封装格式提取出对应的音视频chunk数据,在MediaSource中分别对音频和视频创建SourceBuffer,将音视频的编码数据喂给SourceBuffer后SourceBuffer内部会处理完剩下的解码和音视频对齐工作,最后MediaSource将Video标签中的src替换成MediaSource 对象进行播放。

在判断播放环境时我们可以参照flv.js内部的判断方式,通过调用MSE判断方法和模拟请求的方式判断MSE和StreamIO是否可用:

// 判断MediaSource是否被浏览器支持,H.264视频编码和Acc音频编码是否能够被支持解码

window.MediaSource && window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"');

如果FLV播放不被支持的情况下:需要降级到HLS,这时候需要判断浏览器环境是否在移动端,移动端通常不需要 hls.js 通过MSE解码的方式进行播放,直接将M3U8的地址交给video的src即可。如果是PC端则判断MSE是否可用,如果可用就使用hls.js解码播放。

这些判读可以在自己的逻辑里提前判断后去拉取对应解码库的CDN,而不是等待三方库加载完成后使用三方库内部的方法判断,这样在选择解码库时就可以不把所有的库都拉下来,提高加载速度。

13、同层播放如何解决

电商直播需要观众操作和互动的部分比起传统的直播更加多,因此产品设计的时候很多的功能模块会悬浮在直播视频上方减少占用的空间。这个时候就会遇到一个移动端播放器的老大难问题——同层播放。

同层播放问题:是指在移动端H5页面中,一些浏览器内核为了提升用户体验,将video标签被劫持替换为native播放器,导致其他元素无法覆盖于播放器之上。

比如我们想要在直播间播放器上方增加聊天窗口,将聊天窗口通过绝对定位提升z-index置于播放器上方,在PC中测试完全正常。但在移动端的一些浏览器中,video被替换成了native播放器,native的元素层级高于我们的普通元素,导致聊天窗口实际显示的时候在播放器下方。

要解决这个问题,首先要分多个场景。

首先在iOS系统中:正常情况下video标签会自动被全屏播放,但iOS10以上已经原生提供了video的同层属性,我们在video标签上增加playsinline/webkit-playsinline可以解决iOS系统中大部分浏览器的同层问题,剩下的低系统版本的浏览器以及一些APP内的webview容器(譬如微博),用上面提的属性并不管用,调用三方库iphone-inline-video可以解决大部分剩余问题。

在Android端:大部分腾讯系的APP内置的webview容器用的都是X5内核,X5内核会将video替换成原生定制的播放器已便于增强一些功能。X5也提供了一套同层的方案(该方案官方文档链接已无法打开),给video标签写入X5同层属性也可以在X5内核中实现内联播放。不过X5的同层属性在各个X5版本中表现都不太一样(比如低版本X5中需要使用X5全屏播放模式才能保证MSE播放的视频同层生效),需要注意区分版本。

在蘑菇街App中,目前集成的X5内核版本比较老,在使用MSE的情况下会导致X5同层参数不生效。但如果集成新版本的X5内核,需要对大量的线上页面做回归测试,成本比较高,因此提供了一套折中的解决方案。通过在页面URL中增加一个开关参数,容器读取到参数以后会将X5内核降级为系统原生的浏览器内核,这样可以在解决浏览器视频同层问题的同时也将内核变动的影响范围控制在单个页面当中。

14、相关文章

[1] 移动端实时音视频直播技术详解(四):编码和封装

[2] 移动端实时音视频直播技术详解(五):推流和传输

[3] 实现延迟低于500毫秒的1080P实时音视频直播的实践分享

[4] 浅谈开发实时视频直播平台的技术要点

[5] 直播系统聊天技术(七):直播间海量聊天消息的架构设计难点实践

[6] 从0到1:万人在线的实时音视频直播技术实践分享(视频+PPT) [附件下载]

[7] 实时视频编码H.264的特点与优势

[8] 视频编码H.264、VP8的前世今生

[9] 零基础,史上最通俗视频编码技术入门

[10] 视频编解码之编码基础

[11] 零基础入门:实时音视频技术基础知识全面盘点

[12] 实时音视频面视必备:快速掌握11个视频技术相关的基础概念

[13] 写给小白的实时音视频技术入门提纲

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

posted @ 2022-05-31 15:26 Jack Jiang 阅读(116) | 评论 (0)编辑 收藏

     摘要: 本文作者张彦飞,原题“聊聊TCP连接耗时的那些事儿”,有少许改动。1、引言对于基于互联网的通信应用(比如IM聊天、推送系统),数据传递时使用TCP协议相对较多。这是因为在TCP/IP协议簇的传输层协议中,TCP协议具备可靠的连接、错误重传、拥塞控制等优点,所以目前在应用场景上比UDP更广泛一些。相信你也一定听闻过TCP也存在一些缺点,能常都是老生常谈的开销要略大。但是各路技...  阅读全文

posted @ 2022-05-26 16:10 Jack Jiang 阅读(84) | 评论 (0)编辑 收藏

     摘要: 本文作者“Carson”,现就职于腾讯公司,原题“高效保活长连接:手把手教你实现自适应的心跳保活机制”,有较多修订和改动。1、引言当要实现IM即时通讯聊天、消息推送等高实时性需求时,我们一般会选择长连接的通信方式。而真正当实现长连接方式时,会遇到很多技术问题,比如最常见的长连接保活问题。今天,我将通过本篇文章,手把手教大家实现一套可自适应的心跳保活机...  阅读全文

posted @ 2022-05-18 15:09 Jack Jiang 阅读(91) | 评论 (0)编辑 收藏

本文由ELab技术团队分享,原题“探秘HTTPS”,有修订和改动。

1、引言

对于IM开发者来说,IM里最常用的通信技术就是Socket长连接和HTTP短连接(通常一个主流im会是这两种通信手段的结合)。从通信安全的角度来说,Socket长连接的安全性,就是基于SSL/TLS加密的TCP协议来实现的(比如微信的mmtls,见《微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解);而对于HTTP短连接的安全性,也就是HTTPS了。

到底什么是HTTPS?为什么要用HTTPS?今天就借此机会,跟大家一起深入学习一下HTTPS的相关知识,包括HTTP的发展历程、HTTP遇到的问题、对称与非对称加密算法、数字签名、第三方证书颁发机构等概念。

学习交流:

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

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK 

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

2、系列文章

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

3、写在前面

说到HTTPS,那就得回到HTTP协议。

对于HTTP协议,大家肯定都熟得不能再熟了。那么HTTPS和HTTP的区别大家了解吗?

对于这个经典的面试题,大部分人会这么回答:

  • 1)HTTPS比HTTP多了一个S(Secure):也就是说HTTPS是安全版的HTTP;
  • 2)端口号不同:HTTP使用80端口,HTTPS使用443端口;
  • 3)加密算法:HTTPS用的是非对称加密算法。

上面的回答能给几分?等看完本文我们可以再回头来看下这个回答。

那么,HTTPS是如何实现安全的短连接数据传输呢?想彻底搞明白这个问题,还是要从HTTP的发展历程说起 ......

4、HTTP协议回顾

4.1 基础常识

HTTP是Hypertext Transfer Protocal 的缩写,中文全称是超文本传输协议(详见《深入浅出,全面理解HTTP协议)。

通俗了解释就是:

  • 1)超文本是指包含但不限于文本外的图片、音频、视频等多媒体资源;
  • 2)协议是通信双方约定好的数据传输格式以及通信规则。

HTTP是TCP/IP协议簇的最高层——应用层协议:

▲ 上图引用自《深入浅出,全面理解HTTP协议

浏览器和服务器在使用HTTP协议相互传递超文本数据时,将数据放入报文体内,同时填充首部(请求头或响应头)构成完整HTTP报文并交到下层传输层,之后每一层加上相应的首部(控制部分)便一层层的下发,最终由物理层将二进制数据以电信号的形式发送出去。

HTTP的请求如下图所示:

▲ 上图引用自《深入浅出,全面理解HTTP协议

HTTP报文结构如下:

4.2 发展历程

HTTP的发展历程如下:

由HTTP的发展历程来看,最开始版本的HTTP(HTTP1.0)在每次建立TCP连接后只能发起一次HTTP请求,请求完毕就释放TCP连接。

我们都知道TCP连接的建立需要经过三次握手的过程,而每次发送HTTP请求都需要重新建立TCP连接,毫无疑问是很低效的。所以HTTP1.1改善了这一点,使用长连接的机制,也就是“一次TCP连接,N次HTTP请求”。

HTTP协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。

在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。

PS:对于IM开发者来说,为了与Socket长连接通道区分,通常认为HTTP就是“短连接”虽然这个“短连接”不一定真的“短”)。

HTTP1.0若要开启长连接,需要加上Connection: keep-alive请求头。有关HTTP协议的详细发展历程可阅读《一文读懂HTTP协议的历史演变和设计思路》一文。

4.3 安全问题

随着HTTP越来越广泛的使用,HTTP的安全性问题也逐渐暴露。

回忆一下多年前遍地都是的运营商劫持,当你访问一个本来很正常的网页,但页面上却莫名其妙出现了一些广告标签、跳转脚本、欺骗性的红包按钮,甚至有时候本来要下载一个文件,最后下载下来却变成了另外一个完全不同的东西,这些都是被运营商劫持了HTTP明文数据的现象。

下图就是似曾相识的运营商劫持效果图:

PS:关于运营商劫持问题,可以详细阅读《全面了解移动端DNS域名劫持等杂症:原理、根源、HttpDNS解决方案等》。

HTTP主要有以下3点安全性问题:

 

归纳一下就是:

  • 1)数据保密性问题:因为HTTP无状态,而且又是明文传输,所有数据内容都在网络中裸奔,包用户括身份信息、支付账号与密码。这些敏感信息极易泄露造成安全隐患;
  • 2)数据完整性问题:HTTP数据包在到达目的主机前会经过很多转发设备,每一个设备节点都可能会篡改或调包信息,无法验证数据的完整性;
  • 3)身份校验问题:有可能遭受中间人攻击,我们无法验证通信的另一方就是我们的目标对象。

因此,为了保证数据传输的安全性,必须要对HTTP数据进行加密。

5、常见的加密方式

5.1 基本情况

常见的加密方式分为三种:

  • 1)对称加密;
  • 2)非对称加密;
  • 3)数字摘要。

前两种适合数据传输加密,而数字摘要不可逆的特性常被用于数字签名。

接下来,我们逐一简要学习一下这三种常见的加密方法。

5.2 对称加密

对称加密也称为密钥加密或单向加密,就是使用同一套密钥来进行加密和解密。密钥可以理解为加密算法。

对称加密图示如下:

广泛使用的对称加密有:

对称加密算法的优缺点和适用场景:

  • 1)优点:算法公开、简单,加密解密容易,加密速度快,效率高;
  • 2)缺点:相对来说不算特别安全,只有一把钥匙,密文如果被拦截,且密钥也被劫持,那么,信息很容易被破译;
  • 3)适用场景:加解密速度快、效率高,因此适用于大量数据的加密场景。由于如何传输密钥是较为头痛的问题,因此适用于无需进行密钥交换的场景,如内部系统,事先就可以直接确定密钥。

PS:可以在线体验对称加密算法,链接是:http://www.jsons.cn/textencrypt/

小知识:base64编码也属于对称加密哦!

5.3 非对称加密

非对称加密使用一对密钥(公钥和私钥)进行加密和解密。

非对称加密可以在不直接传递密钥的情况下,完成解密,具体步骤如下:

  • 1)乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的;
  • 2)甲方获取乙方的公钥,然后用它对信息加密;
  • 3)乙方得到加密后的信息,用私钥解密。

以最典型的非对称加密算法RSA为例,举个例子:

想要彻底搞懂RSA,需要了解数论的知识,全部推导过程RSA加密算法。简单介绍思路:使用两个超大质数以及其乘积作为生成公钥和私钥的材料,想要从公钥推算出私钥是非常困难的(需要对超大数因式分解为两个很大质数的乘积)。目前被破解的最长RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。

非对称加密算法的优缺点和适用场景:

  • 1)优点:强度高、安全性强于对称加密算法、无需传递私钥导致没有密钥泄露风险;
  • 2)缺点:计算量大、速度慢;
  • 3)适用场景:适用于需要密钥交换的场景,如互联网应用,无法事先约定密钥。

实践应用过程中,其实可以与对称加密算法结合:

  • 1)利用非对称加密算法安全性较好的特点来传递对称加密算法的密钥。
  • 2)利用对称加密算法加解密速度快的特点,进行数据内容比较大的加密场景的加密(如HTTPS)。

PS:对于IM开发者来说,《探讨组合加密算法在IM中的应用》一文值得一读。

5.4 如何选择?

1)如果选择对称加密:

HTTP请求方使用对称算法加密数据,那么为了接收方能够解密,发送方还需要把密钥一同传递到接收方。在传递密钥的过程中还是可能遭到嗅探攻击,攻击者窃取密钥后依然可以解密从而得到发送的数据,所以这种方案不可行。

2)如果选择非对称加密:

接收方保留私钥,把公钥传递给发送方。发送方用公钥来加密数据,接收方使用私钥解密数据。攻击者虽然不能直接获取这些数据(因为没有私钥),但是可以通过拦截传递的公钥,然后把自己的公钥传给发送方,再用自己的私钥对发送方发送数据进行解密。

整个过程通信双方都不知道中间人的存在,但是中间人能够获得完整的数据信息。

3)两种加密方法的混合:

先使用非对称加密算法加密并传递对称加密的密钥,然后双方通过对称加密方式加密要发送的数据。看起来没什么问题,但事实是这样吗?

中间人依然可以拦截公钥的传递,并以自己的公钥作为替换,治标不治本。

想要治本,就要找到一个第三方公证人来证明公钥没有被替换,因此就引出了数字证书的概念,这也是下一节将分享的内容。

6、数字证书

6.1 CA机构

CA就是 Certificate Authority,即颁发数字证书的机构。

作为受信任的第三方,CA承担公钥体系中公钥的合法性检验的责任。

证书就是源服务器向可信任的第三方机构申请的数据文件。这个证书除了表明这个域名是属于谁的,颁发日期等,还包括了第三方证书的私钥。

服务器将公钥放在数字证书中,只要证书是可信的,公钥就是可信的。

下面两图是飞书域名的证书中部分内容的信:

6.2 数字签名

摘要算法:一般用哈希函数来实现,可以理解成一种定长的压缩算法,它能把任意长度的数据压缩到固定长度。这好比是给数据加了一把锁,对数据有任何微小的改动都会使摘要变得截然不同。

通常情况下:数字证书的申请人(服务器)将生成由私钥和公钥以及证书请求文件(Certificate Signing Request,CSR)组成的密钥对。CSR是一个编码的文本文件,其中包含公钥和其他将包含在证书中的信息(例如:域名、组织、电子邮件地址等)。密钥对和CSR生成通常在将要安装证书的服务器上完成,并且 CSR 中包含的信息类型取决于证书的验证级别。与公钥不同,申请人的私钥是安全的,永远不要向 CA(或其他任何人)展示。

生成 CSR 后:申请人将其发送给 CA,CA 会验证其包含的信息是否正确,如果正确,则使用颁发的私钥对证书进行数字签名,然后将签名放在证书内随证书一起发送给申请人。

在SSL握手阶段:浏览器在收到服务器的证书后,使用CA的公钥进行解密,取出证书中的数据、数字签名以及服务器的公钥。如果解密成功,则可验证服务器身份真实。之后浏览器再对数据做Hash运算,将结果与数字签名作对比,如果一致则可以认为内容没有收到篡改。

对称加密和非对称加密是公钥加密、私钥解密, 而数字签名正好相反——是私钥加密(签名)、公钥解密(验证),如下图所示。

限于篇幅,关于数字证书的内容本文就不再赘述,想详细了解的可以阅读:

7、为什么要使用HTTPS

图解HTTP》一书中提到HTTPS就是身披SSL外壳的HTTP。

7.1 SSL

SSL 在1999年被更名为TLS

所以说:HTTPS 并不是一项新的应用层协议,只是 HTTP 通信接口部分由 SSL 和 TLS 替代而已。

具体就是:HTTP 会先直接和 TCP 进行通信,而HTTPS 会演变为先和 SSL 进行通信,然后再由 SSL 和 TCP 进行通信。

SSL是一个独立的协议,不只有 HTTP 可以使用,其他应用层协议也可以使用,比如FTP、SMTP都可以使用SSL来加密。

7.2 HTTPS请求流程

HTTPS请求全流程如下图:

如上图所示:

  • 1)用户在浏览器发起HTTPS请求,默认使用服务端的443端口进行连接;
  • 2)HTTPS需要使用一套CA 数字证书,证书内会附带一个服务器的公钥Pub,而与之对应的私钥Private保留在服务端不公开;
  • 3)服务端收到请求,返回配置好的包含公钥Pub的证书给客户端;
  • 4)客户端收到证书,校验合法性,主要包括是否在有效期内、证书的域名与请求的域名是否匹配,上一级证书是否有效(递归判断,直到判断到系统内置或浏览器配置好的根证书),如果不通过,则显示HTTPS警告信息,如果通过则继续;
  • 5)客户端生成一个用于对称加密的随机Key,并用证书内的公钥Pub进行加密,发送给服务端;
  • 6)服务端收到随机Key的密文,使用与公钥Pub配对的私钥Private进行解密,得到客户端真正想发送的随机Key;
  • 7)服务端使用客户端发送过来的随机Key对要传输的HTTP数据进行对称加密,将密文返回客户端;
  • 8)客户端使用随机Key对称解密密文,得到HTTP数据明文;
  • 9)后续HTTPS请求使用之前交换好的随机Key进行对称加解密。

7.3 HTTPS到底解决了什么问题

HTTPS确实解决了HTTP的三个安全性问题:

  • 1) 保密性:结合非对称加密和对称加密实现保密性。用非对称加密方式加密对称加密的秘钥,再用对称加密方式加密数据;
  • 2) 完整性:通过第三方CA的数字签名解决完整性问题;
  • 3) 身份校验:通过第三方CA的数字证书验证服务器的身份。

7.4 HTTPS优缺点

最后我们总结一下HTTPS的优缺点:

可以看到:HTTPS的确是当今安全传输HTTP的最优解,但他并不是完美的,仍会有漏洞。

8、参考资料

[1] 深入浅出,全面理解HTTP协议

[2] HTTP协议必知必会的一些知识

[3] 从数据传输层深度解密HTTP

[4] 一文读懂HTTP协议的历史演变和设计思路

[5] 你知道一个TCP连接上能发起多少个HTTP请求吗?

[6] 如果这样来理解HTTPS,一篇就够了

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

[8] 你知道,HTTPS用的是对称加密还是非对称加密?

[9] HTTPS时代已来,打算更新你的HTTP服务了吗?

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

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

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

posted @ 2022-05-13 16:27 Jack Jiang 阅读(94) | 评论 (0)编辑 收藏

关于MobileIMSDK

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

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

关于RainbowChat

► 详细产品介绍:http://www.52im.net/thread-19-1-1.html
► 版本更新记录:http://www.52im.net/thread-1217-1-1.html
► 全部运行截图:Android端iOS端
► 在线体验下载:专业版(TCP协议)专业版(UDP协议)      (关于 iOS 端,请:点此查看

 

RainbowChat是一套基于开源IM聊天框架 MobileIMSDK 的产品级移动端IM系统。RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题(可自行下载体验:专业版下载安装)。

* RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP两种通信协议的IM产品(通信层基于开源IM聊天框架  MobileIMSDK 实现)。

v8.1 版更新内容

此版更新内容:

(1)Android端主要更新内容【新增“扫一扫”等功能及优化!】:

  • 1)[新增]“扫一扫”界面及完整功能(支持扫码加好友、加群);
  • 2)[新增]“我的二维码”界面及完整功能;
  • 3)[新增]“群聊二维码”界面及完整功能;
  • 4)[升级]升级okhttp库至4.9.3;
  • 5)[优化]其它小优化。

(2)服务端主要更新内容:

  • 1)[优化]针对扫码加群等功能的相关修改。

此版主要新增功能运行截图更多截图点此查看):

posted @ 2022-05-11 17:49 Jack Jiang 阅读(75) | 评论 (0)编辑 收藏

     摘要: 一、前言MobileIMSDK 是什么?MobileIMSDK  是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持UDP 、TCP 、WebSocket 三种协议,支持iOS、Android、H5、标准Java平台,服务端基于Netty编写。工程地址是:1)Gitee码云地址:https://www.oschina.net/p/mobilei...  阅读全文

posted @ 2022-05-05 15:15 Jack Jiang 阅读(98) | 评论 (0)编辑 收藏

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