Jack Jiang

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

2018年7月5日

本文在编写时参考了博客作者“鹿呦呦”和在线课程“即时消息技术剖析与实战”的相关资料,一并表示感谢。

1、引言

随着移动互联网络的发展,IM技术的应用已经不仅限于聊天应用本身,它早已融入各种应用形态中,比如:直播中的主播互动、联网游戏中的玩家互动、外卖/打车应用中的实时位置共享、在线教育应用中的互动白板等。

在这些风格迥异的应用场景下,IM技术所呈现出来的功能形态虽有不同,但“实时性”这个技术特征并无区别。

那么,对于技术门外汉来说,到底什么是IM的“实时性”?该如何理解它?这就是本文想要讨论的主题。

区别于强大的原生应用,Web端的IM系统,在很长一段时间内想实现真正的“实时性”,是非常困难的,因为无法直接使用UDP、TCP通信协议,在HTML5中的WebSocket出现之前,Web端几乎没有真正意义上的“双向实时通信”这种技术存在。

正因为如此,理解Web端即时通信技术的演进,也就自然而然能循序渐进地体会到IM系统中的“实时性”了。所以本文将围绕Web端即时通讯技术,为你展开IM“实时性”这个话题。

友情提示:本系列文章侧重于理论概念的讲述,篇幅有限,点到即止,如需系统、深入、具体地学习IM技术的方方面面,请从此文入手:《新手入门一篇就够:从零开发移动端IM》(史诗级文章,适合从入门到放弃)。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170 [推荐]

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

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

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

2、系列文章目录

IM开发快速入门(一):什么是IM系统?

IM开发快速入门(二):什么是IM系统的实时性?》(* 本文

《IM开发快速入门(三):什么是IM系统的可靠性? (稍后发布)》

《IM开发快速入门(四):什么是IM系统的一致性? (稍后发布)》

《IM开发快速入门(五):什么是IM系统的安全性? (稍后发布)》

《IM开发快速入门(六):什么是IM系统的的心跳机制? (稍后发布)》

《IM开发快速入门(七):如何理解并实现IM系统消息未读数? (稍后发布)》

《IM开发快速入门(八):如何理解并实现IM系统的多端消息漫游? (稍后发布)》

3、短轮询技术

在早期的Web时代,技术的创造者们无法预见如今各种选进的技术应用形式,他们认为数据只是用来“看”的,也数据的获取基本就是“请求 -> 响应”这种一问一答形式。包括我们平时浏览的各种门户网站都是采用的“请求响应”模式。

这种依赖于用户“主动”请求的数据获取模式,如果想实现IM系统,是无法即时获得最新的聊天消息的,因为用户并不知道新消息什么时候到来,而服务端也没有办法主动通知用户。

在这个时期,虽然技术和思路都受当时技术水平的限制,但IM总不能不做吧。

于是,一种被称为“短轮询”的数据获取模式出现了。在“短轮询”模式下,IM客户端定时轮询服务端,以便让用户知道是否有新的聊天消息存在。

这种模式下,服务端收到请求后,即刻查询是否存在新消息,有就返回给客户端,没有则返回空并立即关闭连接。

相较于前面用户需要“手动”去刷新页面的方式,这种模式只是将用户的“手动”变为“自动”而已,技术本质并没有发生任何实质性改变。

短轮询这种模式,就好比旧时代一个等待重要邮件的人,他需要每天自已跑到邮局,主动去问是否有自己的信件,有就拿回家,如果没有,则第二天继续去问。一来一去,非常低效。

技术原理总结如下图所示:

短轮询这种模式有好处,也有坏处。

好处是:

  • 1)技术简单,容易实现;
  • 2)可维护性强,因为它没什么复杂的。

坏处是:

  • 1)因为无法预知数据是否存在,所以多数请求是无用的,浪费计算资源;
  • 2)为了提升实时性,高频率的请求会加大服务端的性能负载。

总结一下就是,短轮询这种模式对于IM技术大拿来说,显的非常low,因为技术实现实在是简单粗暴。

4、长轮询技术

正如你所见,用短轮询技术来保证IM的实时性,确实难说优雅。不过,这难不倒无所不能的程序员,一种被称为“长轮询”的数据获取模式出现了。

从技术上来说,长轮询实现的IM相较于短轮询最大的改进在于:短轮询情况下,服务端不管有没有新消息,请求结束就会立即断开连接。而长轮询时,如果本次请求没有新消息发生,糨不会马上断开连接并返回,而是会将本次连接“挂起”一段时间,如果在这段“挂起”时间内有新的聊天消息出现,就能马上读取并立即返回给客户端,接着结束本次连接。一段时间后又会再次发起请求,如此周而复始。

长轮询这种模式,拿上节等待邮件的这个例子来说,就好比收信的人每天到邮局去问是否有信件,如果没有,他不马上回家,而是在邮局待上一段时间,如果这段时间过去了,还是没有,就先回家,接着第二天再来。

技术原理总结如下图所示: 

长轮询的优点是:

  • 1)相较于短连询,一定程度降低了服务端请求负载;
  • 2)相较于短连询,实时性有提升,因为它是主动“等”消息。

长轮询的缺点是:

  • 1)长论询模式下,连接“挂起”的这段时间内,服务端需要配合开启单独的消息查询线程,仍然存在无用功;
  • 2)相较于短连询模式,在一次长轮询结束、下次轮询发起前的窗口期内,仍然存在“实时性”盲区。

实际上,在Web端即时通讯技术里,长轮询有个专业的术语叫“Comet”,有兴趣可以详细学习《Comet技术详解:基于HTTP长连接的Web端实时通信技术》。

5、轮询无法实现真正的“实时性”

对于Web端即时通讯技术来说,上面提到的无论是短轮询,还是长轮询,它们都存在“实时性”盲区。

我们回到上两节介绍的短轮询和长轮询技术原理图。

先看看短轮询这张图:

很明显,短轮询在每次轮询结束和下次轮询开始的间隔期内,是无法感知到新消息的,这也便形成了“实时性盲区”。换句话说,短轮询技术在“实时性盲区”内,无法做到“实时”。

再来看看长轮询:

跟短轮询道理一样,长轮询在每次轮询结束和下次轮询开始的间隔期,依然会形成“实时性盲区”。

要理解纠结轮询技术的实时性缺陷,就得了解它们背后的技术——HTTP协议了。

HTTP协议设计的目的,就是为了实现“请求--响应”这种模式的数据交互,也就是众所周之的“短连接”设计。而无论是短轮询还是长轮询,都跳不出HTTP的先天技术逻辑(请求--响应--断开)。

所以,归根到底,想要基于HTTP协议来实现IM,要达到真正的“实时性”,是相当勉强的。因为HTTP设计的目的,就是用“短连接”来简化传统TCP长连接通信带来的复杂性,而IM的实时性恰好要用到的又是TCP的长连接特性,所以这就是个悖论。

要真正实现Web端的IM“实时性”,肯定不能强行HTTP上做文章了,我们需要新的技术。

6、WebSocket让Web端IM真正的“实时性”变成可能

好消息是,HTML5中带来了WebSocket技术。WebSocket是真正的全双式双向通信技术(详见:《WebSocket从入门到精通,半小时就够!》)。

下图上旧式轮询技术跟WebSocket的对比图:

从上图可以看出:

  • 1)轮询技术一问一答,在下一个请求发起之前,存在“实时性”盲区;
  • 2)WebSocket一旦建立连接后,数据可以随时双向通信(即客户端可以随时向服务端发消息,服务端也可以随时通知客户端有新消息)。

举个例子就是:轮询技术相当于传统的邮件传递方法(你得自已去邮局问有没有新邮件),而WebSocket相当于现代的电话系统,只要你拨通后,随时可以实时收听到对方的声音,对方也能随时收听到你的声音。完美!

总结一下WebSocket 的优点是:

  • 1)真正的实时性:支持客户端与服务端真正的双向实时通信;
  • 2)大幅降低负载:少了轮询技术中高频率无用的请求,可大大降低服务端QPS压力;
  • 3)网络开销降低:一次连接,随时使用,再也不用轮询技术中每次发起HTTP请求(随之而来的是每次HTTP的大量冗余协议头信息等)。

7、本文小结

本文以Web端即时通讯技术的演进为例,从短轮询到长轮询,再到WebSocket,理论联系实际地讲解了Web端IM“实时性”的技术变迁,从而帮助读者理解IM中“实时性”这个最为关键的技术特征。

附录:更多Web端即时通讯资料

新手入门贴:史上最全Web端即时通讯技术原理详解

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

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

Comet技术详解:基于HTTP长连接的Web端实时通信技术

新手快速入门:WebSocket简明教程

WebSocket详解(一):初步认识WebSocket技术

WebSocket详解(二):技术原理、代码演示和应用案例

WebSocket详解(三):深入WebSocket通信协议细节

WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)

WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)

WebSocket详解(六):刨根问底WebSocket与Socket的关系

socket.io实现消息推送的一点实践及思路

LinkedIn的Web端即时通讯实践:实现单机几十万条长连接

Web端即时通讯技术的发展与WebSocket、Socket.io的技术实践

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

开源框架Pomelo实践:搭建Web端高性能分布式IM聊天服务器

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

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

MobileIMSDK-Web的网络层框架为何使用的是Socket.io而不是Netty?

理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性

微信小程序中如何使用WebSocket实现长连接(含完整源码)

八问WebSocket协议:为你快速解答WebSocket热门疑问

快速了解Electron:新一代基于Web的跨平台桌面技术

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

Web端即时通讯基础知识补课:一文搞懂跨域的所有问题!

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

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

>> 更多同类文章 ……

本文已同步发布于“即时通讯技术圈”公众号:

▲ 本文在公众号上的链接是:点此进入,原文链接是:http://www.52im.net/thread-3143-1-1.html

posted @ 2020-09-18 13:56 Jack Jiang 阅读(31) | 评论 (0)编辑 收藏

1、引言

在中大型IM系统中,聊天消息的唯一ID生成策略是个很重要的技术点。不夸张的说,聊天消息ID贯穿了整个聊天生命周期的几乎每一个算法、逻辑和过程,ID生成策略的好坏有可能直接决定系统在某些技术点上的设计难易度。

有中小型IM场景下,消息ID可以简单处理,反正只要唯一就行,而中大型场景下,因为要考虑到分布式的性能、一致性等,所以要考虑的问题点又是另一回事。

总之就是,IM的消息ID生成这件事,可深可浅,看似简单但实际可探索的边界可以很大,这也是为什么即时通讯网为此专门整理了《IM消息ID技术专题》系列文章的原因。做技术所谓厚积薄发,了解的越多,你的技术可操作空间也就越大,希望随着这个系列文章的阅读,可以为你在ID生成这一块的技术选型带来更多有益的启发。

另外,因为即时通讯网主要关注的是即时通讯方面的系统开发,但并不意味着这个系统文章只适用于IM或消息推送等实时通信系统,它同样适用于其它需要唯一ID的应用中。

本文将要分享的是滴滴开源的分布式ID生成器Tinyid的技术原理、使用方法等等,希望能进一步为你打开这方面的技术视野。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

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

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

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

2、专题目录

本文是“IM消息ID技术专题”系列文章的第6篇,专题总目录如下:

IM消息ID技术专题(一):微信的海量IM聊天消息序列号生成实践(算法原理篇)

IM消息ID技术专题(二):微信的海量IM聊天消息序列号生成实践(容灾方案篇)

IM消息ID技术专题(三):解密融云IM产品的聊天消息ID生成策略

IM消息ID技术专题(四):深度解密美团的分布式ID生成算法

IM消息ID技术专题(五):开源分布式ID生成器UidGenerator的技术实现

IM消息ID技术专题(六):深度解密滴滴的高性能ID生成器(Tinyid)》(* 本文

3、什么是Tinyid?

Tinyid是滴滴用Java开发的一款分布式id生成系统,基于数据库号段算法实现。

Tinyid是在美团的ID生成算法Leaf的基础上扩展而来,支持数据库多主节点模式,它提供了REST API和Java客户端两种获取方式,相对来说使用更方便。不过,和美团的Leaf算法不同的是,Tinyid只支持号段一种模式(并不支持Snowflake模式)。(有关美团的Leaf算法,可以详读《IM消息ID技术专题(四):深度解密美团的分布式ID生成算法

Tinyid目前在滴滴客服部门使用,且通过tinyid-client方式接入,每天生成的是亿级别的id。性能上,据称单实例能达到1千万QPS。

它的开源地址是:

PS:滴滴在Tinyid工程页面写了一句话,“tinyid,并不是滴滴官方产品,只是滴滴拥有的代码”,我语文不好,这句该怎么理解呢?

4、Tinyid的主要技术特性

主要特性总结一下就是:

  • 1)全局唯一的long型ID:即id极限数量是2的64次方;
  • 2)趋势递增的id:趋势递增的意思是,id是递增但不一定是连续的(这跟微信的ID生成策略类似);
  • 3)提供 http 和 java-client 方式接入;
  • 4)支持批量获取ID;
  • 5)支持生成1,3,5,7,9…序列的ID;
  • 6)支持多个db的配置。

适用的场景:只关心ID是数字,趋势递增的系统,可以容忍ID不连续,可以容忍ID的浪费。

不适用场景:像类似于订单ID的业务,因生成的ID大部分是连续的,容易被扫库、或者推算出订单量等信息。

另外:微信的聊天消息ID生成算法也是基于号段、趋势递增这种逻辑,如果有兴趣,可以详见:《IM消息ID技术专题(一):微信的海量IM聊天消息序列号生成实践(算法原理篇)》。

5、Tinyid的技术优势

性能方面:

  • 1)http方式:访问性能取决于http server的能力,网络传输速度;
  • 2)java-client方式:id为本地生成,号段长度(step)越长,qps越大,如果将号段设置足够大,则qps可达1000w+。

可用性方面:

  • 1)当db不可用时,因为server有缓存,所以还可以使用一段时间;
  • 2)如果配置了多个db,则只要有1个db存活,则服务可用;
  • 3)使用tiny-client时,只要server有一台存活,则理论上server全挂,因为client有缓存,也可以继续使用一段时间。

6、Tinyid的技术原理详解

6.1 ID生成系统的技术要点

在简单系统中,我们常常使用db的id自增方式来标识和保存数据,随着系统的复杂,数据的增多,分库分表成为了常见的方案,db自增已无法满足要求。

这时候全局唯一的id生成系统就派上了用场,当然这只是id生成其中的一种应用场景。

那么,一个成熟的id生成系统应该具备哪些能力呢?

  • 1)唯一性:无论怎样都不能重复,id全局唯一是最基本的要求;
  • 2)高性能:基础服务尽可能耗时少,如果能够本地生成最好;
  • 3)高可用:虽说很难实现100%的可用性,但是也要无限接近于100%的可用性;
  • 4)易用性:能够拿来即用,接入方便,同时在系统设计和实现上要尽可能的简单。

6.2 Tinyid的实现原理

我们先来看一下最常见的id生成方式,db的auto_increment,相信大家都非常熟悉。

我也见过一些同学在实战中使用这种方案来获取一个id,这个方案的优点是简单,缺点是每次只能向db获取一个id,性能比较差,对db访问比较频繁,db的压力会比较大。

那么,是不是可以对这种方案优化一下呢?可否一次向db获取一批id呢?答案当然是可以的。

一批id,我们可以看成是一个id范围,例如(1000,2000],这个1000到2000也可以称为一个“号段”,我们一次向db申请一个号段,加载到内存中,然后采用自增的方式来生成id,这个号段用完后,再次向db申请一个新的号段,这样对db的压力就减轻了很多,同时内存中直接生成id,性能则提高了很多。

PS:简单解释一下什么是号段模式:

号段模式就是从数据库批量的获取自增ID,每次从数据库取出一个号段范围,例如 (1,1000] 代表1000个ID,业务服务将号段在本地生成1~1000的自增ID并加载到内存。

那么保存db号段的表该怎设计呢?我们继续往下看。

6.3 DB号段算法描述

如上表,我们很容易想到的是db直接存储一个范围(start_id,end_id],当这批id使用完毕后,我们做一次update操作,update start_id=2000(end_id), end_id=3000(end_id+1000),update成功了,则说明获取到了下一个id范围。仔细想想,实际上start_id并没有起什么作用,新的号段总是(end_id,end_id+1000]。

所以这里我们更改一下,db设计应该是这样的:

如上表所示:

  • 1)我们增加了biz_type,这个代表业务类型,不同的业务的id隔离;
  • 2)max_id则是上面的end_id了,代表当前最大的可用id;
  • 3)step代表号段的长度,可以根据每个业务的qps来设置一个合理的长度;
  • 4)version是一个乐观锁,每次更新都加上version,能够保证并发更新的正确性 。

那么我们可以通过如下几个步骤来获取一个可用的号段:

A、查询当前的max_id信息:select id, biz_type, max_id, step, version from tiny_id_info where biz_type='test';

B、计算新的max_id: new_max_id = max_id + step;

C、更新DB中的max_id:update tiny_id_info set max_id=#{new_max_id} , verison=version+1 where id=#{id} and max_id=#{max_id} and version=#{version};

D、如果更新成功,则可用号段获取成功,新的可用号段为(max_id, new_max_id];

E、如果更新失败,则号段可能被其他线程获取,回到步骤A,进行重试。

6.4 号段生成方案的简单架构

如上述内容,我们已经完成了号段生成逻辑。

那么我们的id生成服务架构可能是这样的:

如上图,id生成系统向外提供http服务,请求经过我们的负载均衡router,到达其中一台tinyid-server,从事先加载好的号段中获取一个id。

如果号段还没有加载,或者已经用完,则向db再申请一个新的可用号段,多台server之间因为号段生成算法的原子性,而保证每台server上的可用号段不重,从而使id生成不重。

可以看到:

  • 1)如果tinyid-server如果重启了,那么号段就作废了,会浪费一部分id;
  • 2)同时id也不会连续;
  • 3)每次请求可能会打到不同的机器上,id也不是单调递增的,而是趋势递增的(不过这对于大部分业务都是可接受的)。

6.5 简单架构的问题

到此一个简单的id生成系统就完成了,那么是否还存在问题呢?

回想一下我们最开始的id生成系统要求:高性能、高可用、简单易用。

在上面这套架构里,至少还存在以下问题:

  • 1)当id用完时需要访问db加载新的号段,db更新也可能存在version冲突,此时id生成耗时明显增加;
  • 2)db是一个单点,虽然db可以建设主从等高可用架构,但始终是一个单点;
  • 3)使用http方式获取一个id,存在网络开销,性能和可用性都不太好。

6.6 优化办法及最终架构

1)双号段缓存:

对于号段用完需要访问db,我们很容易想到在号段用到一定程度的时候,就去异步加载下一个号段,保证内存中始终有可用号段,则可避免性能波动。

2)增加多db支持:

db只有一个master时,如果db不可用(down掉或者主从延迟比较大),则获取号段不可用。实际上我们可以支持多个db,比如2个db,A和B,我们获取号段可以随机从其中一台上获取。那么如果A,B都获取到了同一号段,我们怎么保证生成的id不重呢?tinyid是这么做的,让A只生成偶数id,B只生产奇数id,对应的db设计增加了两个字段,如下所示

delta代表id每次的增量,remainder代表余数,例如可以将A,B都delta都设置2,remainder分别设置为0,1则,A的号段只生成偶数号段,B是奇数号段。通过delta和remainder两个字段我们可以根据使用方的需求灵活设计db个数,同时也可以为使用方提供只生产类似奇数的id序列。

3)增加tinyid-client:

使用http获取一个id,存在网络开销,是否可以本地生成id?

为此我们提供了tinyid-client,我们可以向tinyid-server发送请求来获取可用号段,之后在本地构建双号段、id生成,如此id生成则变成纯本地操作,性能大大提升,因为本地有双号段缓存,则可以容忍tinyid-server一段时间的down掉,可用性也有了比较大的提升。

4)tinyid最终架构:

最终我们的架构可能是这样的:

下面是更具体的代码调用逻辑:

如上图所示,下面是关于这个代码调用逻辑图的说明:

  • 1)nextId和getNextSegmentId是tinyid-server对外提供的两个http接口;
  • 2)nextId是获取下一个id,当调用nextId时,会传入bizType,每个bizType的id数据是隔离的,生成id会使用该bizType类型生成的IdGenerator;
  • 3)getNextSegmentId是获取下一个可用号段,tinyid-client会通过此接口来获取可用号段;
  • 4)IdGenerator是id生成的接口;
  • 5)IdGeneratorFactory是生产具体IdGenerator的工厂,每个biz_type生成一个IdGenerator实例。通过工厂,我们可以随时在db中新增biz_type,而不用重启服务;
  • 6)IdGeneratorFactory实际上有两个子类IdGeneratorFactoryServer和IdGeneratorFactoryClient,区别在于,getNextSegmentId的不同,一个是DbGet,一个是HttpGet;
  • 7)CachedIdGenerator则是具体的id生成器对象,持有currentSegmentId和nextSegmentId对象,负责nextId的核心流程。nextId最终通过AtomicLong.andAndGet(delta)方法产生。

具体的代码实现,有兴趣可以直接阅读源码:

7、Tinyid的最佳实践

1)tinyid-server推荐部署到多个机房的多台机器:

多机房部署可用性更高,http方式访问需使用方考虑延迟问题。

2)推荐使用tinyid-client来获取id,好处如下:

a、id为本地生成(调用AtomicLong.addAndGet方法),性能大大增加;

b、client对server访问变的低频,减轻了server的压力;

c、因为低频,即便client使用方和server不在一个机房,也无须担心延迟;

d、即便所有server挂掉,因为client预加载了号段,依然可以继续使用一段时间

注:使用tinyid-client方式,如果client机器较多频繁重启,可能会浪费较多的id,这时可以考虑使用http方式。

3)推荐db配置两个或更多:

db配置多个时,只要有1个db存活,则服务可用 多db配置,如配置了两个db,则每次新增业务需在两个db中都写入相关数据。

8、Tinyid该怎么调用?

关于怎么调用。鉴于篇幅原因,就不再具体去写了,有兴趣的话,可以读一下这篇《Tinyid:滴滴开源千万级并发的分布式ID生成器》。

9、参考资料

[1] 面试总被问分布式ID怎么办? 滴滴(Tinyid)甩给他

[2] Tinyid:滴滴开源千万级并发的分布式ID生成器

[3] tinyid工程中文readme

[4] 滴滴开源的Tinyid如何每天生成亿级别的ID?

附录:更多IM开发热门技术文章

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

移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端IM开发者必读(二):史上最全移动弱网络优化方法总结

从客户端的角度来谈谈移动端IM的消息可靠性和送达机制

现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障

移动端IM中大规模群消息的推送如何保证效率、实时性?

移动端IM开发需要面对的技术问题

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

请问有人知道语音留言聊天的主流实现方式吗?

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

IM消息送达保证机制实现(二):保证离线消息的可靠投递

如何保证IM实时消息的“时序性”与“一致性”?

一个低成本确保IM消息时序的方法探讨

IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?

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

谈谈移动端 IM 开发中登录请求的优化

移动端IM登录时拉取数据如何作到省流量?

浅谈移动端IM的多点登录和消息漫游原理

完全自已开发的IM该如何设计“失败重试”机制?

自已开发IM有那么难吗?手把手教你自撸一个Andriod版简易IM (有源码)

IM开发基础知识补课(六):数据库用NoSQL还是SQL?读这篇就够了!

适合新手:从零开发一个IM服务端(基于Netty,有完整源码)

拿起键盘就是干:跟我一起徒手开发一套分布式IM系统

适合新手:手把手教你用Go快速搭建高性能、可扩展的IM系统(有源码)

IM里“附近的人”功能实现原理是什么?如何高效率地实现它?

IM开发基础知识补课(七):主流移动端账号登录方式的原理及设计思路

IM要做手机扫码登录?先看看微信的扫码登录功能技术原理

IM开发宝典:史上最全,微信各种功能参数和逻辑规则资料汇总

IM开发干货分享:我是如何解决大量离线消息导致客户端卡顿的

IM开发干货分享:如何优雅的实现大量离线消息的可靠投递

IM开发干货分享:有赞移动端IM的组件化SDK架构设计实践

>> 更多同类文章 ……

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:点此进入,原文链接是:http://www.52im.net/thread-3129-1-1.html

posted @ 2020-09-08 22:31 Jack Jiang 阅读(99) | 评论 (0)编辑 收藏

     摘要: 本文由小米信息技术团队研发工程师陈刚原创,原题“当我们在谈论高并发的时候究竟在谈什么?”,为了更好的内容呈现,即时通讯网收录时有修订和改动。1、引言在即时通讯网社区里,多是做IM、消息推送、客服系统、音视频聊天这类实时通信方面的开发者,在涉及到即时通讯技术时聊的最多的话题就是高并发、高吞吐、海量用户。代码还没开始写,就考虑万一哪天这IM用户量破百万、千万该怎么办的问题,是多...  阅读全文

posted @ 2020-09-03 23:08 Jack Jiang 阅读(151) | 评论 (0)编辑 收藏

本文内容编写时,参考了网上的资料,详见“参考资料”部分,感谢分享者。

1、引言

这个系列文章已经整理了10篇,但都没有涉及到具体的红包算法实现,主要有以下两方面原因。

一方面是各社交/IM产品中的红包功能同质化严重,红包算法的“可玩性”便是“核心竞争力所在”,这是同质化功能的差异化竞争思路,不会随便公开。

另一方面,市场上还存在各种抢红包插件这类灰产存在,一旦公开这些算法,很可能又被这帮插件开发者们搞出什么幺蛾子。

所以,这样的情况下,如果要做社交/IM产品中的红包功能,红包随便算法该怎么实现,基本上只能自已琢磨,很难找到大厂算法直接套用。

本着即时通讯网一贯的im知识传播精神,我收集整理并参考了大量的网上资料,综合了比较靠谱的信息来源,便有了本文。本文根据有限的资料,分享了微信红包随机算法实现中的一些技术要点,并整理了两种比较靠谱的红包算法实现思路(含可运行的实现代码),希望能给你的红包算法开发带来启发。

申明:本文资料整理自网络,仅供学习研究之用,如有不妥,请通知作者。

学习交流:

- 即时通讯开发交流5群:215477170 [推荐]

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

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK  [推荐]

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:点此进入,原文链接是:http://www.52im.net/thread-3125-1-1.html

2、系列文章

3、微信红包算法要点汇总

这是目前能找到的仅有的一份,有微信团队人员参与的微信红包算法技术要点的讨论资料。分享于2015年,差不多是微信红包刚火没多久,大概是微信技术团队的人当时没有现在这些技术之外的顾虑,所以作了有限的分享,资料难得,本次重新整理了一下,可以作为参考资料使用。以下是资料正文。

资料来源:来自InfoQ的某架构群的技术讨论,由朱玉华整理(个人博客是:zhuyuhua.com(目前已无法访问))。

资料背景:起因是有朋友在朋友圈咨询微信红包的架构,于是在微信团队成员参与讨论的情况下,我(指“朱玉华”)整理了这次讨论的技术要点,也就是下面的内容(内容为问答形式)。

3.1、算法实现的技术要点

问:微信的金额什么时候算?

答:微信金额是拆的时候实时算出来,不是预先分配的,采用的是纯内存计算,不需要预算空间存储。

为什么采取实时计算金额?原因是:实时效率更高,预算才效率低下。预算还要占额外存储。因为红包只占一条记录而且有效期就几天,所以不需要多大空间。就算压力大时,水平扩展机器是。

问:关于实时实时性,为什么明明抢到红包,点开后发现没有?

答:2014年的红包一点开就知道金额,分两次操作,先抢到金额,然后再转账。

2015年的红包的拆和抢是分离的,需要点两次,因此会出现抢到红包了,但点开后告知红包已经被领完的状况。进入到第一个页面不代表抢到,只表示当时红包还有。

问:关于分配算法,红包里的金额怎么算?为什么出现各个红包金额相差很大?

答:随机,额度在 0.01 和剩余平均值 2 之间。 例如:发 100 块钱,总共 10 个红包,那么平均值是 10 块钱一个,那么发出来的红包的额度在 0.01元~20元之间波动。

当前面 3 个红包总共被领了 40 块钱时,剩下 60 块钱,总共 7 个红包,那么这 7 个红包的额度在:0.01~(60/7 * 2)=17.14之间。

注意:这里的算法是每被抢一个后,剩下的会再次执行上面的这样的算法(Tim老师也觉得上述算法太复杂,不知基于什么样的考虑)。

这样算下去,会超过最开始的全部金额,因此到了最后面如果不够这么算,那么会采取如下算法:保证剩余用户能拿到最低1分钱即可。

如果前面的人手气不好,那么后面的余额越多,红包额度也就越多,因此实际概率一样的。

问:红包的设计

答:微信从财付通拉取金额数据过来,生成个数/红包类型/金额放到redis集群里,app端将红包ID的请求放入请求队列中,如果发现超过红包的个数,直接返回。根据红包的逻辑处理成功得到令牌请求,则由财付通进行一致性调用,通过像比特币一样,两边保存交易记录,交易后交给第三方服务审计,如果交易过程中出现不一致就强制回归。

问:并发性处理:红包如何计算被抢完?

答:cache会抵抗无效请求,将无效的请求过滤掉,实际进入到后台的量不大。cache记录红包个数,原子操作进行个数递减,到 0 表示被抢光。财付通按照 20万笔每秒入账准备,但实际还不到 8万每秒

问:通如何保持8w每秒的写入?

答:多主sharding,水平扩展机器。

问:数据容量多少?

答:一个红包只占一条记录,有效期只有几天,因此不需要太多空间。

问:查询红包分配,压力大不?

答:抢到红包的人数和红包都在一条cache记录上,没有太大的查询压力。

问:一个红包一个队列?

答:没有队列,一个红包一条数据,数据上有一个计数器字段。

问:有没有从数据上证明每个红包的概率是不是均等?

答:不是绝对均等,就是一个简单的拍脑袋算法。

问:拍脑袋算法,会不会出现两个最佳?

答:会出现金额一样的,但是手气最佳只有一个,先抢到的那个最佳。

问:每领一个红包就更新数据么?

答:每抢到一个红包,就cas更新剩余金额和红包个数。

问:红包如何入库入账?

答:数据库会累加已经领取的个数与金额,插入一条领取记录。入账则是后台异步操作。

问:入帐出错怎么办?比如红包个数没了,但余额还有?

答:最后会有一个take all操作。另外还有一个对账来保障。

问:既然在抢的时候有原子减了就不应该出现抢到了拆开没有的情况?

答:这里的原子减并不是真正意义上的原子操作,是Cache层提供的CAS,通过比较版本号不断尝试。

问:cache和db挂了怎么办?

答:主备 +对账。

问:为什么要分离抢和拆?

答:总思路是设置多层过滤网,层层筛选,层层减少流量和压力。

这个设计最初是因为抢操作是业务层,拆是入账操作,一个操作太重了,而且中断率高。 从接口层面看,第一个接口纯缓存操作,搞压能力强,一个简单查询Cache挡住了绝大部分用户,做了第一道筛选,所以大部分人会看到已经抢完了的提示。

问:抢到红包后再发红包或者提现,这里有什么策略吗?

答:大额优先入账策略。

针对上面的技术要点,有人还画了张原理图(这是网上能找到的相对清晰的版本): 

3.2、微信抢红包的过程模拟

针对上节中整理的资料,当有人在微信群里发了一个 N 人的红包、总金额 M 元,后台大概的技术逻辑如下。

3.2.1)发红包后台操作:

  • 1)在数据库中增加一条红包记录,存储到CKV,设置过期时间;
  • 2)在Cache(可能是腾讯内部kv数据库,基于内存,有落地,有内核态网络处理模块,以内核模块形式提供服务))中增加一条记录,存储抢红包的人数N。

3.2.2)抢红包后台操作:

  • 1)抢红包分为抢和拆:抢操作在Cache层完成,通过原子减操作进行红包数递减,到0就说明抢光了,最终实际进入后台拆操作的量不大,通过操作的分离将无效请求直接挡在Cache层外面。
  • 这里的原子减操作并不是真正意义上的原子减操作,是其Cache层提供的CAS,通过比较版本号不断尝试,存在一定程度上的冲突,冲突的用户会放行,让其进入下一步拆的操作,这也解释了为啥有用户抢到了拆开发现领完了的情况。
  • 2)拆红包在数据库完成:通过数据库的事务操作累加已经领取的个数和金额,插入一条领取流水,入账为异步操作,这也解释了为啥在春节期间红包领取后在余额中看不到。
  • 拆的时候会实时计算金额,其金额为1分到剩余平均值2倍之间随机数,一个总金额为M元的红包,最大的红包为 M * 2 /N(且不会超过M),当拆了红包后会更新剩余金额和个数。财付通按20万笔每秒入账准备,实际只到8万每秒。

4、微信红包算法模拟实现1(含代码)

根据上一节的微信红包随机算法技术要点资料,实现了一个算法,以下供参考。(注:本节内容引用自《微信红包随机算法初探》一文)

4.1、算法约定

算法很简单,跟微信的算法一样,不是提前算好,而是抢红包时计算。

即:金额随机,额度在0.01和剩余平均值*2之间。(参见上一节的 “关于分配算法,红包里的金额怎么算?为什么出现各个红包金额相差很大?” 内容)

4.2、代码实现

算法的逻辑主要是:

public static double getRandomMoney(RedPackage _redPackage) {

    // remainSize 剩余的红包数量

    // remainMoney 剩余的钱

    if(_redPackage.remainSize == 1) {

        _redPackage.remainSize--;

        return (double) Math.round(_redPackage.remainMoney * 100) / 100;

    }

    Random r     = newRandom();

    double min   = 0.01; //

    double max   = _redPackage.remainMoney / _redPackage.remainSize * 2;

    double money = r.nextDouble() * max;

    money = money <= min ? 0.01: money;

    money = Math.floor(money * 100) / 100;

    _redPackage.remainSize--;

    _redPackage.remainMoney -= money;

    return money;

}

LeftMoneyPackage数据结构如下:

class RedPackage {

    int remainSize;

    double remainMoney;

}

测试时初始化相关数据是:

static void init() {

    redPackage.remainSize  = 30;

    redPackage.remainMoney = 500;

}

附件是可以运行的完整Java代码文件:

(无法上传附件,如有需要请从此链接处下载:http://www.52im.net/thread-3125-1-1.html

4.3、测试结果

4.3.1 单次测试

按上述代码中的初始化数据(30人抢500块),执行了两次,结果如下:

//第一次

15.69   21.18   24.11   30.85   0.74    20.85   2.96    13.43   11.12   24.87   1.86    19.62   5.97    29.33   3.05    26.94   18.69   34.47   9.4 29.83   5.17    24.67   17.09   29.96   6.77    5.79    0.34    23.89   40.44   0.92

//第二次

10.44   18.01   17.01   21.07   11.87   4.78    30.14   32.05   16.68   20.34   12.94   27.98   9.31    17.97   12.93   28.75   12.1    12.77   7.54    10.87   4.16    25.36   26.89   5.73    11.59   23.91   17.77   15.85   23.42   9.77

第一次随机红包数据图表如下: 

▲ x轴为抢的顺序,y轴为抢到的金额

第二次随机红包数据图表如下:

▲ x轴为抢的顺序,y轴为抢到的金额

4.3.2 多次均值

重复执行200次的均值:

▲ x轴为抢的顺序,y轴为该次抢到金额的概率均值

重复执行2000次的均值: 

▲ x轴为抢的顺序,y轴为该次抢到金额的概率均值

从以上两张图的均值结果可以看出,这个算法中每一次能抢到的金额几率几乎是均等的,从随机性来说比较合理。

5、微信红包算法模拟实现2(含代码)

我对随机算法很感兴趣,正巧最近研究的方向有点偏随机数这块,所以也自己实现了一下微信的红包分发算法(算法要点参考的是本文第三节内容)。(注:本节内容引用自《微信红包算法的分析》一文)

5.1、代码实现

从第三节中可以了解到,微信并不是一开始就预分配所有的红包金额,而是在拆时进行计算的。这样做的好处是效率高,实时性。本次的代码中,红包具体是怎么计算的呢?请参见第4节中的“关于分配算法,红包里的金额怎么算?为什么出现各个红包金额相差很大?”。

那基于这个思想,可以写出一个红包分配算法:

/**

 * 并不完美的红包算法

 */

public static double rand(double money, int people, List<Double> l) {

    if(people == 1) {

        double red = Math.round(money * 100) / 100.0;

        l.add(red);

        return0;

    }

    Random random = newRandom();

    double min = 0.01;

    double max = money / people * 2.0;

    double red = random.nextDouble() * max;

    red = red <= min ? min : red;

    red = Math.floor(red * 100) / 100.0;

    l.add(red);

    double remain = Math.round((money - red) * 100) / 100.0;

    return remain;

}

算法整体思路很简单,就在在最后一个人的时候要注意,此时不进行随机数计算,而是直接将剩余金额作为红包。

5.2、第一次分析

采用上述算法,可以对用户的抢红包行为做分析。这里的模仿行为是:30 元的红包,10 人抢。操作 100 次。

可以得出如下结果: 

▲ x轴为抢的顺序,y轴为该次抢到金额

从上图中可以很轻易的看出来,越后抢的人,风险越大,同时收益也越大,有较大几率获得“手气最佳”。

那红包面值的分布性如何呢?

▲ x轴为抢的顺序,y轴为该次抢到金额重复 100 次后的平均值

从上图可以看出,都是比较接近平均值(3 元)的。

那重复 1000 次呢?

▲ x轴为抢的顺序,y轴为该次抢到金额重复 1000 次后的平均值

更接近了。。。

可以看出,这个算法可以让大家抢到红包面额在概率上是大致均等的。

5.3、不足之处

有人提出了这个问题: 

他接下来放了好几张他试验的截图。我这里取了一张,如果有兴趣,可以去知乎的问题里查看更多图片。

而此时,我哥们在和我的在讨论中,也告诉我,确实存在某个规律,可能让最后一个抢的人占有某些微小的优势,比如,多 0.01 的之类。

例如发 6 个,总额 0.09 的包,最后一个抢的有极大概率是 0.03。

然而我之前的代码却没办法体现出这一点。

比如 10 人拆 0.11 元的包,我的结果是:

可见以上代码还存在不足之处。

于是我就有一个猜测:

微信可能不是对全金额进行随机的,可能在派发红包之前,已经对金额做了处理,比如,事先减去(红包个数*0.01),之后在每个红包的随机值基础上加 0.01,以此来保证每个红包最小值都是 0.01。

这个猜测或许可以解开那位知友和我哥们这边的疑惑。

5.4、完善算法

在原先的基础上对代码进行简单的修正:

public static double rand(double money, int people, List<Double> l) {

    if(people == 1) {

        double red = Math.round(money * 100) / 100.0;

        l.add(red+0.01);

        return 0;

    }

    Random random = newRandom();

    double min = 0;

    double max = money / people * 2.0;

    double red = random.nextDouble() * max;

    red = red <= min ? min : red;

    red = Math.floor(red * 100) / 100.0;

    l.add(red+0.01);

    double remain = Math.round((money - red) * 100) / 100.0;

    return remain;

}

这个算法,在第一次调用时传入 money 的值是总金额减去红包数*0.01,大概像这样:

_money = _money - people * 0.01;

5.5、第二次分析

5.5.1 验证上次的不足之处

1)10 人抢 0.11 元的包:

2)2 人抢 0.03 元的包: 

3)6 人抢 0.09 的包:

5.5.2 修改后的代码会不会对已知结论造成影响?

30 元的红包,10 人抢,操作 100 次。

▲ x轴为抢的顺序,y轴为该次抢到金额 

▲ x轴为抢的顺序,y轴为该次抢到金额重复 100 次后的平均值

由上面两图可见,结论基本上没有改变。

5.6、结论

经过上述代码实践可知:

1)先抢后抢,金额期望都是相同的;

2)微信的红包算法很可能是预先分配给每人 0.01 的“底额”;

3)后抢者风险高,收益大。

5.7、补充

上几张后面测试的图,补充一下之前的观点,发 n 个红包,总金额是(n+1)*0.01,最后一个领的一定是手气最佳。

 

大家也可以试试。

以上,大概可以证明,微信红包是在分配前先给每个人 0.01 的最低金额的!

6、参考资料

[1] 微信红包随机算法初探

[2] 微信红包算法的分析

[3] 微信红包的架构设计简介

[4] 微信红包的随机算法是怎样实现的?

另外,知乎上对于微信红包算法的讨论问题很多人参与,有兴趣可以上去看看,或许会有更多启发:《微信红包的随机算法是怎样实现的?》。

附录:更多微信相关资源

IM开发宝典:史上最全,微信各种功能参数和逻辑规则资料汇总

微信本地数据库破解版(含iOS、Android),仅供学习研究 [附件下载]

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

posted @ 2020-08-26 14:32 Jack Jiang 阅读(124) | 评论 (0)编辑 收藏

本文由手机淘宝技术团队原创分享,吴志华(天施)、洪海(孤星)、陈虓将(仲升)等专家参与了本文创作,首次发表于公众号“淘系技术”,收录整理时有修订和改动。

1、引言

移动端网络的优化是超级APP们永恒的话题,而对于无线电商来说这更为重要,因为网络请求体验跟用户的购买行为息息相关。

手机淘宝从过去的HTTP API网关,到后来扛住双十一战场主要流量的自研高性能、全双工、安全的ACCS(阿里云通道服务),无论是基础架构的演进、网络调优、协议的优化、异地多活、网络调度上,都有不少宝贵的经验与大家分享,本文借此机会总结了整个技术演进过程。

* 阅读对象:本文属于移动端网络优化的深水区总结性文章,适合有一定移动端网络应用经验的开发者阅读(尤其对移动弱网有一定了解的),初学者如果没有相关知识积累的话,可以简单了解无需深入。如果你对移动弱网很有兴趣,可以进一步阅读本文末尾“附录”部分的推荐文章。

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:点此进入,原文链接是:http://www.52im.net/thread-3110-1-1.html

2、相关文章

Netty干货分享:京东京麦的生产级TCP网关技术实践总结

知乎技术分享:知乎千万级并发的高性能长连接网关技术实践

手机淘宝消息推送系统的架构与实践(音频+PPT) [附件下载]

3、技术背景

回想移动电商在双十一业务开始兴起的时候,当时双十一当天移动成交243亿占整体571亿的42.6%。

业务高速发展希望更多主动推送去触达用户,一些新的玩法和互动形式,需要连接买家与买家、买家与卖家、买家与达人,因为没有有效的通道能力,业务采取的是不停去轮询服务器,一来对服务器造成不必要的压力,二来对于用户手机的电量流量也是极大的浪费,关键在双十五这种大促的情况下,不必要的请求过大甚至会导致后端集群限流,从而影响到用户体验。

信息传播形态的变化的背后是移动化带来新的技术特征导致的结果。移动电商领域,手机淘宝一直是先行者。移动电商从最初的复制WEB的业务形态到移动特性不断涌现,更多的互动形式的出现,向社交化、娱乐化不断迈进的今天,一个单纯的商品的陈列架形式已经不能满足业务的需求。

业务上需要实时的触达用户,充分发挥移动的特性,将消费时间的碎片利用起来,事实也证明了用户的消费时间随着移动化的进程不断发生变化,逐步分布到全天的碎片时间中。同时货架形态也在向社区化、娱乐化的方向发展,这些都对网络层连接用户有了更高的要求。更多的媒体形态和展示方式,对网络层提出了更多元的要求。

大家可以关注到手机淘宝内的消息盒子这些产品都是业务求变的体现,业务的变化倒逼技术的前进。

4、移动网络环境的挑战性一直都存在

移动网络的速度随便3g、4g、5g的普及,速度有很大提升,但网络环境的多样性和差异性使移动网络的环境更加复杂,在过去双十一前还常遇到一些移动网络劫持的事情。网络劫持这块问题的排查效率很低,需要找到用户、复现现场,甚至找网工、运营商配合排查,一查就是几天过去。

同时在我们的舆情反馈上总是看到用户在说“某个页面加载中、页面打不开、请求很慢、打开某个功能很慢”,面对这些问题过去我们是没有太好的办法,只能猫抓耗子一桩桩去排雷很被动。很多网络的问题是偶现的,一旦错过现在就无从查起。

诸如此类的问题,背后的原因很多:

  • 1)运营商问题;
  • 2)机房部署原因;
  • 3)客户端SDK Bug;
  • 4)弱网和网络抖动;
  • 5)DNS劫持和数据篡改。

在PC时代,我们访问网站的接入条件是相对恒定的,所以在开发时很少考虑网络对用户体验的影响。但是移动APP则不然,尤其是在国内,基础的移动网络环境还不算太好,而且我们有很多用户的访问是发生在地铁、公交车这样的移动环境下,移动基站的频繁切换进一步增加了网络的不稳定。从手机淘宝的数据可以看出,我们每天活跃用户中有不少来自于弱网环境。如果端到云的连接不稳定、高延时,那么所有的用户体验都无从谈起。

基础网络的效率就像一辆列车,时延是火车的速度(启动时间),而带宽就像火车的车厢装载量,整个传输的物理链路就像火车的铁轨。目前现实条件下的移动网络条件非常复杂,我们的目标很简单,就是想让所有用户都能在手机淘宝获得流畅的体验。

下面这张图,能够让大家更加直观的了解国内的移动网络环境。描述了从用户到IDC的端到端的路由情况,不仅数据传输耗时长且丢包率高,同时安全性也是相当糟糕的,DNS劫持、内容劫持在中国就是家常便饭。

因此,我们在改善网络通道上有很多的事情可以去做,去探索突破运营商基础网络的限制,力争为用户创造极致的购物体验。

移动端的DNS问题相当普遍,可以详读以下专题文章:

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

美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

百度APP移动端网络深度优化实践分享(一):DNS优化篇

移动端网络优化之HTTP请求的DNS优化

5、整体技术架构

为了满足移动电商业务高速发展的需求,我们决定打造一个世界级的网络接入服务,构建一个无线网络下”水、电、煤“ 一样的基础设施。

这样一个基础设施需要做到的四个目标:

  • 1)全双工;
  • 2)低延时;
  • 3)高安全;
  • 4)开放。

在这四个目标之上是围绕这个接入服务配套的运维体系,帮助最终用户取得良好的端上体验的同时,帮助开发者快速构建自己的业务。 

如上图所示,在整个接入服务上我们划分为两层:

  • 1)接入网关:负责连接的保持、消息的解析、消息的分发;
  • 2)应用网关:实现各种应用层协议:API、SYNC、RPC、PUSH等,在应用网关的背后是具体的业务系统。

同时我们建立了一个统一调度服务,而不是采用传统的DNS,调度服务是我们的控制中心,通过它我们可以强有力的指挥我们的客户端,并且不会受到DNS污染的影响。

与服务端的分层架构对应的是客户端的SDK,最底层的统一网络库SDK集中了我们对网络优化的策略,并向上为各个应用网关技术的SDK提供API。

基于上面的开放架构,业务方可以选择直接开放具体的后端服务对接不同的应用网关,不需要了解网络背后的细节,并通过应用网关如API网关提供的开发工具快速生成客户端代码。业务方也可以基于这个接入层设计自己的协议。

统一接入层集中管理了用户的设备、在线状态,并提供信息的双向传递能力。

如下图所示:

网关将致力于解决中间网络的通讯,为上层的服务提供高质量的双向通讯能力。

6、稳定性与容灾

稳定性与容灾是服务端中间件永恒的主题,统一接入层这样一个汇聚网关收益和风险是并存的,一旦这个入口故障了,波及的用户范围是不可想象的,如何做的更加稳定,是一个巨大的挑战。

6.1 网关架构的优化

对于一个统一网关来说,对接的业务网关的信息传递特点是不一样的,大部分的业务在全天都是比较平缓的,但是个别营销类业务会在短时间内发布海量的信息,这样的信息发布会抢占网关的大量资源,对于用户的正常访问会产生影响。

举个例子:push服务需要通过网关推送2亿条消息,而这些消息需要在短时间内全部推送完,而同时网关在为正常的用户的交互提供服务,海量信息的推送和正常的用户交互相互竞争资源,最终会造成正常用户的交互失败,对于业务来说,这是不可接受的。

基于上面的情况考虑,整个网关在布署上分为两个集群:

  • 1)一个集群处理常态的在线用户访问;
  • 2)一个集群处理海量信息的推送。

如下图所示,通过这样的方式,避免了业务形态不同,对统一网关的冲击,将不同的业务形态进行了隔离。

6.2 异地多活

在异地多活的整体方案中,统一网关承担了快速引导流量的职责,也是这一方案顺利实施的一个重要环节。

异地多活是一个多机房的整体方案,在多个地区同时存在对等的多个机房,以用户维度划分,多机房共同承担全量用户的流量;在单个机房发生故障时,故障机房的流量可以快速的被迁引到可用机房,减少故障的恢复时间。

6.2.1)无线接入层单元化的协商机制:

先看一下web端在这异地多活中的实现方式:

从上图可以看到,浏览器的业务器求会发给CDN,由CDN上保存的分发规则,向后续的单元机房分发。

无线端也这样做吗?

  • 1)客户端拥有强大的能力,可以做的更灵活;
  • 2)CDN的分发节点带来更多的机器成本;
  • 3)对于需要双工通讯能力的客户端,消息投递更为复杂。

这些是我们思考与WEB不同的地方,是不是能做些不一样的选择?

如上图所示, 我们借助了客户端的强大能力,利用协商的机制来完成用户的请求正确被分配到不同的单元。

含以下几点:

  • 1)客户端的请求始终带上当前用户归属单元的信息;
  • 2)当请求到达服务端时,服务端判断用户归属单元是否正确,不正确将用户重定向到正确的单元 ;
  • 3)当前请求由网关在服务端上通过跨单元调用保证业务的正确性;
  • 4)当客户端归属单元更新后,后续的请求都会发到正确的单元机房。

6.2.2)无线接入层单元化的旁路调度:

协商机制看起来很不错,这里一个重磅炸弹丢过来了,机房的入口网络断了!

如上图,外网不可用,协商的机会都没有故障单元的用户无法恢复,这时旁路的调度服务出场了。

如上图,我们设计的调度中心这时又承担了单元化的旁路调度职责,当app访问的单元无法访问的时候,app会访问不同单元的调度中心,询问用户的归属单元。通过这种方式取得可用的单元节点,将用户切到正确的单元。这个方案同样适用于单机房的接入层网关不可用的场景。

6.2.3)应用层网关不可用:

某个单元机房的应用层网关不可用,这时等待应用网关排查问题需要的时间比较久,为了达到最快的故障恢复,我们通过开关把修改接入层的转发规则,将流量切到可用的单元。

如下图所示: 

7、端到端网络优化

7.1 统一网络库

在做网络优化一开始,我们想做一个通用的网络库,这个网络库包含策略、httpDNS、SPDY协议等一切系统网络优化需要的方方面面。(如果你对httpDNS不甚了解,可以详读《全面了解移动端DNS域名劫持等杂症:原理、根源、HttpDNS解决方案等》)

上层api网关请求逻辑、推送逻辑、上传下载逻辑对于这样一个通用网络库来说都是业务。在分层上将通用网络库和上层应用逻辑分开、彻底解耦,对长期持续优化网络是很有必要。

如下图所示架构: 

这样架构上分离,可以让我们更专注更系统化去做无线网络优化。

统一网络库的几个重要特性:

  • 1)灵活控制客户端网络行为策略(建连、超时处理、请求协议、是否加密);
  • 2)包含HTTPDNS;
  • 3)支持异地多活;
  • 4)更细粒度控制和调度(域名级和域名下参数级)。

1、2、3、4均由网络调度中心的集群控制,我们希望这个可以做到与业务无关,去掉一些阿里的业务属性后,这个模块大家可以理解为HTTPDNS,可以理解我们在HTTPDNS之外做了大量网络优化的端到端的工作。

7.2 就近就快接入

基于网络库我们实现了一套智能学习的网络策略,智能学习客户端在不同网络环境下建连策略,用户重新回到这个网络环境会给出最优的策略进行快速连接,并定期去更新或淘汰本地cache的历史最优网络策略。

为了建立更加迅速在各自网络下穿透性更好,接入服务器支持了多种协议和端口,客户端建连时可以极速接入网络。

我们有一个重要指标是打开客户端30秒内网络请求成功率,就是关注连的快给用户体验带来的价值。

基于调度中心,我们搭建了一个智能大数据分析平台,将客户端在在网络请求过程中的数据如建连时间、首包收取时间、整包收取时间、ssl握手时间等重要指标收集上来 。根据这些指标分析出网络异常区域,调整我们的就近就快接入规则,甚至推动IDC建设和CDN的布点完善。

7.3 弱网优化和抗抖动

在弱网优化上我们尝试了QUIC协议,在网络延时较高、丢包严重情况下比TCP有更好表现。

线上手机淘宝灰度版本实测切换到QUIC后,平均RT收益有接近20%。考虑QUIC在移动网络可能存在穿透性问题,未来我们将采取SPDY为主,QUIC为辅助的模式来完善我们的网络链接策略。

现在QUIC协议在移动端应用的越来越广泛,有兴趣的话可详细以下文章:

网络编程懒人入门(十):一泡尿的时间,快速读懂QUIC协议

技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解

让互联网更快:新一代QUIC协议在腾讯的技术实践分享

七牛云技术分享:使用QUIC协议实现实时视频直播0卡顿!

同样在一些网络环境较差情况下,我们采取长短链接结合方式,在长链接遇到请求超时或穿透性较差情况,利用短链接HTTP短链接去请求数据(在移动网络环境下HTTP协议尤其HTTP1.0的穿透性是最好的),这样可以在一些极端情况下最大程度保证用户体验。

数据如下图:

网络切换和网络抖动情况下的技术优化也是一个很重要的方面,我们经常遇到移动设备网络切换和信号不稳定的情况,在这种情况我们怎么保证用户的体验?

针对这种情况我们的思路是有策略合理增加重试。我们对一个网络请求以是否发送到socket缓冲区作为分割,将网络请求生命周期划分为“请求开始到发送到 socket缓冲区”和“已经发送到socket缓冲区到请求结束”两个阶段。在阶段一内请求失败了,会根据业务需求帮助业务请求去做重试。阶段二请求失败只针对读操作提供重试能力。

设想一个场景:用户在进电梯发起一个刷新数据请求,进到电梯因为网络抖动的原因网络链接断了,这个时候我们能够合理策略去做重试,这样当用户离开电梯时很可能网络请求重试成功,帮助用户拉到了想要的数据,提升了用户体验和客户端的网络抗抖动能力。

7.4 加密传输1秒钟法则

众所周知的传统https的整个握手流程是非常重的,在网络质量不高的情况下,造成建连过慢,用户体验惨不能睹,甚至都无法完成安全握手。然而从安全的角度我们是需要一个安全的传输通道保护用户的隐私数据。

安全与网络这一对冲突放在我们的面前,需要在技术上有所突破,因此我们自建了一套slight-ssl的技术,参考了tls1.3的协议,通过合并请求,优化加密算法,运用session-ticket等策略,最终在安全和体验之间找到了一个平衡点,在基本不牺牲用户体验的基础上,达到了安全传输的目地, 同时还大幅度提升了服务端的性能。通过技术的创新,我们实现了无线网络加密传输下1秒钟法则。

关于TLS1.3在移动端的应用,也可以详读微信团队分享的这篇《微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解》。

附录:有关移动端弱网方面的资料汇总

IM开发者的零基础通信技术入门(十一):为什么WiFi信号差?一文即懂!

IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!

IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!

IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!

现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障

聊聊iOS中网络编程长连接的那些事

移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端IM开发者必读(二):史上最全移动弱网络优化方法总结

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

美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

百度APP移动端网络深度优化实践分享(一):DNS优化篇

百度APP移动端网络深度优化实践分享(二):网络连接优化篇

百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇

爱奇艺移动端网络优化实践分享:网络请求成功率优化篇

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

5G时代已经到来,TCP/IP老矣,尚能饭否?

微信Mars:微信内部正在使用的网络层封装库,即将开源

如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源

谈谈移动端 IM 开发中登录请求的优化

腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率》 

腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)》 

腾讯原创分享(三):如何大幅压缩移动网络下APP的流量消耗(上篇)》 

IM开发者的零基础通信技术入门(十一):为什么WiFi信号差?一文即懂!

IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!

IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!

IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!

>> 更多同类文章 ……

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

posted @ 2020-08-19 13:49 Jack Jiang 阅读(139) | 评论 (0)编辑 收藏

1、引言

最近在从头重写 MobileIMSDK 的TCP版,自已组织TCP数据帧时就遇到了字节序大小端问题。所以,借这个机会单独整理了这篇文章,希望能加深大家对字节序问题的理解,加强对IM这种基于网络通信的程序在数据传输这一层的知识掌控情况。

程序员在写应用层程序时,一般不需要考虑字节序问题,因为字节序跟操作系统和硬件环境有关,而我们编写的程序要么不需要跨平台(比如只运行在windows),要么需要跨平台时会由Java这种跨平台语言在虚拟机层屏蔽掉了。

但典型情况,当你编写网络通信程序,比如IM聊天应用时,就必须要考虑字节序问题,因为你的数据在这样的场景下要跨机器、跨网络通信,必须解决不同系统、不同平台的字节序问题。

* 阅读对象:本文属于计算机基础知识,特别适合从事网络编程方面工作(比如IM这类通信系统)的程序员阅读。面视时,面视官一般都会聊到这个知识点。

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:点此进入 ,原文链接是:http://www.52im.net/thread-3101-1-1.html

2、什么是字节序?

字节序,是指数据在内存中的存放顺序,当字节数大于1时需要考虑(只有一个字节的情况下,比如char类型,也就不存在顺序问题啦)。

从下图中,可以直观的感受到什么是字节序问题: 

上图片改编自《C语言打印数据的二进制格式-原理解析与编程实现

3、字节序的分类

字节序常被分为两类:

  • 1)Big-Endian(大端字节序):高位字节排放在内存的低地址端,低位字节排放在内存的高地址端(这是人类读写数值的方法);
  • 2)Little-Endian(小端字节序):低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

举个具体的例子,0x1234567 的大端字节序和小端字节序写法如下:

如上图所示:大端小端字节序最小单位1字节,即8bit;大端字节序就是和我们平时写法的顺序一样,从低地址到高地址写入0x01234567;而小端字节序就是和我们平时的写法反过来,因为字节序最小单位为1字节,所以从低地址到高地址写入0x67452301。

4、为什么会存在大端、小端字节序问题?

4.1 比较合理的解释

一个比较合理的解释是说:计算机中电路优先处理低位字节,效率比较高,因为计算机都是从低位开始的,所以计算机内部处理都是小端字节序。

而人类人类读写数值的方法,习惯用大端字节序,所以除了计算机的内部处,其他的场理合都是大端字节序,比如:网络传输和文件储存时都是用的大端字节序(关于网络字节序,会在后面继续展开说明)。

大小端字节序问题,最有可能是跟技术算硬件或软件的创造者们,在技术创立之初的一些技术条件或个人习惯有关。

所以大小端问题,体现在实际的计算机工业应用来上,不同的操作系统和不同的芯片类型可能都会有不同。

4.2 常见的操作系统和芯片使用的字节序

具体来说:DEC和Intel的机器(X86平台)一般采用小端,IBM、Motorola(Power PC)、Sun的机器一般采用大端。

当然,这不代表所有情况。有的CPU即能工作于小端, 又能工作于大端,比如:Arm、Alpha、摩托罗拉的PowerPC。 

而且,具体这类CPU是大端还是小端,和具体设置也有关。如:Power PC支持小端字节序,但在默认配置时是大端字节序。

一般来说:大部分用户的操作系统(如:Windows、FreeBsd、Linux)是小端字节序。少部分,如:Mac OS 是大端字节序。

4.3 如何判断用的是什么字节序?

怎么判断我的计算机里使用的是大端还是小端字节序呢?

下面的这段代码可以用来判断计算机是大端的还是小端。判断的思路是:确定一个多字节的值(下面使用的是4字节的整数),将其写入内存(即赋值给一个变量),然后用指针取其首地址所对应的字节(即低地址的一个字节),判断该字节存放的是高位还是低位,高位说明是Big endian,低位说明是Little endian。

#include <stdio.h>

int main ()

{

  unsigned int x = 0x12345678;

  char*c = (char*)&x;

  if(*c == 0x78) {

    printf("Little endian");

  } else{

    printf("Big endian");

  }

  return 0;

}

5、“大端”、“小端”名字由来

根据网上的资料,据说名字的由来跟乔纳森·斯威夫特的著名讽刺小说《格列佛游记》有关。

书中的故事是这样的:一般来说,大家都认为吃鸡蛋前,原始的方法是打破鸡蛋较大的一端。可是当今皇帝的祖父小时候吃鸡蛋,一次按古法打鸡蛋时碰巧将一个手指弄破了,因此他的父亲,当时的皇帝,就下了一道敕令,命令全体臣民吃鸡蛋时打破鸡蛋较小的一端,违令者重罚。

小人国内部分裂成Big-endian和Little-endian两派,区别在于一派要求从鸡蛋的大头把鸡蛋打破,另一派要求从鸡蛋的小头把鸡蛋打破。

小人国国王改变了打开鸡蛋的方位与理由,并由此招致了修改法律、引发战争和宗教改革等一序列事件的发生。

《格列佛游记》中的这则故事,原本是借以讽刺英国的政党之争。而在计算机工业中,也借用了这个故事来代指大家在数据储存字节顺序中的分歧,并把“大端”(Big-endian)、“小端”(Little-endian)的名字,沿用到了计算机中。 

上图片改编自《“字节序”是个什么鬼?

或许,借用这个故事来命名大小端字节序问题,无非就是想告诉大家,所谓的“大端”、“小端”实际上可能无关计算机性能,更多的只是创造者们在创立计算机之初,代入了个人的一些约定俗成的习惯而已。

6、什么是网络字节序?

6.1 字节序问题给网络通信带来的困扰

对于搞网络通信应用(比如IM、消息推送、实时音视频)开发的程序员来说,自已写通信底层的话是一定会遇到大小端问题的,对于网络字节序这个知识点是一定要必知必会。(当然,你要是很没追求的认为,反正我公司就让租租第3方,能用就行,具体通底层怎么写我才不想掉头发去考虑那么多。。。。 那哥也救不了你。。

上面所说的大小端字节序都是在说计算机自己,也被称作主机字节序。同型号计算机上写的程序,在相同的系统上面运行总归是没有问题。

但计算机网络的出现让大小端问题变的复杂化了,因为每个计算机都有自己的主机字节序。不同计算机之间通过网络通信时:我“说”的你听不懂,你“说”我也听不懂,这可怎么办?

6.2 TCP/IP协议强行约定了字节序方案

好消息是,TCP/IP协议很好的解决了这个问题,TCP/IP协议规定使用“大端”字节序作为网络字节序。

这样,即使不使用大端的计算机也没有关系,因为发送数据的时候可以将自己的主机字节序转换为网络字节序(即“大端”字节序),对接收到的数据转换为自己的主机字节序。这样一来,也就达到了与CPU、操作系统无关,实现了网络通信的标准化。

具体的原理就是:

  • 1)TCP/IP协议会把接收到的第一个字节当作高位字节看待,这就要求发送端发送的第一个字节是高位字节;
  • 2)而在发送端发送数据时,发送的第一个字节是该数值在内存中的起始地址处对应的那个字节。

也就是说,该数值在内存中的起始地址处对应的那个字节就是要发送的第一个高位字节(即:高位字节存放在低地址处)。由此可见,多字节数值在发送之前,在内存中就是以大端法存放的。

所以说,网络字节序就是大端字节序。

6.3 主机字机序到网络字节序的转换

那么,为了程序的兼容,程序员们每次发送和接受数据都要进行转换,这样做的目的是保证代码在任何计算机上执行时都能达到预期的效果。

通信时的这种常用的操作,Socket API这一层,一般都提供了封装好的转换函数,方便程序员使用。比如从主机字节序到网络字节序的转换函数:htons、htonl(C语言中常用),从网络字节序到主机字节序的转换函数:ntohs、ntohl(C语言中常用)。当然,也可以编写自己的转换函数。

7、实践中的大小端字节序处理

在我编写MobileIMSDK的TCP版时(MobileIMSDK是我开源的IM通信层库),同样遇到了大小端字节序问题。

以MobileIMSDK的iOS端拼装网络数据收发的代码为例:

如上图代码所示,注意以下两个大小端转换函数的使用:

  • 1)第27行“CFSwapInt32HostToBig”函数:网络发出数据之前,先将主机字节序转为网络字节序(即大端字节序);
  • 2)第53行“CFSwapInt32BigToHost”函数:收到原始网络数据后,转为主机字节序后就可以在程序中正常使用了。

如果对网络大小端转换这方面的实践感兴趣,可以自已去下载MobileIMSDK源码试一试:https://github.com/JackJiang2011/MobileIMSDK

8、参考资料

[1] “字节序”是个什么鬼?

[2] 大小端及网络字节序

[3] C语言打印数据的二进制格式-原理解析与编程实现

附录:系列文章

本文是系列文章中的第9篇,本系列大纲如下:

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

脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

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

脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)

脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

脑残式网络编程入门(六):什么是公网IP和内网IP?NAT转换又是什么鬼?

脑残式网络编程入门(七):面视必备,史上最通俗计算机网络分层详解

脑残式网络编程入门(八):你真的了解127.0.0.1和0.0.0.0的区别?

脑残式网络编程入门(九):面试必考,史上最通俗大小端字节序详解》(本文)

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

posted @ 2020-08-13 14:58 Jack Jiang 阅读(107) | 评论 (0)编辑 收藏

本文作者网易智慧企业web前端开发工程师马莹莹。为了提升内容质量,收录时有修订和改动。

1、引言

在一个完善的即时通讯IM应用中,WebSocket是极其关键的一环,它为基于Web的即时通讯应用提供了一种全双工的通信机制。但为了提升IM等实际应用场景下的消息即时性和可靠性,我们需要克服WebSocket及其底层依赖的TCP连接对于复杂网络情况下的不稳定性,即时通讯的开发者们通常都需要为其设计一套完整的连接保活、验活以及断片网重连方案。

就断网重连而言,其重连响应速度将严重影响了上层应用的“即时性”和用户体验。试想打开网络一分钟后,微信的网络不能即时感知到socket连接的恢复,无法即时收发聊天消息的话,是不是很崩溃?

因此,如何在复杂网络场景下,更即时快速地感知网络变动,并快速恢复WebSocket的可用性,就变得尤为重要。本文将基于笔者的开发实践,分享WebSocket在不同状态下、不同的网络状态下,应该如何实现快速断网重连。

* 阅读对象:本文适合有过IM底层网络实际开发经验,或者对底层网络实现有较深了解的开发者阅读。如果对底层网络了解甚少,建议跳过本文,直接阅读网络本文末尾附录部分的基础后再回头来看。

* 内容点评:本文内容没有高大上,但比较干货,实用性较高,内容也很通俗,建议可详细阅读。文中虽讲的是WebSocket,但思想可以延伸应用到基于TCP协议的同类技术中。

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:点此进入原文链接是:http://www.52im.net/thread-3098-1-1.html

2、预备知识

本文中将要分享的内容是基于实践总结,如果你对Web端的即时通讯知识还一头雾水,务必先读:《新手入门贴:史上最全Web端即时通讯技术原理详解》、《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》。

限于篇幅,本文不会深究WebSocket技术细节,如有兴趣请系统学习:

3、快速了解WebSocket

Websocket诞生于2008年,在2011年成为国际标准,现在所有的浏览器都已支持(详见《新手快速入门:WebSocket简明教程》)。它是一种全新的应用层协议,是专门为web客户端和服务端设计的真正的全双工通信协议,可以类比HTTP协议来了解websocket协议。

图片引用自《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)

它们的不同点:

  • 1)HTTP的协议标识符是http,WebSocket的是ws;
  • 2)HTTP请求只能由客户端发起,服务器无法主动向客户端推送消息,而WebSocket可以;
  • 3)HTTP请求有同源限制,不同源之间通信需要跨域,而WebSocket没有同源限制。

它们的相同点:

  • 1)都是应用层的通信协议;
  • 2)默认端口一样,都是80或443;
  • 3)都可以用于浏览器和服务器间的通信;
  • 4)都基于TCP协议。

两者和TCP的关系图:

图片引用自《新手快速入门:WebSocket简明教程

有关Http和WebSocket的关系,可以详读:

有关WebSocket和Socket的关系,可以详读:《WebSocket详解(六):刨根问底WebSocket与Socket的关系》.

4、WebSocket重连过程拆解

首先考虑一个问题,何时需要重连?

最容易想到的是WebSocket连接断了,为了接下来能收发消息,我们需要再发起一次连接。

但在很多场景下,即便WebSocket连接没有断开,实际上也不可用了。

比如以下场景:

  • 1)设备切换网络;
  • 2)链路中间路由崩溃(常识是一条socket连接对应的网络通路上,会存在很多路由设备);
  • 3)链路的前端出口不可用(比如家庭WiFi中,网络连接正常,但实际运营商的宽带已经欠费被停机);
  • 4)服务器负载持续过高无法响应等。

这些场景下的WebSocket都没有断开,但对上层来说,都没办法正常的收发数据了。

因此在重连前,我们需要一种机制来感知连接是否可用、服务是否可用,而且要能快速感知,以便能够快速从不可用状态中恢复。

一旦感知到了连接不可用,那便可以弃旧图新了,弃用并断开旧连接,然后发起一次新连接。这两个步骤看似简单,但若想达到快,且不是那么容易的。

首先:是断开旧连接,对客户端来说,如何快速断开?协议规定客户端必须要和服务器协商后才能断开WebSocket连接,但是当客户端已经联系不上服务器、无法协商时,如何断开并快速恢复?

其次:是快速发起新连接。此快非彼快,这里的快并非是立即发起连接,立即发起连接会对服务器带来不可预估的影响。重连时通常会采用一些退避算法,延迟一段时间后再发起重连。但如何在重连间隔和性能消耗间做出权衡?如何在“恰当的时间点”快速发起连接?

带着这些疑问,我们来细看下这三个过程:

5、快速重连关键1:快速感知何时需要重连

5.1 场景

需要重连的场景可以细分为三种:

  • 1)连接明确断开了;
  • 2)连接没断但是不可用了;
  • 3)连接对端的服务不可用了。

对于第一种场景:这很简单,连接直接断开了,肯定需要重连了。

对于后两者:无论是连接不可用,还是服务不可用,对上层应用的影响都是不能再收发即时消息了。

5.2 心跳包主动探测网络可用性

所以从上面这个角度出发,感知何时需要重连的一种简单粗暴的方法就是通过心跳包超时:发送一个心跳包,如果超过特定的时间后还没有收到服务器回包,则认为服务不可用,如下图中左侧的方案(这种方法最直接)。

那如果想要快速感知呢,就只能多发心跳包,加快心跳频率。但是心跳太快对移动端流量、电量的消耗又会太多,所以使用这种方法没办法做到快速感知,可以作为检测连接和服务可用的兜底机制。

5.3 被动监听网络状态改变

如果要检测连接不可用,除了用心跳检测,还可以通过判断网络状态来实现,因为断网、切换wifi、切换网络是导致连接不可用的最直接原因,所以在网络状态由offline变为online时,大多数情况下需要重连下,但也不一定,因为webscoket底层是基于TCP的,TCP连接不能敏锐的感知到应用层的网络变化,所以有时候即便网络断开了一小会,对WebSocket连接是不会有影响的,网络恢复后,仍然能够正常地进行通信。

因此在网络由断开到连接上时,立即判断下连接是否可用,可以通过发一个心跳包判断,如果能够正常收到服务器的心跳回包,则说明连接仍是可用的,如果等待超时后仍没有收到心跳回包,则需要重连,如上图中的右侧。这种方法的优点是速度快,在网络恢复后能够第一时间感知连接是否可用,不可用的话可以快速执行恢复,但它只能覆盖应用层网络变化导致WebSocket不可用的情况。

5.4 小结

综上所述:

  • 1)定时发送心跳包检测的方案贵在稳定,能够覆盖所有场景,但速度不即时(心跳间隔是固定的);
  • 2)判断网络状态的方案速度快,无需等待心跳间隔,较为灵敏,但覆盖场景较为局限。

因此,我们可以结合两种方案:

  • 1)定时以不太快的频率发送心跳包,比如40s/次、60s/次等,具体可以根据应用场景来定;
  • 2)然后在网络状态由offline变为online时立即发送一次心跳,检测当前连接是否可用,不可用的话立即进行恢复处理。

这样在大多数情况下,上层的应用通信都能较快从不可用状态中恢复,对于少部分场景,有定时心跳作为兜底,在一个心跳周期内也能够恢复。

6、快速重连关键2:快速断开旧连接

通常情况下,在发起下一次连接前,如果旧连接还存在的话,应该先把旧连接断开。

这样做的目的:

  • 1)一来可以释放客户端和服务器的资源;
  • 2)二来可以避免之后误从旧连接收发数据。

我们知道WebSocket底层是基于TCP协议传输数据的,连接两端分别是服务器和客户端,而TCP的TIME_WAIT状态是由服务器端维持的,因此在大多数正常情况下,应该由服务器发起断开底层TCP连接,而不是客户端。

也就是说:

  • 1)要断开WebSocket连接时,如果是服务器收到指示要断开WebSocket,那它应该立即发起断开TCP连接;
  • 2)如果是客户端收到指示要断开WebSocket,那它应该发信号给服务器,然后等待底层TCP连接被服务器断开或直至超时。

那如果客户端想要断开旧的WebSocket,可以分为WebSocket连接可用和不可用两种情况来讨论。

具体如下:

  • 1)当旧连接可用时,客户端可以直接给服务器发送断开信号,然后服务器发起断开连接即可;
  • 2)当旧连接不可用时,比如客户端切换了wifi,客户端发送了断开信号,但是服务器收不到,客户端只能迟迟等待,直至超时才能被允许断开。

超时断开的过程相对来说是比较久的,那有没有办法可以快点断开?

上层应用无法改变只能由服务器发起断开连接这种协议层面的规则,所以只能从应用逻辑入手,比如在上层通过业务逻辑保证旧连接完全失效,模拟连接断开,然后在发起新连接,恢复通讯。

这种方法相当于尝试断开旧连接不行时,直接弃之,然后就能快速进入下一流程,所以在使用时一定要确保在业务逻辑上旧连接已完全失效。

比如:

  • 1)保证丢掉从旧连接收到所有数据;
  • 2)旧连接不能阻碍新连接的建立
  • 3)旧连接超时断开后不能影响新连接和上层业务逻辑等等。

7、快速重连关键3:快速发起新连接

有IM开发经验的同学应该有所了解,遇到因网络原因导致的重连时,是万万不能立即发起一次新连接的,否则当出现网络抖动时,所有的设备都会立即同时向服务器发起连接,这无异于黑客通过发起大量请求消耗网络带宽引起的拒绝服务攻击,这对服务器来说简直是灾难(即:服务端雪崩效应)。

所以在重连时通常采用一些退避算法,延迟一段时间再发起重连,如下图中左侧的流程。

如果要快速连上呢?最直接的做法就是缩短重试间隔,重试间隔越短,在网络恢复后就能越快的恢复通讯。但是太频繁的重试对性能、带宽、电量的消耗就比较严重。

如何在这之间做一个较好的权衡呢?

  • 1)一种比较合理的方式是随着重试次数增多,逐渐增大重试间隔;
  • 2)另一方面监听网络变化,在网络状态由offline变为online这种比较可能重连上的时刻,适当地减小重连间隔。

上述第2)种方案,如上图中的右侧所示,随重试次数的增多,重连间隔也会变大。这两种方式配合使用,更为合理。

除此之外,还可以结合业务逻辑,根据成功重连上的可能性适当的调整间隔,如网络未连接时或应用在后台时重连间隔可以调大一些,网络正常的状态下可以适当调小一些等等,加快重连上的速度。

8、本文小结

最后总结一下。

本文将WebSocket断网重连逻辑细分为三个步骤:

  • 1)确定何时需要重连;
  • 2)断开旧连接;
  • 3)发起新连接。

然后分别分析了在WebSocket的不同状态下、不同的网络状态下,如何快速完成这个三个步骤。

过程具体总结就是:

  • 1)首先:通过定时发送心跳包的方式检测当前连接是否可用,同时监测网络恢复事件,在恢复后立即发送一次心跳,快速感知当前状态,判断是否需要重连;
  • 2)其次:正常情况下由服务器断开旧连接,与服务器失去联系时直接弃用旧连接,上层模拟断开,来实现快速断开;
  • 3)最后:发起新连接时使用退避算法延迟一段时间再发起连接,同时考虑到资源浪费和重连速度,可以在网络离线时调大重连间隔,在网络正常或网络由offline变为online时缩小重连间隔,使之尽可能快地重连上。

以上就是我关于如何实现WebSocket快速重连的技术分享,欢迎留言与我探讨。

9、参考资料

[1] RFC 6455 文档

[2] 新手快速入门:WebSocket简明教程

[3] WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)

[4] WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)

[5] WebSocket详解(六):刨根问底WebSocket与Socket的关系

附录:更多Web端即时通讯资料

新手入门贴:史上最全Web端即时通讯技术原理详解

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

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

Comet技术详解:基于HTTP长连接的Web端实时通信技术

socket.io实现消息推送的一点实践及思路

LinkedIn的Web端即时通讯实践:实现单机几十万条长连接

Web端即时通讯技术的发展与WebSocket、Socket.io的技术实践

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

开源框架Pomelo实践:搭建Web端高性能分布式IM聊天服务器

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

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

MobileIMSDK-Web的网络层框架为何使用的是Socket.io而不是Netty?

理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性

微信小程序中如何使用WebSocket实现长连接(含完整源码)

八问WebSocket协议:为你快速解答WebSocket热门疑问

快速了解Electron:新一代基于Web的跨平台桌面技术

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

Web端即时通讯基础知识补课:一文搞懂跨域的所有问题!

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

>> 更多同类文章 ……

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

posted @ 2020-08-05 15:36 Jack Jiang 阅读(154) | 评论 (0)编辑 收藏

本文由有赞技术团队原创分享,原题“有赞 APP IM SDK 组件架构设计”,即时通讯网收录时有修订和改动,感谢原作者的无私分享。

1、引言

本文主要以Android客户端为例,记录了有赞旗下 App 中使用自研 IM,并将IM提炼成组件化SDK的设计思路。此项工作由有赞移动开发组 IM SDK 团队共同讨论完成。

 

在有赞产品中,存在大量需要交易双方沟通交流的场景,比如,客户咨询商家产品信息,售前售后简单的答疑和维权等。另外,有赞业务还存在一些特殊的复杂场景,如供应商、分销商、客户三方之间需要同步沟通,会同时存在多种沟通角色。

此时需要较为完善的即时通信(IM)解决方案,但是由于有赞针对不同的商户和使用场景有多个APP,APP自行实现IM功能代价较大,且维护起来人力分散,于是,IM SDK项目便应运而生了,APP 通过接入此给件化SDK,可以快速实现IM基本功能。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

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

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:https://mp.weixin.qq.com/s/ANp1kuj65Ww5RpABl2M9RQ,原文链接是:http://www.52im.net/thread-3088-1-1.html

2、相关文章

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

从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结》(* 推荐

从游击队到正规军(三):基于Go的马蜂窝旅游网分布式IM系统技术实践

一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

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

一套原创分布式即时通讯(IM)系统理论架构方案

蘑菇街即时通讯/IM服务器开发之架构选择

自已开发IM有那么难吗?手把手教你自撸一个Andriod版简易IM (有源码)

适合新手:从零开发一个IM服务端(基于Netty,有完整源码)

拿起键盘就是干:跟我一起徒手开发一套分布式IM系统

3、设计目标

本次IM组件化SDK的设计目标有以下几点:

  • 1)IM 主流程稳定可用:消息传输具有高可靠性;
  • 2)UI 组件直接集成进入SDK,并支持可定制化;
  • 3)富媒体发送集成进入SDK,并可按需定制需要的富媒体类型;
  • 4)实现消息传输层SDK,与带有UI的SDK的功能分离,业务调用方既可以使用消息传输SDK,处理消息,然后自行处理UI,也可以使用带有UI组件的SDK,一步实现较为完备的IM功能。

4、整体结构

下图中简要描述了有赞客户端中IM系统的基本结构 : 

如上图所示,各分层的职责分工如下:

  • 1)消息通道层:维护Socket长连接作为消息通道,消息收发流程主要在这一层中完成;
  • 2)持久化层:主要将消息存入数据库中,富媒体文件存入文件缓存中,方便第二次展示消息时候,从本地加载,而不是网络层获取;
  • 3)逻辑处理层:完成各种消息相关的逻辑处理,如排序,富媒体文件的预处理等;
  • 4)UI显示层:将数据在UI上进行呈现。

5、设计要点1:Socket长连接的创建与维护

IM SDK 所有数据收发流程,均通过Socket长连接完成,如何维护一个稳定Socket通道,是IM系统是否稳定的重要一环。 

下面描述下Socket通道几个重要的流程。

1)创建流程(连接) :

如图上所示,当IM SDK初始化后,业务调用连接请求接口,会开始连接的创建过程,创建成功后,会完成鉴权操作,当创建和鉴权都完成后,会开启消息收发线程,为了维持长连接,会有心跳机制,特别的,会开启一个心跳轮询线程。

2)心跳机制 :

心跳机制,是IM系统设计中的常见概念,简单的解释就是每隔若干时间发送一个固定信息给服务端,服务端收到后及时回复一个固定信息,如果服务端若干时间内没有收到客户端心跳信息则视客户端断开,同理如果客户端若干时间没有收到服务端心跳回值则视服务端断开。 

 

当长连接创建成功后,会开启一个轮询线程,每隔一段时间发送心跳消息给服务器端,以维持长连接。

有关IM心跳方面的专项文章,请见:

手把手教你用Netty实现网络通信程序的心跳机制、断线重连机制

为何基于TCP协议的移动端IM仍然需要心跳保活机制?

移动端IM实践:实现Android版微信的智能心跳机制

移动端IM实践:WhatsApp、Line、微信的心跳策略分析

一文读懂即时通讯应用中的网络心跳包机制:作用、原理、实现思路等

正确理解IM长连接的心跳及重连机制,并动手实现(有完整IM源码)

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

手把手教你用Netty实现网络通信程序的心跳机制、断线重连机制

3)重连流程 :

重连被触发时,如果该次连接成功,退出重连。反之重连失败后,会判断当前重连的次数是否超过预期值(这里设为6次),并对重连次数计数,如果超过就会退出重连,反之休眠预设的时间后再次进行重连操作。

重连触发条件分为三种:

  • a. 主动连接不成功(主动连接Socket,如果连接失败,会触发重连机制);
  • b. 网络被主动断开(正常建立连接,操作过程中,网络被断开,通过系统广播触发重连);
  • c. 服务器没响应,心跳没回值(服务端心跳预设时间内没回值,客户端认为服务端已经断开,触发重连)。

有关重连机制的深入学习,可以阅读以下两篇:

4)网络状态判断:

TCP API并没有提供一个可靠的方法判断当前长连接通道状态,isConnected()和isClosed()仅仅告诉你当前的Socket状态,不是是长连接断开是一回事。 isConnected()告诉你是否Socket与Romote host保持连接,isClosed()告诉你是否Socket被关闭。 

假如你判断长连接通道是否被关闭,只能通过和流操作相关的以下方法:

  • a. read() return -1;
  • b. readLine() return null;
  • c. readXXX() throw EOPException for any other XXX;
  • d. write 将抛出IOException: Broken pipe(通道被关闭)。

所以SDK封装isConnected(方法的时候,是根据这几种情况综合判断当前的通道状态,而不是仅仅通过Socket.isConnected()或者Socket.isClosed()。

6、设计要点2:消息发送流程

消息发送流程主要有两大类:

1)一类是IM相关数据的请求,例如:历史消息列表,会话列表等;

2)另一类是IM消息的发送,主要是文字消息。

富媒体消息发送,会将富媒体文件先上传服务器后,拿到文件URL, 通过文字消息,将此URL发给接收方,接收方下载后进行UI展示)。 

以上两类消息发送,均使用上图的流程进行发送,可通过发送回调感知请求的结果。

如上图所示,消息发送流程,需要先封装消息请求,在通过发送队列发送至服务器,发送前,在将请求id和对应回调存入本地Map数据结构中。

if(requestCallBack != null) { 

  mCallBackMap.put(requestId, requestCallBack);

}

之后接收服务器推送消息(此消息带有发送请求时的请求id),在本地的Map数据找到请求id对应的回调,然后通过回调返回服务器推送过来的数据。 

请求可以通过泛型指定返回值类型,SDK中会自行解析服务器数据返回的数据,直接返回给业务调用方model对象,方便使用。(目前支持json格式的数据解析)

private void IMResponseOnSuccess(String requestid, String response) { 

        if(mCallBackMap != null) {

           IMCallBack callBack = mCallBackMap.get(requestid);

           if(callBack == null) {

               return;

           }

           if(callBack instanceofJsonResultCallback) {

               finalJsonResultCallback resultCallback = (JsonResultCallback) callBack;

               if(resultCallback.mType == String.class) {

                   callBack.onResponse(response);

               } else{

                   Object object = newGson().fromJson(response, resultCallback.mType);

                   callBack.onResponse(object);

               }

               removeCallBack(requestid);

           }

        }

}

如下的示例中,展示了一个获取会话列表的请求,可以看出目前的请求封装,和一些第三方的的网络库类似,使用起来较为方便。

RequestApi requestApi = new RequestApi(IMConstant.REQ_TYPE_GET_CONVERSATION_LIST, Enums Manager.IMType.IM_TYPE_WSC.getRequestChannel());

 

requestApi.addRequestParams("limit", 100); 

requestApi.addRequestParams("offset", 0);

 

IMEngine.getInstance().request(requestApi, newJsonResultCallback<List<ConversationEntity>>() { 

    @Override

    publicvoidonResponse(List<ConversationEntity> response) {

        mSwipeRefreshLayout.setRefreshing(false);

        mAdapter.mDataset.clear();

        mAdapter.mDataset.addAll(response);

        mAdapter.notifyDataSetChanged();

    }

 

    @Override

    publicvoidonError(intstatusCode) {

        //do something

    }

});

可以看出,该请求直接返回了一个会话类型的List集合,业务方可直接使用。

7、设计要点3:消息接收流程

消息的监听流程主要使用了一个全局监听的方式来进行,需要先注册监听器,监听器中有默认的回调。

public interface IMListener { 

    /**

     * 连接成功

     */

    void connectSuccess();

 

    /**

     * 连接失败

     */

    void connectFailure(EnumsManager.DisconnectType type);

 

    /**

     * 鉴权成功

     */

    void authorSuccess();

 

    /**

     * 鉴权失败

     */

    void authorFailure();

 

    /**

     * 接收数据成功

     */

    void receiveSuccess(int reqType, String msgId, String requestChannel, String message, int statusCode);

 

    /**

     * 接收数据失败

     */

    void receiveError(int reqType, String msgId, String requestChannel, int statusCode);

}

该监听器中可以接收如下类型的消息:

  • 1)Socket连接状态的返回结果;
  • 2)鉴权状态的返回结果,(鉴权流程因有赞业务需要);
  • 3)接收的IM消息,或者其他类型的返回消息。可根据消息类型进行后续的分发处理。

业务如需使用此全局监听器,需要自行实现此接口,并在业务初始化时,注册此监听器即可。SDK中会根据注册的监听器,在读取到服务器推送消息后,直接通过监听器到回调进行分发。

private void distributeData(IMEntity imEntity) { 

        if(mIMListener != null&& imEntity != null) {

       // 省略部分逻辑代码

       ……

       if(status == Response.SUCCESS) {

           switch(responseModel.reqType) {

               caseIMConstant.REQ_TYPE_AUTH: // 鉴权成功

                   mIMListener.authorSuccess();

                   return;

 

               caseIMConstant.REQ_TYPE_OFFLINE: //  服务端踢客户端下线

                   mIMListener.connectFailure(EnumsManager.DisconnectType.SERVER);

                   break;

 

               caseIMConstant.REQ_TYPE_HEARTBEAT: // 心跳成功

               caseIMConstant.REQ_TYPE_RECEIVER_MSG: // 收到回调消息

                   handleMessageID(responseModel.body);

                   break;

               default:

                   break;

           }

           mIMListener.receiveSuccess(responseModel.reqType, msgId, responseModel

                   .requestChannel, responseModel.body, 0);

       } else{

           mIMListener.receiveError(responseModel.reqType, msgId, responseModel

                   .requestChannel, status);

       }

   }

}

部分接收消息,如心跳,多端登录时被踢下线通知等,sdk内部会自行处理,业务基本无感知。

8、设计要点4:可定制化的UI

随着公司规模的扩大与业务线的快速迭代,可能新的业务也需要 IM 这个功能,众所周知,IM UI 功能的嵌入会占据大量的开发与调试时间, 为了解决这个痛点,决定将 IM UI 部分抽成一个 Library,实现可定制与单独维护,做到真正的敏捷开发与快速迭代。

8.1 UIKit设计 

IM UIKit暴露相应的api接口,业务方注入相应的功能定制项,针对UI的点击回调通过EventBus总线post分发,减少了业务方与UIKit的耦合,底层业务方通过MVP模式对View与Model进行解耦。

定制项一般通过如下几种方式。

1)XML(定制业务信息,资源信息,显示条数,各个业务功能开关等):

<?xml version="1.0" encoding="utf-8"?>

<resources>

    <stylename="limit">

        <!--每屏展示的条数-->

        <itemname="swiplimit">5</item>

        ......

    </style>

    ......

    ......

    <stylename="itembox">

        <itemname="showvoice">true</item>

        ......

        ......

        <itemname="more"show="true">

            <more>

                <iconstyle="mipmap">im_plus_image</icon>

                <itemname>测试</itemname>

                <callback>false</callback>

            </more>

             ......

             ......

            <more>

                <iconstyle="mipmap">ic_launcher</icon>

                <itemname>测试</itemname>

                <callback>true</callback>

            </more>

        </item>

        ......

        ......

    </style>

</resources>

2)Style(定制UI背景,气泡颜色,字体大小等):

<?xml version="1.0" encoding="utf-8"?>

<resources>

    <!--im 聊天背景-->

    <stylename="imui_background">

        <itemname="android:background">@android:color/holo_red_dark</item>

    </style>

    ......

    ......

 

    <!--气泡背景-->

    <stylename="bubble_background">

        <itemname="android:background">@mipmap/bubble_right_green</item>

    </style>

 

       <!--背景和和字段颜色定制-->

    <stylename="bg_and_textcolor"parent="bubble_background">

        <itemname="android:textColor">@android:color/holo_red_dark</item>

    </style>

    ......

    ......

</resources>

3)Model定制(传入预设的定制Model模板填入相应参数,UIKit里面做相应解析):

public class Entity {

    publicString action1;

    publicString action2;

    publicString aciton3;

    ......

}

8.2 UIKit 支持的富媒体类型

除了文字消息之外,现在主流的IM系统中也支持各种富媒体发送,在有赞IM SDK UIKit中,目前也支持几种富媒体发送。 以下是发送流程图和两类常见富媒体消息简介。

  • 1)语音消息:除了使用常见的录制和解码播放的技术之外。还利用了 AudioManager 中 requestAudioFocus,abandonAudioFocus 相关方法,实现了录制和播放语音消息,如果有第三方播放音乐,会自动暂停,录制和播放语音消息结束后,声音会自动播放。
  • 2)图片消息:通过七牛服务器设置了缩略图,接收方收到消息后,会先下载缩略图,当用户再点击进入图片详情页时,会下载大图,Andorid客户端使用Picasso加载库加载图片,并做本地缓存。

9、设计要点5:UI 中聊天会话数据加载策略

参考业界主流的IM系统方案,用户聊天时,需要将已经发送和接收到的聊天信息保存到本地,而不是每次都拉取历史数据。以达到节约流量和无网络状态下也查看数据的效果。

为此IM SDK持久化层的数据库中,也实现了简单存储加载机制,下面描述典型的数据加载场景。

1)IM会话首次请求数据流程:

2)IM下拉获取历史数据流程: 

3)IM单条消息发送持久化方案:

4)IM单条数据重发流程: 

10、设计不足之处

1)消息回执:

当前的设计方案中,没有消息回执的机制,也就是说接受方收到消息后,不会返回服务器收到消息的通知,服务器无法判断消息是否推送成功,这样在突然断网,网络模式切换,或者弱网环境下,会影响消息的到达率。 

一种可行的设计方式是,发送方增加已送到和未送达的状态,接收方收到消息后,给服务器返回已收到消息的通知,服务器再推送给发送方该状态,如果没有收到接收方回执,服务器可尝试重新推送。发送方接受到接收方的收到回执后,更新发送状态已发送,如果未收到,则显示未送达。为了防止接收方回执丢失,接收方接收消息时候,可维护本地去重队列。

2)本地请求超时的判断:

本地发起的请求,没有用定时器,完全依赖服务器返回或者出现Socket通道异常后上抛的通知作为超时判断,部分场景可能覆盖不到,需要对请求增加固定的超时处理机制,固定时候未收到请求,即认为超时。

* 推荐学习:针对以上两点不足,感兴趣的读者,可以研究一下MobileIMSDK开源工程源码https://github.com/JackJiang2011/MobileIMSDK,MobileIMSDK已经实现了完整的消息送达保证机制(包括:ACK回执、重传、去重、超时判定等等)。

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

posted @ 2020-07-29 14:09 Jack Jiang 阅读(131) | 评论 (0)编辑 收藏

     摘要: 本文引用自公众号“开发的猫”,本次收录时有改动,感谢原作者“开发的猫”的分享。1、引言随着移动网络速度越来越快、质量越来越来,实时音视频技术已经在各种应用场景下全面开花,语音通话、视频通话、视频会议、远程白板、远程监控等等。实时音视频技术的开发也越来越受到重视,但是由于音视频开发涉及知识面比较广,入门门槛相对较高,让许许多多开发者望而生畏。虽然网上有...  阅读全文

posted @ 2020-07-24 14:13 Jack Jiang 阅读(177) | 评论 (0)编辑 收藏

1、点评

IM聊天消息的可靠投递,是每个线上产品都要考虑的IM热点技术问题。

IM聊天消息能保证可靠送达,对于用户来说,就好比把钱存在银行不怕被偷一样,是信任的问题。试想,如果用户能明显感知到聊天消息无法保证送达,谁还愿意来用你的APP?谁也不希望自已的话就像浮云一样随风飘逝。

必竟用IM聊天,虽然很多时候是费话,但总有关键时刻存在——比如向女神表白(哪怕明知被拒),作为合格的舔狗一定不希望女神错过这条消息。

所以,消息的可靠投递是每款IM产品和立足之本,也是IM开发者们孜孜不倦追求的技术目标。

本文作者将以自已IM开发过程中的真实总结,分享针对大量离线聊天消息,在确保用户端体验不降级的前提下,保证离线消息的可靠投递。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

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

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:https://mp.weixin.qq.com/s/T2w9h_AN_T2UnqNdVikX0Q,原文链接是:http://www.52im.net/thread-3069-1-1.html

 

2、本文作者 

fzully(柳林勇):2005年数学系毕业,先后就职于福建新大陆、福建富士通、北京世纪奥通。长期从事服务端软件开发,涉及SIP服务器、内核RTP转送、电信级AAA认证系统、IM即时通讯系统等。在分布式高性能系统设计有多年经验积累。

本作者的另一篇:《IM群聊消息的已读未读功能在存储空间方面的实现思路探讨》也已被即时通讯网收录并整理发布,有兴趣可以前往阅读。

3、相关文章

从客户端的角度来谈谈移动端IM的消息可靠性和送达机制

移动端IM中大规模群消息的推送如何保证效率、实时性?

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

IM消息送达保证机制实现(二):保证离线消息的可靠投递》(* 强烈推荐

如何保证IM实时消息的“时序性”与“一致性”?

一个低成本确保IM消息时序的方法探讨

IM群聊消息如此复杂,如何保证不丢不重?》(* 强烈推荐

移动端IM登录时拉取数据如何作到省流量?》(* 强烈推荐

完全自已开发的IM该如何设计“失败重试”机制?

IM开发干货分享:我是如何解决大量离线消息导致客户端卡顿的》(* 强烈推荐

4、正文引言

暗恋女神良久,终于鼓起勇气决定向女神写一封情书。但如何表达才能感动女神?自感才疏学浅,于是通读四书五经、熟背唐诗宋词、遍览四大名著,已然腹有诗书气自华。一周末冥思苦想整日才写就一首七言律诗,虽无惊天地泣鬼神之势,但诚挚的爱念在字里行间里流淌,亦歌亦诗,相信会感动到女神,手机欣然发出。

发出一秒后,手心冒汗,感觉脸颊发烫,心脏像受惊吓的野兔一样快速跳动,就像第一次看见女神那时的感觉。闭着眼睛,想象女神看到消息时的情形,她是否也期盼我的表白?看到消息时是否心跳加速、小脸绯红?

一分钟后,紧盯手机屏幕,等待、期盼女神回复。

时间一分一秒地逝去,等一分钟像等一年一样漫长。

一小时后,仍然杳无音讯,难道她没看到消息么?或许在忙什么而没留意手机吧!

一天过去了,坐立不安,等待是一种痛苦的煎熬,期待和煎熬在心中交织翻滚,有几个瞬间甚至希望女神赶快拒绝自己,好让自己解脱!茶饭无味,失眠多天,整日魂不守舍。

一个月过去了,死心。

半年后,女神出嫁,婚礼那天前去祝福。席间亦随众觥筹交错,略有醉意,向女神敬酒:祝福你,但愿以后能遇见像你这样的女人。女神先是愣住、收起笑容,低下头,目光无神地看着大红地毯,长叹一声,言:我等你表白,等了一年!空气凝滞了几秒,女神强作欢颜:从今往后,各自安好吧,干杯!

我转身踱回到座位,拿起手机,打开那个App,看着曾经发出的情书,一切仿佛还在昨日,但故事脚本已被别人书写,欲哭无泪,叹老天为何如此捉弄我?为何我发的消息女神没收到啊!

失魂落魄地回到家里,从冰箱里拿出几瓶罗斯福10号来麻醉自己,在酒精强烈的作用下,迷迷入睡。

第二天醒来,我明白了一个道理:对IM系统而言,消息必达永远摆在第一位!

以上是胡说八道,以下开始正文。。。

5、用全量离线消息实现消息必达

我们在重构IM系统时,需解决上一代设计的痛点之一就是确保消息必达。

5.1 离线消息实现消息必达的流程

自然而然地会想到这么做——即由服务端为每个人保存一个“离线消息列表”。

具体的思路是这样:

  • 1)当用户在线时,由IMS主动确保消息下发且收到客户端的应答确认时,才认为消息送达客户端,相应地把消息从“离线消息列表”移除;
  • 2)如果客户端没有发回应答确认,IM服务端会再发送。

以此来确保消息一定送到客户端,看起来是很符合逻辑。当时调查过市面上多款IM,行为基本如此。

5.2 海啸般的离线消息

5.2.1)和平时期:

重构后的IM上线,内部测试及在公网运行,离线消息的工作一直很正常。

5.2.2)被签到签死了:

后来,为某客户部署的私有环境,其用户量达几十万,其中的一个组织接近三万人,全员群也接近三万人;还有,底下的部门也有相应的群组,几百到几千人群不等。

“报到”、“签到”。。。大量的类似消息被发到几千、几万人的群内,然后如果有人一两天没上线,或者被加入到多个组织内,等到其上线时,几万条离线消息像海啸一般涌来,您想象一下:手机用户刚登陆的几分钟内,是什么场景?

用户真的很无辜:我不就是登陆了一下App,叮叮咚咚响了几分钟,还卡,还发热。。。

客户端承受不起大规模离线消息的轰炸,怎么办?

5.3 临时运用方案

  • 1)对若干大组织的全员群,对非管理员禁言;
  • 2)通知所有用户不要在大群签到。

我承认,这确实不算是个正经方案。。。

6、远离全量离线消息

我承认,一开始设计离线消息时,真没想到是这样的使用场景。对于大多数IM的开发者,或许不会碰到这种场景(但凡事住最坏的可能性想,总是没错的)。

6.1 放弃以离线消息的形式实现消息必达

我开始思考什么是消息必达,以前的想法是:把用户该收的消息都送到其客户端,是消息必达。

后来,给消息必达下了新的定义:

  • 1)用户有新消息时,确保让用户知道;
  • 2)当用户要查看这些消息时,确保其可一条不漏地看到。

打个比方:

  • 1)客户要把钱给您,不必送到您家里才算送到;
  • 2)而是转账到您的银行账户上,并告知您;
  • 3)当您要用钱时,直接从银行账户上消费即可。

从此,不会在用户上线时向其发送大量离线消息(即全量推送)。

6.2 以会话列表为基础来实现消息必达

客户端在上线时,先从服务端更新会话列表,也就是你通常在每个IM客户端的首页看到的这个(如下图所示)。

上图引用自《IM开发快速入门(一):什么是IM系统?

每一个会话列表项包含如下信息(此处简化了与本文无关的成员变量):

{

        // 会话对象的角色类型,比如私聊、群聊、系统通知、业务通知。。。

        uint32  session_role;

        // 会话对象的ID

        uint32        session_id;

        // 会话时间戳,用于消息同步;

        // 指会话的最后操作时间,比如清除角标的时间,与会话最后一条的消息时间未必一致

        uint64 session_timestamp;

        // true表示新增或更新,false表示被删除

        boolis_add;

 

        // 当is_add=false时,忽略以下信息

 

        // 仅用于显示角标的未读数量,当用户查看该会话后清零,且客户端多端同步

        uint32 new_msg_count;

        // 会话的最后一条消息

        MessageItem         latest_msg;

        // 跳转消息的时间戳,即new_msg_count的最旧1条消息的时间

        uint64 goto_timestamp;

}

为方便讨论,假设以下前提:

  • 1)周五傍晚18:00下班,我关闭App,我是9527;
  • 2)有1小姐姐向我发了5条消息留言,约我周末去海边玩,她是杨幂3306;
  • 3)然后,另1小姐姐也向我发了33条消息留言,内容我不便透露,她是景甜5672;
  • 4)严正声明:我跟她们很清白,其实我喜欢的是6379。

对,既然是假设,假一点也无妨。

我下班回到家,看到手机有通知栏消息,打开App将会发生哪些事呢?

App和IM后端的交互:

1)登录后,App以18:00填充参数latest_session_time,向IMS获取会话列表(其实不是以下线时间18:00,但这样更易理解);

2)IM后端检查发现我从18:00开始,有2个会话更新了,于是向App发送应答,以增量形式携带2个会话项:杨幂3306,景甜5672。其中景甜5672的会话项信息如下:

{

        uint32  session_role = Role_User; //表示私聊

        uint32        session_id = 5672; //景甜的ID

        uint64  session_timestamp = 1594464295335672; //最后一条消息的时间戳,微秒

        boolis_add = true; // true表示是更新项

        uint32  new_msg_count = 33; // 景甜向我发了33条消息

        MessageItem         latest_msg = "房号是0520"; //最后1条消息,结构体MessageItem简略不表

        uint64  goto_timestamp = 1594463697556677; // 向我发的33条消息的最早1条的时间

}

3)App收到步骤2的应答,我在App的会话列表窗口里,能看到2项更新,景甜发来的未读消息数33条,杨幂的是5条,如下图所示:

 

4)点开景甜5672的会话,App将向IMS发起同步消息的请求,获取最新的10条聊天消息(为了显示一屏):

{

        uint32  session_role = Role_User; //表示私聊

        uint32        session_id = 5672; //景甜的ID

        uint64        begin_time  = 1594464295335672; //步骤2返回的session_timestamp

        uint64        end_time  = 1594434153444222; //景甜上午向我发的最后一条消息的时间

        uint32        max_pieces = 10; //本次最多取10条,PC屏幕大则不妨取20条

}

5)IM后端收到步骤4请求,将返回33条新消息的最后10条给App,呈现聊天窗口内,且聊天窗口上方有一个tip:“↑ 33条新消息”,如下图所示:

 
 

6)我可以向上翻动聊天记录,那么App将持续向IMS获取第2批同步消息;或者也可以点击tip:“↑ 33条新消息”,直接跳转到33条消息的最旧一条,这样支持从最旧的消息向新的翻看。

相比于客户端简单地被动接收服务端的离线通知方式,这种设计使得客户端的处理逻辑更复杂。

主要体现在:

  • 1)客户端向服务端取的同步消息是未必完整,这些存在客户端的消息,在时间区间上可能不连续的;
  • 2)客户端需要知道不同消息之间是否有断代,如果有则需要向服务端查询同步消息来merge本地信息,使其连续,即客户端要实现消息融合。

我的建议:用C++实现一个统一的底层imsdk库,来负责这些共通的消息处理和存储。避免各客户端(Windows,iOS,Android等)各自实现这些逻辑,减少工作量,也降低各端不一致的风险。

6.3 以会话列表为基础与用全量离线消息的方案对比

6.3.1)用全量离线消息实现的方案优缺点:

实现原理:由IM服务端确保消息送达客户端,客户端存储后发回确认。

方案优点:逻辑简单。

在聊天消息不同数量级时的表现:

  • a. 离线消息量不多(如几百条):没有效率问题,且消息全部达到客户端本地,方便进行查找等动作;
  • b. 离线消息量巨大(如几万条):用户登录瞬间CS间瞬时流量大,客户端瞬时要存储、更新的数据量巨大,可能出现卡顿、假死等情况。

6.3.2)用会话列表为基础的方案优缺点:

实现原理:客户端先同步会话列表,由用户驱动不定次获取同步消息。

方案缺点:逻辑复杂,客户端增加不少工作。

在聊天消息不同数量级时的表现:

  • a. 离线消息量不多(如几百条):没优势;
  • b. 离线消息量巨大(如几万条):登录时交互数据小,对IM后端、客户端、用户体验,都比较友好。

7、多终端条件下,如何得到完整消息履历?

由于同一个用户的每个终端,其会话最后更新时间、每个会话的最后一条时间可能都不一样,参照上一节的实现思路,可以得到解决方案。

具体如下:

  • 1)参照第6.2章节的“App和IM后端的交互”第1个步骤,可取到不同的增量变化的会话列表项;
  • 2)参照第6.2章节的“App和IM后端的交互”第4个步骤,可取到任一区间的同步消息,得到完整消息。

8、离线消息是否就彻底废弃了?

有若干情况,仍然需要保留离线消息,以确保消息送达。

比如以下情形:

  • 1)别人向我发送离线文件:这种情况下不能依赖同步消息来获取。因为不以离线消息通知的话,用户在没有拉取到对应的同步消息前,是不知道有离线文件的;
  • 2)撤回消息:即使接收者不拉取同步,仍然要保证在上线后其数据在第一时间被撤回。注意:这里可能存在多端撤回问题;
  • 3)用户在线时的消息下发:由于用户在线时,IM后端向客户端发送消息可能碰到网络抖动等情况,导致消息下发失败,这些消息先可以直接存在离线消息队列,IM后端可在收到客户端的心跳包时重发消息。相当于维护了一个在线消息的离线队列。

9、本文结语

曾经有一段真挚的爱情摆在我面前,如果时间倒流到半年前,我会选择一个靠谱的IM来发送消息,也许故事的脚本就由自己书写——是否要整一个时光倒流的版本,抱得美人归的那种?

不整了不整了,我得不到女神,你们才欢喜,我太了解你们了。。。各位爷欢喜就好。

附录:IM开发干货系列文章

本文是系列文章中的第26篇,总目录如下:

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

IM消息送达保证机制实现(二):保证离线消息的可靠投递

如何保证IM实时消息的“时序性”与“一致性”?

IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?

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

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

移动端IM登录时拉取数据如何作到省流量?

通俗易懂:基于集群的移动端IM接入层负载均衡方案分享

浅谈移动端IM的多点登陆和消息漫游原理

IM开发基础知识补课(一):正确理解前置HTTP SSO单点登陆接口的原理

IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?

IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议

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

IM群聊消息的已读回执功能该怎么实现?

IM群聊消息究竟是存1份(即扩散读)还是存多份(即扩散写)?

IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

一个低成本确保IM消息时序的方法探讨

IM开发基础知识补课(六):数据库用NoSQL还是SQL?读这篇就够了!

IM里“附近的人”功能实现原理是什么?如何高效率地实现它?

IM开发基础知识补课(七):主流移动端账号登录方式的原理及设计思路

IM开发基础知识补课(八):史上最通俗,彻底搞懂字符乱码问题的本质

IM的扫码登功能如何实现?一文搞懂主流应用的扫码登陆技术原理

IM要做手机扫码登陆?先看看微信的扫码登录功能技术原理

IM开发基础知识补课(九):想开发IM集群?先搞懂什么是RPC!

IM开发实战干货:我是如何解决大量离线聊天消息导致客户端卡顿的

IM开发干货分享:如何优雅的实现大量离线消息的可靠投递》(* 本文)

另外,如果您是IM开发初学者,强烈建议首先阅读《新手入门一篇就够:从零开发移动端IM》。

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

posted @ 2020-07-21 13:58 Jack Jiang 阅读(170) | 评论 (0)编辑 收藏

本文在编写时参考了博客作者“鹿呦呦”和在线课程“即时消息技术剖析与实战”的相关资料,一并表示感谢。

1、系列文章引言

IM系统看似简单(没错,很多土老板认为开发个qq和微信也就是几万块钱的事... ),实责是众多技术的应用合体,包括网络编程、移动开发、后端开发、高并发、高可用、高安全等技术范畴,再加上多端使用不同的编程语言,想要凑齐一个典型的IM产品技术栈那也不是个容易事。

而对于IM开发入门者来说,想要在众多的IM技术术语和概念中找到学习的方向和需要的资料,那也是件很让人抓狂的事。如果看到不该看的技术深水区文章,直接从入门到放弃——被活活吓退,那也是相当悲剧的。

本系列文章将尽量从理论概念入手,通俗易懂的梳理IM中的基础技术概念和热门技术点,希望能帮你理清看似一团乱麻的IM知识体系,助你找到清晰的IM技术学习方向,来日工资翻倍、迎娶白富美也未必不可能!

 

友情提示:本系列文章侧重于理论概念的讲述,篇幅有限,点到即止,如需系统、深入、具体地学习IM技术的方方面面,请从此文入手:《新手入门一篇就够:从零开发移动端IM》(史诗级文章,适合从入门到放弃)。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

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

2、系列文章目录

IM开发快速入门(一):什么是IM系统?》(* 本文

《IM开发快速入门(二):什么是IM系统的实时性? (稍后发布)》

《IM开发快速入门(三):什么是IM系统的可靠性? (稍后发布)》

《IM开发快速入门(四):什么是IM系统的一致性? (稍后发布)》

《IM开发快速入门(五):什么是IM系统的安全性? (稍后发布)》

《IM开发快速入门(六):什么是IM系统的的心跳机制? (稍后发布)》

《IM开发快速入门(七):如何理解并实现IM系统消息未读数? (稍后发布)》

《IM开发快速入门(八):如何理解并实现IM系统的多端消息漫游? (稍后发布)》

3、本文内容概述

本文将带你快速了解一个主流IM系统的应用场景、典型架构、技术特点和功能组成,帮你快速建立对IM系统的主观认知。

如果你不想从技术的角度理解IM原理,可以尝试阅读此文:《知识科普:IM聊天应用是如何将消息发送给对方的?(非技术篇)》。

本文已收入即时通讯网的入门纲领性文章《新手入门一篇就够:从零开发移动端IM》。

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:https://mp.weixin.qq.com/s/h7L4UGHRl7qI1bi8WyZ5iw,原文链接是:http://www.52im.net/thread-3065-1-1.html

4、IM的应用场景

IM其实并不局限于聊天、社交这类“典型”应用中,实际上它已经广泛运用于我们身边形形色色的软件中。

聊天、直播、在线客服、物联网等所有需要实时互动、高实时性的场景等等,都需要应用到 IM 技术。

下面这些场景是我们大家都熟悉的,都用到了IM技术:

  • 1)微信、qq、钉钉等主流IM应用:这是IM技术的典型应用场景;
  • 2)微博、知乎等社区应用:它们利用IM技术实现了用户私信等点对点聊天;
  • 3)抖音、快手等直播/短视频应用:它们利用IM技术实现了与主播的实时互动;
  • 4)米家等智能家居物联网应用:利用IM技术实现实时控制、远程监控等;
  • 5)滴滴、Uber等共享家通类应用:利用IM技术实现位置共享;
  • 6)在线教育类应用:利用IM技术实现在线白板。 

5、IM的典型架构

一个典型的IM架构类似于下图这样:

本图引用自《即时消息技术剖析与实战》学习笔记1——IM系统的架构》一文

如上图所示,IM架构中的各分层职责如下:

  • 1)客户端:作为与服务端进行消息收发通信的终端;
  • 2)接入层:也叫网关层,为客户端收发消息提供入口;
  • 3)逻辑层:负责IM系统各功能的核心逻辑实现;
  • 4)存储层:负责IM系统相关数据的持久化存储,包括消息内容、账号信息、社交关系链等;
  • 5)第三方服务:保证APP在未打开或后台运行时也能收到消息通知(这主要是第第3方消息推送服务)。

尤其对于“接入层”,它的职责最为关键,具体是:

  • 1)保持海量用户连接;
  • 2)解析协议,对传输内容进行编解码;
  • 3)维护客户端的连接(也叫“Session”);
  • 4)推送消息。

以下文章适合IM架构设计入门,有兴趣可以读一读:

6、IM技术的特点

IM技术的特点主要就是以下4点: 

▶ 1)实时性:

对于IM系统,“实时”二字是精髓,也是这项技术存在关键意义所在。它保证的是消息的实时触达。

举个例子:如果跟你的好友微信或qq聊天,我发的消息他不能即时收到,或者他发的信息你也不知道什么时候能收到,这基本上也就没法聊下去了(干吗不痛快打个电话呢)。

▶ 2)可靠性:

保证消息的不丢失和不重复,是IM系统的另一个关键技术特点。试想,当你在用qq或微信跟女朋友聊天,好不容易鼓起勇气向“她”表白,结果这消息要是丢包了,那肯定得卸载应用了,搞不好砸手机都有可能。当然,好话不说二遍,消息重复也同样恼人。

以下文章对消息的不丢/不重问题进行了深入探讨,有兴趣可以详读:

▶ 3)一致性:

对于单聊消息而言,保证同一个设备的时间顺序、不同设备的漫游同步,也是相当重要的一环。

IM系统中的消息交互,就到底就是人跟人在“说话”,前言不搭理后言、或者胡言乱语式的消息展现,那不是人疯了就是程序疯了,总之就是没法再聊下去了。

以下文章对消息时序问题进行了深入探讨,有兴趣可以详读:

▶ 4)安全性:

保证数据传输安全、数据存储安全、消息内容安全,也是IM系统必不可少的特性。尤其在私聊场景下,如果不能做到安全性,聊天的体验跟被人偷窥的感觉是没有区别的。

以下文章对IM的安全问题进行了深入探讨,有兴趣可以详读:

7、IM的功能组成

浅显的角度讲,一个典型的IM功能组成,无非就是以下5样:

  • 1)联系人列表;
  • 2)聊天界面;
  • 3)消息发送通道;
  • 4)消息接收通道;
  • 5)消息存储;
  • 6)消息未读数。

我们一样一样来说说各自的用途。

▶ 1)联系人列表:

这个很好理解,使用IM系统的第一步,就是要解决“跟谁聊”的问题。从功能表象上来说,联系人列表也就是社交关系列表,无非就是个信息列表界面,有什么特殊的地方?

联系人列表看似简单,实际上它是一系列IM系统的社交关系确立动作的结果体现。

要想建立联系人列表,你可能需要实现以下逻辑:

  • 1)怎么能找到想要聊天的人?(需要实现随机查找?精确查找?)
  • 2)怎么决定要不要跟这个人聊?(需要实现对方的个人信息查看)
  • 3)开始发出好友请求;
  • 4)被请求的一方,还可以决定是“同意”还是“拒绝”(“同意”该怎么处理?“拒绝”又该怎么处理?)。

总的来说,联系人列表的建立,是一个IM系统聊天关系确立的表现,不可或缺。

▶ 2)聊天界面: 

聊天界面看似很平常,实际它就是IM系统客户端的核心功能所在,所有主要的IM功能都是通过它展现。

它应该具备的能力有:

  • 1)各种聊天功能按钮:语音留言、图片、文字、表情、文件、实时电话、实时视频等;
  • 2)各种聊天消息显示:各种消息都有不同的UI显示元素和处理逻辑;
  • 3)流畅的使用体验:大量不同类型的消息显示时,不能卡顿;
  • 4)即时显示聊天消息:网络线程收到的消息,要马上在UI上显示出来;
  • 5)历史消息的加载:上次聊过的内容也得显示出来吧。

以上只是简单罗列,这看似简单的聊天界面,能把上面列表的事情做好,工作量也不小吧。

▶ 3)消息发送通道:

下图是一个典型的IM消息收发通道示意: 

如上图所示,消息发送通道这个比较好懂,最浅显易懂的理解就是用tcp或udp,建立socket长连接,需要发消息的时候,wirte一下就过去了,好简单!

但,事情往往不是想象的这么简单:

  • 1)如何保证这条socket长连接时一直处于可用的状态?
  • 2)当socket长连接不可用时,用户此时发送的消息该怎么处理?
  • 3)怎么保证发送的消息不丢?
  • 4)怎么保证发送的消息不复重?
  • 5)怎么保证发送的消息乱序?
  • 6)当对方不在线时,发送的消息去哪了?
  • 7)发送的消息,能保证实时送到?

这么一说,事情还挺多(那不废话吗。。。)。

▶ 4)消息接收通道:

正如上节中的消息收发通道示意图所示,消息接收通道也很好理解,对方通过消息发送通道write的消息,我得收到并显示啊。

要实现一个可靠的消息接收通道,也并非易事:

  • 1)如何保证socket长连接通道能随时处于良好的边接状态(随时接收对方write的消息);
  • 2)当socket长连接断开时,对方发送消息该怎么实现?
  • 3)当socket恢复连接时,怎么恢复之前的聊天现场?
  • 4)当我收到对方的消息时,对方怎么知道我已经收到了?
  • 5)当重复收到对方的消息时,该怎么处理?
  • 6)当收到的消息时序有错乱,该怎么处理?

▶ 5)消息存储:

消息存储这个功能好理解,聊天的消息如果存储,下次再聊的时候就不知道之前聊过什么,做不到这一点,这个IM系统的聊天体验好不起来。

那么,哪些情况下需要进行消息存储呢:

  • 1)对方不在线时:聊天消息应该存储(这叫离线消息存储);
  • 2)对方在线时:聊天消息也要存到本地存储(这叫消息缓存);
  • 3)对方在线或不在线时:聊天消息都要存到服务端(用于实现多设备的消息漫游和同步)。

具体要存储的内容和时机也就上面这几样。

但技术落到实处,要做的事情同样少不了:

  • 1)离线消息该怎么多久?
  • 2)图片、短视频、大文件这类的离线消息,多媒体文件该怎么存(有可能量会很大)?
  • 3)当本地的消息积累太多时,怎么能保证本地存储的性能?
  • 4)当应用更新、升级或异常时,怎么能保证本地存储的完整性(不被破坏)?
  • 5)怎么能保证多设备消息能不丢、不重、不乱?

这么多需要考虑的内容,也挺让人抓狂。

下图是一个IM系统的典型存储架构设计,了解一下:

本图引用自《现代IM系统中聊天消息的同步和存储方案探讨》一文

存储是IM系统的基石,以下文章可以深入阅读:

▶ 6)消息未读数:

消息未读数?看起来也就是那个所有IM应用都有的未读小红点嘛。是的,看起来也好简单!

然而,消息未读数功能的实现也一样不简单:

  • 1)未读数是客户端实现还是服务端实现?
  • 2)会话未读和总未读怎么保持一致?
  • 3)多终端情况下,怎么保证未读数的一致性(我在这台设备上读没读,那台设备怎么知道的?)?

是的,看起来就这么简简单单的3件事,但深入思考一下,还真的简单不起来。

8、本文小结

IM系统的应用场景已经不单单是IM聊天应用这一种形态,它已经融入到互联网应用的方方面面,必竟谁都想自已的应用具备“实时”交互这种能力,因为体验太好了。

IM系统典型架构无非就是网络接入层、业务逻辑层、数据存储层,除开网络接入层,其它各层其实跟普通的应用系统看起来差别并不是太大。

IM系统的技术特点来说,就是实时性、可靠性、一致性、安全性,除了实时性对于多数应用来说并不关心,其它的指标也很好理解。

IM系统的功能组成上,联系人列表用于数据模型的建立、聊天界面承载了IM系统的终端展现、消息的收发通道用于实现“实时”这个特性、存储和未读数看似不是必须但用户体验上确必不可少。

附录:更多IM开发资料汇总

[1] 有关IM架构设计的文章:

浅谈IM系统的架构设计

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

一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

一套原创分布式即时通讯(IM)系统理论架构方案

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

蘑菇街即时通讯/IM服务器开发之架构选择

腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT

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

微信技术总监谈架构:微信之道——大道至简(演讲全文)

如何解读《微信技术总监谈架构:微信之道——大道至简》

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

17年的实践:腾讯海量产品的技术方法论

移动端IM中大规模群消息的推送如何保证效率、实时性?

现代IM系统中聊天消息的同步和存储方案探讨

WhatsApp技术实践分享:32人工程团队创造的技术神话

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

王者荣耀2亿用户量的背后:产品定位、技术架构、网络方案等

IM系统的MQ消息中间件选型:Kafka还是RabbitMQ?

腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面

以微博类应用场景为例,总结海量社交系统的架构设计步骤

快速理解高性能HTTP服务端的负载均衡技术原理

子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技术实践

IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

微信技术分享:微信的海量IM聊天消息序列号生成实践(容灾方案篇)

新手入门:零基础理解大型分布式架构的演进历史、技术原理、最佳实践

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

社交软件红包技术解密(一):全面解密QQ红包技术方案——架构、技术实现等

社交软件红包技术解密(二):解密微信摇一摇红包从0到1的技术演进

社交软件红包技术解密(三):微信摇一摇红包雨背后的技术细节

社交软件红包技术解密(四):微信红包系统是如何应对高并发的

社交软件红包技术解密(五):微信红包系统是如何实现高可用性的

社交软件红包技术解密(六):微信红包系统的存储层架构演进实践

社交软件红包技术解密(七):支付宝红包的海量高并发技术实践

社交软件红包技术解密(八):全面解密微博红包技术方案

社交软件红包技术解密(九):谈谈手Q红包的功能逻辑、容灾、运维、架构等

社交软件红包技术解密(十):手Q客户端针对2020年春节红包的技术实践

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

从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结

IM开发基础知识补课(六):数据库用NoSQL还是SQL?读这篇就够了!

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

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

从游击队到正规军(三):基于Go的马蜂窝旅游网分布式IM系统技术实践

微信后台基于时间序的新一代海量数据存储架构的设计实践

IM开发基础知识补课(九):想开发IM集群?先搞懂什么是RPC!

>> 更多同类文章 ……

[2] IM开发热门综合文章:

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

移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端IM开发者必读(二):史上最全移动弱网络优化方法总结

从客户端的角度来谈谈移动端IM的消息可靠性和送达机制

IM开发基础知识补课:正确理解前置HTTP SSO单点登录接口的原理

移动端IM中大规模群消息的推送如何保证效率、实时性?

移动端IM开发需要面对的技术问题

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

请问有人知道语音留言聊天的主流实现方式吗?

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

IM消息送达保证机制实现(二):保证离线消息的可靠投递

如何保证IM实时消息的“时序性”与“一致性”?

一个低成本确保IM消息时序的方法探讨

IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?

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

谈谈移动端 IM 开发中登录请求的优化

移动端IM登录时拉取数据如何作到省流量?

浅谈移动端IM的多点登录和消息漫游原理

完全自已开发的IM该如何设计“失败重试”机制?

通俗易懂:基于集群的移动端IM接入层负载均衡方案分享

微信对网络影响的技术试验及分析(论文全文)

即时通讯系统的原理、技术和应用(技术论文)

开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀

如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源

全面掌握移动端主流图片格式的特点、性能、调优等

子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技术实践

IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

自已开发IM有那么难吗?手把手教你自撸一个Andriod版简易IM (有源码)

融云技术分享:解密融云IM产品的聊天消息ID生成策略

IM开发基础知识补课(六):数据库用NoSQL还是SQL?读这篇就够了!

适合新手:从零开发一个IM服务端(基于Netty,有完整源码)

拿起键盘就是干:跟我一起徒手开发一套分布式IM系统

适合新手:手把手教你用Go快速搭建高性能、可扩展的IM系统(有源码)

IM里“附近的人”功能实现原理是什么?如何高效率地实现它?

IM要做手机扫码登录?先看看微信的扫码登录功能技术原理

IM消息ID技术专题(一):微信的海量IM聊天消息序列号生成实践(算法原理篇)

IM消息ID技术专题(二):微信的海量IM聊天消息序列号生成实践(容灾方案篇)

IM消息ID技术专题(三):解密融云IM产品的聊天消息ID生成策略

IM消息ID技术专题(四):深度解密美团的分布式ID生成算法

IM消息ID技术专题(五):开源分布式ID生成器UidGenerator的技术实现

IM开发宝典:史上最全,微信各种功能参数和逻辑规则资料汇总

IM开发干货分享:我是如何解决大量离线消息导致客户端卡顿的

IM开发快速入门(一):什么是IM系统?

>> 更多同类文章 ……

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

posted @ 2020-07-09 14:16 Jack Jiang 阅读(222) | 评论 (0)编辑 收藏

1、引言

IM系统中,特别是在企业应用场景下,消息的已读未读状态是一个强需求。

以阿里的钉钉为例,钉钉的产品定位是用于商务交流,其“强制已读回执”功能,让职场人无法再“假装不在线”、“假装没收到”。更有甚者,钉钉的群聊“强制已读回执”功能,甚至能够知道谁读了消息,谁没有读消息(老板的福音啊)。

 

▲ 钉钉里的群聊消息已读未读功能效果

功能看起来很酷,但用起来是一言难尽(上班族心里苦.... )。实际上,技术实现也并不容易。

那么,对于已读未读状态:

  • 1)如果是私聊:消息的阅读状态比较容易实现,在性能和存储上也不存在问题;
  • 2)如果是群聊:考虑到存储和处理性能,特别当处于一个云环境时,如何高效地处理群聊的已读未读状态是一个非常值得探讨的话题。

这里提到的“高效”含3个方面:

  • 1)存储空间;
  • 2)处理速度;
  • 3)传输字节数。

本文将从服务端的角度来探讨已读未读状态,在具体的技术实现上对于存储空间占用方面的思路差异。能力有限,权当个人笔记,欢迎交流。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

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

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:https://mp.weixin.qq.com/s/yUkKPOBsdqLlxiFrGmwFRQ,原文链接是:http://www.52im.net/thread-3054-1-1.html

2、内容点评

在收录本文前,Jack Jiang建议原作者对某些具体的技术点进行更深入的分享,但因作者工作较忙,本文中的某些关键技术点未来的及作进一步展开。

所以,本文可以作为IM聊天消息(主要是群聊)中已读未读功能的基本实现思路方面的参考,但不建议盲目迷信文中的结论或方案,避免被一些不够具体的技术指标而误导。

3、相关文章

如果你还想了解更多有关IM群聊中已读未读功能的实现逻辑,可以进一步阅读干货文章《IM群聊消息的已读回执功能该怎么实现?》(强烈推荐)。

如果你对IM中的已读未读功能有产品方面的痛点困惑,可以参考一下微信对已读未读功能的设计定位,详见《IM热门功能思考:为什么微信里没有消息“已读”功能?》。

更多IM群聊技术方面的文章详见文本附录部分。

4、已读未读状态交互流程

发送者发送的IM聊天消息,在接收者阅读消息后,是否要求阅读者通知已读,可能是由系统配置、组织配置、群组配置等决定,也可能由发送者根据业务需求决定。以下的讨论,均假设消息需要已读未读状态。

客户端与服务端之间,关于阅读状态的命令只需3个,每个命令含请求和应答。

4.1 通知消息已读(私聊、群聊通用)

当小宝阅读了一条或若干条消息,需向服务端发送消息已读通知:“众爱卿发的x+y+z消息,朕已阅”。

服务端收到小宝的已读通知时,需完成以下事项:

  • 1)存储消息的已读状态;
  • 2)返回应答给小宝;
  • 3)向已读列表的消息的原始发送者通知消息已读。

对于第“3)”步:

  • 1)私聊的场合,比较好理解,就是发送给私聊的对方;
  • 2)群聊的场合,可很不一样:因为小宝发送的已读消息列表,可能是由众爱卿发送的。考虑这种假设:张三、李四、王五发出的群聊消息,被小宝一下都阅读了,那么小宝发出的已读通知包含的消息列表,需要被IMS分解成3个已读通知(3个不同的消息列表),分别通知给张三、李四、王五,通知内容是“爱卿(不含'"众")发的这些消息,朕已阅”。

下面是大致的逻辑流程图: 

4.2 查询消息的未读人数(私聊、群聊通用)

消息的发送者,加载消息列表到聊天窗口时,可能需要展示消息是否被已读。

对群聊而言,显示的信息可能是n人未读的提示,那么需要向服务端查询消息的未读人数,由于客户端可能在UI显示自己发出的多条消息,需支持一次请求查询多条消息。

以未读人数的方式来表示消息的阅读状态,统一了私聊、群聊的查询,使得客户端-服务端间的接口更简单,同时使客户端的实现逻辑更统一。

就像下面这样:

  • 1)对于私聊:如果未读人数n>0,表示消息未读;
  • 2)对于群聊:直接显示n人未读即可,当然,当n等于0时表示全部已读。

4.3 查询群消息的已读、未读人员清单(群聊)

当客户端希望显示某一条群聊消息的已读、未读人员列表,需向服务端发起查询。

大致的逻辑流程图如下:

5、几种具体的已读未读状态存储思路探讨

5.1 基本约定

群聊的阅读状态比私聊复杂,因此这里着重讨论群聊的阅读状态。

假设群成员数是n,各个客户端立即IM服务端发送已读通知。服务端需存储每个人的阅读状态,包括那些未读的成员。由于群的成员清单可能变化,比如今天增加了一个成员,则昨天发的消息、与今天发的消息,其接收者列表不一样。

即:

  • 1)同一个群的不同消息,对应的接收者列表可能不一样。
  • 2)换言之,每一条消息都需要记录完整的接收者列表和已读人员列表。

为了方便讨论,本章假设群成员有640人为前提。

5.2 存储思路1

每一条消息都维护:

  • 1)接收人员列表receiver_list;
  • 2)已读人员列表read_list。

具体是:

  • 1)IM Server收到一条消息时,用全体群成员构建receiver_list;
  • 2)IM Server收到群成员对这条消息的已读通知时,将此成员加入到read_list。

客户端获取此消息的数据:

  • 1)当需要获取未读人数时,用receiver_list的个数减去read_list的个数;
  • 2)当需要获取已读、未读人员列表时,需用receiver_list减去read_list得到未读人员列表。

那么,思路1每条消息的存储空间是:

640个ID + 不定数量的已读人员ID

5.3 存储思路2

每一条消息维护:

  • 1)未读人员列表unread_list;
  • 2)已读人员列表read_list。

具体是:

  • 1)IM Server收到一条消息时,用全体群成员构建unread_list;
  • 2)IM Server收到群成员对这条消息的已读通知时,将此成员从unread_list移出,同时加入到read_list。

客户端获取此消息的数据:

  • 1)当需要获取未读人数时,直接计算unread_list的个数;
  • 2)当需要获取已读、未读人员列表时,直接返回unread_list和read_list。

那么,思路2每条消息的存储空间是:

未读人员ID + 已读人员ID,合计640个ID

思路2的实现,占用的空间是案1的0.5倍~1.0倍。即案2占用的空间少,但在每次收到客户端的已读通知时,比案1多了一个操作:从unread_list进行减员。

5.4 存储思路3(我的实现)

5.4.1)探讨5.2节、5.3节的不足:

5.2节、5.3节这两种思路,都能满足功能需求,但存在巨大的存储浪费。

该群有640人,如果群内聊天每天有1024条消息,人员ID以4字节存储计算,那么为该群每天的消息阅读状态需要消耗的空间是:

5.2节思路1:1024 * (640 * 4 + 已读人数 * 4),范围是 2.5MB ~ 5MB;

5.3节思路2:1024 * 640 * 4,等于2.5MB。

这仅仅是一个群在一天之内产生的阅读状态数据,如果是在云平台运行,单此功能消耗的空间,呵呵~~

题外话:如果成员不是用4字节整型存储,而改用字符串,比如"1123356777",那就更可观了。

5.4.2)如何减少存储空间:

考虑群成员并非时时刻刻都在变化,多数情况下,群成员的列表是相对稳定的,今天的和上周(甚至更久以前)的列表甚至可能是一样的,那么有可能几百条消息,甚至几万条消息对应的群成员列表是相同的。

因此,引出本文的重点思想:

考虑让不同的消息共用群成员列表,即把消息的阅读状态与群成员列表分开存储,并记录它们之间的关联。

假定平均每1024条消息共用一个群成员列表,发了1024条消息后,群成员变化了,此后需要用新的群成员列表。

那么这一千条消息的阅读状态所占用的空间是:

群成员列表空间 + 1024条消息的阅读状态:640 * 4 + 1024 * 每条消息的阅读状态所占空间

在具备群成员列表的前提下,如何减少每条消息的阅读状态所占空间?

很自然会想到用bit来表示已读人员,因为一个32位整型可表示32个人的已读状态。bit的顺序只需与群成员列表的顺序一致即可。

当一条消息没有人已读时,阅读状态占用0字节;当群内每个人都阅读时,占用的空间最大,即640 / 32 = 20字节。

因此优化之后,这一千条消息的阅读状态所占用的空间,范围是2.5KB ~ (2.5KB + 1024 * 20B),即2.5KB ~ 22.5KB,此数值与5.2节思路1、5.3节思路2对比,有了极大幅度地下降。

如下图所示:

该表格的前提条件:

  • 1)一个群有640人;
  • 2)该群连续1024条消息对应的群成员列表是稳定的。

退一步考虑,哪怕这1024条消息对应的群成员列表不稳定,中间变化了10次,那么也仅会多出2.5KB * 10即25KB的存储空间,与案1、案2相比仍然有极大优势。

6、如何提高已读未读状态的处理速度

小宝往公司群发了一条消息我来给大家介绍一下新来的女同事,大家立即、马上、瞬间、闪电般地查看消息,感觉迟1秒就会失去秒杀女神的机会一样,意味着一瞬间会有N多条已读通知发送到IMS。

对这些消息的处理流程是一样的:

  • 1)可合并这些操作以批量形式进行存储、转发;
  • 2)由于存储消息的阅读状态是一个设置bit的过程,所以不存在互斥的问题,即使在分布式环境也可以放心操作;
  • 3)消息对应的成员列表信息可临时缓存在内存对象内,以减少查询IO,提高效率。

附录:更多IM群聊技术文章

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

如何保证IM实时消息的“时序性”与“一致性”?

IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?

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

微信后台团队:微信后台异步消息队列的优化升级实践分享

移动端IM中大规模群消息的推送如何保证效率、实时性?

现代IM系统中聊天消息的同步和存储方案探讨

关于IM即时通讯群聊消息的乱序问题讨论

IM群聊消息的已读回执功能该怎么实现?

IM群聊消息究竟是存1份(即扩散读)还是存多份(即扩散写)?

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

[技术脑洞] 如果把14亿中国人拉到一个微信群里技术上能实现吗?

IM群聊机制,除了循环去发消息还有什么方式?如何优化?

网易云信技术分享:IM中的万人群聊技术方案实践总结

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

IM群聊消息的已读未读功能在存储空间方面的实现思路探讨

>> 更多同类文章 ……

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

posted @ 2020-07-02 14:04 Jack Jiang 阅读(198) | 评论 (0)编辑 收藏

1、引言

IM在Android上的保活问题经常在即时通讯网的论坛和技术群里被讨论,自从Android 8.0后系统大大降低了后台运行应用的保活容忍度(详见《Android P正式版即将到来:后台应用保活、消息推送的真正噩梦》),保活从黑科技横行的时代进入了技术蛮荒阶段,真要实现保活,技术难度越来越大。

不过话说回来,既然用黑科技进行保活是Andriod技术的逆潮流,那何不回头是岸,做个“良民”?

本文将以某款线上的IM产品为例,介绍它是如何引导用户在多款主流机型上加白名单的,并分享了该款IM中已制作完成的多达7款主流Andriod机型的详细加白FAQ页面资源(含完整HTML+图片),方便您进行参考、学习和研究,希望能为你的应用开发带来帮助。

特别申明:本文示例中的资源来自某款真实的IM产品,仅供学习和研究,请勿用作非法用途,如有侵权,请告之于我。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

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

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:https://mp.weixin.qq.com/s/JqWloZLBYicpxElVL_HKYw ,原文链接是:http://www.52im.net/thread-3033-1-1.html

2、Android保活,变的越来越不可能了

IM产品在Android上的保活问题从早期的系统版本到现在,从未有人停止过尝试。即时通讯通讯网也随着Andriod系统版本的升级,持续整理了很多篇相关文章,比如下面这些(文章的顺序按照Android系统的版本从低到高)。

上面这些文章,我们可以看到,自从Android 8.0(即Andriod P)以后,IM以及其它需要在后台保活的产品,存活难度越来越高,黑科技几乎都不起作用了。

于是,一些技术从牛们只能从更深的Android系统层面尝试突破系统的保活限制,比如这两篇:《史上最强Android保活思路:深入剖析腾讯TIM的进程永生技术》、《Android进程永生技术终极揭密:进程被杀底层原理、APP应对被杀技巧》。

正如上面两篇文章,为了跟系统作斗争,可谓斗智斗勇。但Android系统的历史进程终究无人能阻挡,越来越严格的保活限制已经是Android官方及各大手机厂商的共识。

好吧,之前费尽心机折腾的各种黑科技,如今就像浮云一样。。。

 

3、死磕保活?别做梦了,回头是岸

正如上节所述,鉴于Andriod保活变的越来越不可能,很多原本靠黑科技保活的产品,开始重新审视保活技术实现,到底是把保活黑科技这条路走到黑,还是回归Android官方最佳实践(乖乖引导用户手动设置白名单)?

我个人认为,后者是保活技术发展的必然结果,就像之前分享的这篇文章里所做的尝试一样:《2020年了,Android后台保活还有戏吗?看我如何优雅的实现!》,规范地引导用户“加白”。

放弃“黑科技”,并不意味着技术不行,回归“良民”,反而变的一身轻松。

 

4、调用系统代码引导用户加白名单,也不完美

之前整理的《2020年了,Android后台保活还有戏吗?看我如何优雅的实现!》一文,是按照不同的机型,自动适配代码并在代码中调用系统的加白名单设置功能。

比如像下面这样的代码调用:

▲ 以下代码引用自《2020年了,Android后台保活还有戏吗?看我如何优雅的实现!

会弹出这样一个窗口:

这个方法确实不错,但因为机型不同、同机型的ROOM版本不同,代码的兼容处理,可能会相当复杂,所以方法虽好,但也并不能一劳永逸的解决所有问题。

5、应用内提供更多机型的“加白”FAQ帮助,是一个补充办法

正如上节所示,调用系统代码引导用户加白名单确实算的上“优雅”,但在不同的机型、同机型的不同系统版本上,可能差异很大,代码兼容性是个头疼的问题,总之这不是个百分百完美的办法。

这就需要一个补充手段,比如我们可以针对大量不同的机型,针对它的最行或最常用系统版本,在应用内以FAQ帮助网页的方式,为用户提供帮助。

比如可以在手机里打开像下面这样FAQ网页页面:

至少能在调用系统代码无法实现的情况下,可以让用户自主找到解决问题的办法。而这便是本文要分享,下节内容会以一个市面上做的比较好的IM应用为例,为你提供一个完整示例。

6、一个完整的“加白”FAQ帮助示例

最近发现的一款市面上的IM应用(此产品跟即时通讯网无任何关系,仅仅是作为技术研究参考对象而已),它内置的“加白”FAQ帮助就很完善。

以下是从该款IM中截下来的图: 

 

以下是该款IM应用中的运行演示视频(点此打开视频链接):

 

目前该应用中FAQ帮助已覆盖7款主流Andriod机,以下是完整示例页面链接:

可以看到,这款IM里的“加白”FAQ做的还是比较细、覆盖的机型也比较典型, 如果你有类似的想法或需求,完全可以参考这款产品的实现。尤其在一些特定的场景(比如企业内部的IM等)下,这种方式还是能解决大部分终端用户的问题的。

7、覆盖7款主流机型的“加白”FAQ页面静态资源(附件下载)

我整理了上节中提到的这款IM产品中的全部“加白”FAQ帮助页面静态资源,覆盖7款主流Andriod机型,如果你也需要同样的东西,可以参考这份完整的示例实现,打包到手机中使用之。

以下是这份静态资源示例的内容(图太长,已截掉了一部分): 

以下是这份静态资源示例的打包附件:

请从原文附件中下载:http://www.52im.net/thread-3033-1-1.html

附录:更多精品资源汇总

[1] 精品源码下载:

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

轻量级即时通讯框架MobileIMSDK的iOS源码(开源版)[附件下载]

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

微信本地数据库破解版(含iOS、Android),仅供学习研究 [附件下载]

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

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

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

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

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

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

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

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

高仿Android版手机QQ首页侧滑菜单源码 [附件下载]

开源libco库:单机千万连接、支撑微信8亿用户的后台框架基石 [源码下载]

分享java AMR音频文件合并源码,全网最全

微信团队原创Android资源混淆工具:AndResGuard [有源码]

一个基于MQTT通信协议的完整Android推送Demo [附件下载]

Android版高仿微信聊天界面源码 [附件下载]

高仿手机QQ的Android版锁屏聊天消息提醒功能 [附件下载]

高仿iOS版手机QQ录音及振幅动画完整实现 [源码下载]

Android端社交应用中的评论和回复功能实战分享[图文+源码]

Android端IM应用中的@人功能实现:仿微博、QQ、微信,零入侵、高可扩展[图文+源码]

仿微信的IM聊天时间显示格式(含iOS/Android/Web实现)[图文+源码]

Android版仿微信朋友圈图片拖拽返回效果 [源码下载]

[2] 精品文档和工具下载:

计算机网络通讯协议关系图(中文珍藏版)[附件下载]

史上最全即时通讯软件简史(精编大图版)[附件下载]

重磅发布:《阿里巴巴Android开发手册(规约)》[附件下载]

阿里技术结晶:《阿里巴巴Java开发手册(规约)-终极版》[附件下载]

基于RTMP协议的流媒体技术的原理与应用(技术论文)[附件下载]

独家发布《TCP/IP详解 卷1:协议》CHM版 [附件下载]

良心分享:WebRTC 零基础开发者教程(中文)[附件下载]

MQTT协议手册(中文翻译版)[附件下载]

经典书籍《UNIX网络编程》最全下载(卷1+卷2、中文版+英文版)[附件下载]

音视频开发理论入门书籍之《视频技术手册(第5版)》[附件下载]

国际电联H.264视频编码标准官方技术手册(中文版)[附件下载]

Apache MINA2.0 开发指南(中文版)[附件下载]

网络通讯数据抓包和分析工具 Wireshark 使用教程(中文) [附件下载]

最新收集NAT穿越(p2p打洞)免费STUN服务器列表 [附件下载]

高性能网络编程经典:《The C10K problem(英文)》[附件下载]

即时通讯系统的原理、技术和应用(技术论文)[附件下载]

技术论文:微信对网络影响的技术试验及分析[附件下载]

华为内部3G网络资料: WCDMA系统原理培训手册[附件下载]

网络测试:Android版多路ping命令工具EnterprisePing[附件下载]

Android反编译利器APKDB:没有美工的日子里继续坚强的撸

一款用于P2P开发的NAT类型检测工具 [附件下载]

两款增强型Ping工具:持续统计、图形化展式网络状况 [附件下载]

Android保活从入门到放弃:乖乖引导用户加白名单吧(附7大机型加白示例)

[3] 精选视频、演讲PPT下载:

美图海量用户的IM架构零基础演进之路(PPT)[附件下载]

开源实时音视频工程WebRTC的架构详解与实践总结(PPT+视频)[附件下载]

QQ空间百亿级流量的社交广告系统架构实践(视频+PPT)[附件下载]

海量实时消息的视频直播系统架构演进之路(视频+PPT)[附件下载]

YY直播在移动弱网环境下的深度优化实践分享(视频+PPT)[附件下载]

QQ空间移动端10亿级视频播放技术优化揭秘(视频+PPT)[附件下载]

RTC实时互联网2017年度大会精选演讲PPT [附件下载]

微信分享开源IM网络层组件库Mars的技术实现(视频+PPT)[附件下载]

微服务理念在微信海量用户后台架构中的实践(视频+PPT)[附件下载]

移动端IM开发和构建中的技术难点实践分享(视频+PPT)[附件下载]

网易云信的高品质即时通讯技术实践之路(视频+PPT)[附件下载]

腾讯音视频实验室:直面音视频质量评估之痛(视频+PPT)[附件下载]

腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT[附件下载]

微信朋友圈海量技术之道PPT[附件下载]

手机淘宝消息推送系统的架构与实践(音频+PPT)[附件下载]

如何进行实时音视频的质量评估与监控(视频+PPT)[附件下载]

Go语言构建高并发消息推送系统实践PPT(来自360公司)[附件下载]

网易IM云千万级并发消息处理能力的架构设计与实践PPT [附件下载]

手机QQ的海量用户移动化实践分享(视频+PPT)[附件下载]

钉钉——基于IM技术的新一代企业OA平台的技术挑战(视频+PPT)[附件下载]

微信技术总监谈架构:微信之道——大道至简(PPT讲稿)[附件下载]

Netty的架构剖析及应用案例介绍(视频+PPT)[附件下载]

声网架构师谈实时音视频云的实现难点(视频采访)

滴滴打车架构演变及应用实践(PPT讲稿)[附件下载]

微信海量用户背后的后台系统存储架构(视频+PPT)[附件下载]

在线音视频直播室服务端架构最佳实践(视频+PPT)[附件下载]

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

微信移动端应对弱网络情况的探索和实践PPT[附件下载]

Android版微信从300KB到30MB的技术演进(PPT讲稿)[附件下载]

从零开始搭建瓜子二手车IM系统(PPT)[附件下载]

极光分享:高并发海量消息推送系统架构演进(视频+PPT)[附件下载]

微信红包系统可用性设计实践(PPT) [附件下载]

微信红包数据架构演变(PPT) [附件下载]

百度网盘千万节点的P2P架构设计(PPT) [附件下载]

瓜子IM智能客服系统的数据架构设计(PPT) [附件下载]

基于C++构建微信客户端跨平台开发框架(PPT) [附件下载]

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

posted @ 2020-06-24 13:55 Jack Jiang 阅读(220) | 评论 (0)编辑 收藏

     摘要: 1、引言好久没写技术文章了,今天这篇不是原理性文章,而是为大家分享一下由笔者主导开发实施的IM即时通讯聊天系统,针对大量离线消息(包括消息漫游)导致的用户体验问题的升级改造全过程。文章中,我将从如下几个方面进行介绍:1)这款IM产品的主要业务及特点;2)IM系统业务现状和痛点;3)升级改造之路;4)消息ACK逻辑的优化。下述内容都是根据笔者开发IM的亲身经历总结下来的宝贵经验,干货满满,期待你的点...  阅读全文

posted @ 2020-06-17 13:47 Jack Jiang 阅读(214) | 评论 (0)编辑 收藏

1、内容点评

本文以轻松幽默的语气,讲解了视频编解码的一些基本常识,并以爱奇艺为例,讲述了视频编解码技术在国内的发展以及未来的一些展望。

▼ 阅读本文需要有一些音视频编解码技术的基础,否则请先阅读以下文章:

即时通讯音视频开发(一):视频编解码之理论概述

即时通讯音视频开发(二):视频编解码之数字视频介绍

即时通讯音视频开发(三):视频编解码之编码基础

即时通讯音视频开发(十九):零基础,史上最通俗视频编码技术入门

本文并未就具体的视频编解码概念进行深入的讨论,目的是尽可能以浅显易懂的方式让读者轻松了解本文标题想呈现的内容。如果您想深入了解视频编解码技术,可继续阅读以下文章。

▼ 以下是比较深入的视频编解码相关文章:

即时通讯音视频开发(四):视频编解码之预测技术介绍

即时通讯音视频开发(五):认识主流视频编码技术H.264

即时通讯音视频开发(十三):实时视频编码H.264的特点与优势

即时通讯音视频开发(十七):视频编码H.264、VP8的前世今生

即时通讯音视频开发(十八):详解音频编解码的原理、演进和应用选型

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

[观点] WebRTC应该选择H.264视频编码的四大理由

▼ 爱奇艺技术产品团队还分享了其它两篇文章,有兴趣也可以读一读:

爱奇艺移动端网络优化实践分享:网络请求成功率优化篇

爱奇艺技术分享:爱奇艺Android客户端启动速度优化实践总结

欢迎关注“即时通讯技术圈”,更多好文会同步发布在公众号:

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

2、正文引言

初夏最火的造型是什么?不少人可能会脱口而出——“淡黄的长裙,蓬松的头发。。。”

就连我这个上古时期的老年人,都开始每周四和周六准时点开爱奇艺首页,吸一口青春美少女们。原因无他,后疫情灰色时期,还有什么能比漂亮小姐姐的灿烂笑容更能让人感觉到人间值得呢?而我上一次真情实感追完的的女团选秀,可能要追溯到……《超级女声》。

 

不管自己pick的姐姐妹妹能不能顺利出道,至少今天在屏幕上欣赏她们的颜,绝对是一件超幸福的事儿。既不用忍受电视的“马赛克画质”,还能随时随地掏出手机来欣赏妹妹们今日份的可爱。

 

不知道大家有没有同一种快乐,那就是用4G网络看蓝光1080P,已经没有“流量焦虑”了,出现缓冲旋转“小菊花”的情况的几率也在悄然减少。这种观看体验的优化,除了通信网络环境的改变之外,缔造这种视觉快乐的一项关键技术——视频编码,就像是宇宙中的暗物质——鲜为人知,但十分重要。

简单来说:视频编码技术的升级,能够让你用更少的流量、更低的带宽、更快的速度,看更高清晰度的视频画面。比如《青春有你2》溢出屏幕的元气少女感,是不是比2005年的朦胧美更令人心动呢?

 

习惯了1080P高清的用户,绝对不愿意再回到480P的自动马赛克时代了。那么,视频编码到底在高清视频的烹制中,发挥了怎样神奇的化学反应?搞秀之余,不妨来了解一下视频编码的前世今生,看看无数科技巨头如何围绕它撕得花红柳绿。

3、曾今的视频编码标准,是IT巨头们“跑马圈地”的游戏

曾今的视频编码标准,巨头们争相“入股”,视频编码标准有何诱人之处?

思科、微软、苹果、谷歌、奈飞等这些大名鼎鼎的巨头,为什么都觉得视频编码技术这波“入股不亏”,非要pick助其出道?

回答这个问题之前,有必要先简单解释一下,视频编码技术究竟是干什么的?

简单来说:就是将视频压缩成一定的格式,去除掉其中的空间冗余和时间冗余,形成更适合存储和传输的码流。之所以需要被编码压缩,最主要原因就是原始视频的数据量过于庞大。高清视频文件往往高达1G以上,如果本地播放也就算了,一旦需要将其上传、分享给他人,传输网络和存储设备都扛不住那么巨大的数据量。

所以视频平台就需要对所播放的文件进行重构:

  • 1)通过压缩编码将数据量变小,以方便传输;
  • 2)再依靠解压缩在用户端解码,将视频图像还原出来。

简单总结就是:编码效率决定了你的手机能下载多少部高清视频。

 

如果你经历过一晚上不关机终于下好一部2G大小的视频,却发现播放器弹出一行大字——“该视频无法播放”的绝望,那一定会鼓掌欢迎编解码技术的更新。

 

当然,一些“有流量任性”的小伙伴也会选择直接用4G网络在线观看视频,这时候视频大小可就没什么影响了吧?

这么想可就太天真了。视频编码技术越强,传输需要占用的带宽也就更小,就像堤坝没有加固,但冲击河道的流水变小了,自然也就不会出现出水口淤塞的问题,看视频卡顿、掉帧的事故也就不会上演了。

比如此次疫情期间,网络流量比例不断增加,为互联网服务商带来极大的挑战,传统的解决方案就是在网络带宽有限的前提下,降低视频的清晰度。如,YouTube、亚马逊旗下Prime Video、Netflix等一众互联网视频提供商都在欧洲、印度、澳大利亚等国家降低了视频画质,用户只能默认收看标清视频。

可是,吃惯了高清这盘珍馐,哪个用户还愿意忍受低画质的粗茶淡饭呢?为了留住挑剔的内容食客们,平台们不得不想尽办法,提升对视频的烹饪技艺。

那么,让我们得以随时随地追剧追综的视频编解码技术,到底有哪些呢?

目前,国际上主要有几种主流的视频编解码标准(国际上音视频编码技术的标准化),包括VPx(VP8VP9),H.26x(H.264H.265),AVS(AVS1,AVS2),AVx(AV1)等等。视频平台们用某一种通用编码格式标准,自己开发编码器,就可以用更厉害的标准批量生产视频了。

可详读以下相关文章:

即时通讯音视频开发(五):认识主流视频编码技术H.264

即时通讯音视频开发(十三):实时视频编码H.264的特点与优势

即时通讯音视频开发(十七):视频编码H.264、VP8的前世今生

[观点] WebRTC应该选择H.264视频编码的四大理由

这些标准都是什么?到底哪个更厉害?为什么每个字符我都认识但完全不知道是干什么的?甚至还有种被张含韵张韶涵张涵予张予曦张馨予等支配的恐惧,傻傻分不清楚……别急,其实就算是流媒体从业者,也很少有人将它们搞清楚。其实吧,只需要了解三个关键点,你就能轻松变成“技术派”碾压不少业内人士了。

简单来说:不同的视频编码标准,就是围绕三个要素所展开的“量子纠缠”的。

4、视频编码标准要素之一:高清

上世纪90年代,第一代视频编码标准H.261和MPEG-1就开始出现,其后几乎每十年就有一次迭代更新。

启动视频编码技术不断演进的核心要素,还是人们对于高清、更高清的不断追求。

视频编码技术每进化一代,视频压缩效率都至少提高了一倍。比如十几年前第二代视频编码标准VP8 和 H.264,只能应用在低于HD的中小分辨率视频上,稍微兼顾一点1080P分辨率。而2012年爱立信公司推出了首款H.265编解码器,所引领的第三代视频编码HEVC标准就只需H.264一半带宽,即可播放相同质量的视频。

啥意思的?如果你是一个拥有过MP4设备的互联网早期弄潮儿,同样大的存储空间,你可以多下载一倍大小的视频,告别四处借硬盘的苦日子。

在线看视频则更爽了,基于编解码标准,智能手机、平板等移动设备也能够直接在线播放 1080P 的全高清视频,还支持4K 和 8K 超高清。也就是说,只要有内容方愿意生产8K视频,平台就能给你100%还原出画面来,而不用受最高清晰度720P这样的限制。

那么,为什么HEVC标准推出2年后,采用AV1格式的消费类设备又开始出现呢?因为移动互联网的爆发,原有的编码标准依然不能完全解决带宽消耗的问题。所以更高效的视频编码标准如AVS3、H.266等,也都相继被研发人员安排上了。

为什么视频平台关于编码标准的“墙头”这么多?

试想一下,如果你用的是一个高分辨率配置的智能手机,但视频只能到480P的清晰度,为硬件高配置花的钱不就白瞎了吗?有的用户为了防止观看卡顿或模糊,还得额外下一个完美解码、格式工厂之类的第三方解码器,将视频转化一下才能看。

而只要视频平台支持更高效率的编解码标准,就能实现低带宽下播放高清视频不卡顿的效果。有现炒的热菜,谁还愿意等打包的盒饭呢?所以细心的读者会发现,编码技术的不断升级,开始让第三方编码工具悄悄退出了追剧党的工具箱。

 

5、视频编码标准要素之二:专利

尽管用户体验是视频编码技术的首要进化原则,但专利所带来的限制与成本,也成为产业风云迭起的重要诱因。

由GE、Technicolor、杜比,飞利浦和三菱等组建的H.265专利联盟HEVC Advance,就向使用该标准的厂商收取专利费。

因此,不少开源标准逐渐崛起。其中谷歌打造的VP9标准就是最负盛名的一个。不仅在实际效率上与HEVC/H.265接近,大大优于H.264及它的前身VP8,而且可以对专利免费使用。很快,YouTube全面支持VP9超高清流媒体节目,Netflix、苹果等也加入其中。

当年,爱奇艺的《破冰行动》无疑是热度最高的"爆款剧"之一,一度引起风靡,高清流畅的画面质感为其加分增色不少,就采用了基于VP9标准开发的全新编码器,就采用了基于VP9标准开发的全新编码器面部细节等方面画面真实感尤为显著。

 

而我国自主知识产权的第二代信源编码标准AVS的出现,更与专利有着不解之缘。

大家的童年有没有出现过DVD这种物件,租一部剧不用等更新一个周末看完的快乐,不亚于今天购买视频平台尊贵的“VIP中P”会员。但中国的DVD行业曾经也遇到过一次严重的专利危机。

2002年,一批出口的DVD产品因为技术专利费的缴纳问题没有解决而被扣押。于是同年6月,数字音视频编解码技术标准工作组成立,2006年,第一代视频编码标准AVS1推出,压缩效率和H.264相当,并且每个编解码器只象征性得收取1元专利费,对互联网上的软件服务更是免收专利费,从此摆脱了只能使用国际标准、被高额专利费卡脖子的窘境。

可以说,目前主流的两大标准VP9和AVS,都是在专利的锁链中生长出来的自由之翼。

6、视频编码标准要素之三:垄断

既然VP9已经开源了,那就抱紧谷歌大腿等大佬迭代再应用不就好了吗?一个国家的大部分视频都坐落在某一个标准体系上,等于将标准的议价权交到了别人手中,面对这种“垄断优势”,谷歌表示,我疯起来可能连自己都打,为了不作恶还是赶紧给自己培养个对手吧……

所以2015年,一个由谷歌倡议并参与,试图替代VP9和HEVC/H.265的新标准组织成立了,那就是开放媒体联盟Alliance for Open Media(AOM)。这个新的开源标准很快吸引了Adobe、亚马逊、AMD、奈飞、Facebook、思科、苹果、英特尔、英伟达等等巨头的参与。中国的爱奇艺也率先加入了AOM联盟。

这个由30多家领先的高科技公司组成的会员制联盟,很快开发出了新一代开源的视频编码标准AV1(AOMedia Video Codec 1.0),也就是今天能让我们看到高清版《青春有你2》,特别是选秀舞台上的说唱、劲舞的画面更加清晰平滑的“后台”。

 

AV1之所以在产业端迅速上马,成为包括奈飞、YouTube、BBC、爱奇艺等一众平台的推行目标,主要就是在用户体验上太能打了。

更高的编码效率、更低的码率,同等质量可以节省20%以上的带宽。举个例子,就是下载整期1080P版《青春有你2》,原本需要10G的手机存储,而AV1标准下只需要8G就能搞定,剩下2G空间咱们存点PLMM(漂亮妹妹)的高清大图舔颜它不香吗?

在线观看也很爽,不仅妹妹们的脸看起来会更清晰,而且高清播放所占的带宽也更小,同时下载个东西、刷个微博啥的,也不会因为网络拥挤而卡顿。

作为视频观众,谁不愿意平台默默地为我们殚精竭虑,周全每一点流量、带宽和存储卡呢?

 

不难看出,视频编码标准迭代,既是技术天花板的层层上探,也是整个视频平台必须攻占的体验高地。

7、如今,国内的视频平台正在抢跑编码标准“赛道”

具体到国内视频平台上,关于编码标准目前竞争身位如何,未来还有哪些硬仗要打,都是值得我们重点关注的话题。我们不妨具体到某一个平台的探索经历之中,用历史观的视角来捋一捋,视频编码技术到底给中国这片土地的网民,带来了哪些体验上的蝶变。

比如:以爱奇艺为例,2016年爱奇艺在万能播放器上线了AVS2格式,是当时国内唯一支持这一标准的平台;也是国内第一个实现VP9标准、AV1标准并应用的视频厂商。可以说在编码标准领域,无论是技术领先度、布局完善度上,都能够从一定程度代表中国流媒体产业的关键抉择。

有了标准,是不是只需要拿来直接上手呢?答案显然是否定的。

拿爱奇艺来说,我们的标准探索之旅,又是如何的呢?

我们就以当前效率最高的AV1标准为例,其算法运算复杂度高,所需要的编码时间很长,这样把平台所有视频都处理一遍,可能会等来用户一句“奶奶你等的AV1格式上线了”!

所以,为了提高编码效率,让处理效果能够快速细致,又不影响编码质量,达到工业应用标准,标准编码器就要靠各个平台发挥自主能动性了。

以爱奇艺为例,对每一代开源技术都保持紧密跟进的同时,也会发挥自身的技术特长来进行针对性的迭代,让同一标准在爱奇艺平台上的应用有更优秀的表现。

比如VP9标准推出时,爱奇艺的技术团队就根据开源的版本VP9编码器进行了专门的算法优化,所开发的QVP9编码器的速率是开源版本的5.4倍左右。作为国内首先支持VP9的视频厂商,其画面质量在快速镜头、轮廓边缘、面部细节等方面真实感尤为显著,压缩效率比市面主流的标准更是提升了一倍。可能也是在不知不觉间,突然发现视频中那些高速打斗的场面似乎更加细腻流畅了,人物的皮肤也变得更加立体和容易辨别,连女主角额头的青春痘都是那么的昭然若揭……

 

而伴随着用户在移动场景下观看视频的诉求越来越高,比如我本人就喜欢在地铁上刷短视频,别问,问就是流量多有钱任性!这时候要保证流畅不卡顿,主打PC端的VP9可能就有点不够了,所以对移动端设备更友好的AV1,在推出后也很快被安排的明明白白。

独立研发的QAV1编码器,不仅比H265减小将近一半的带宽,节省40%以上码率。而且速度比开源编码器SVT-AV1还快出5倍左右。比如同样是看《青春有你2》,用QAV1展示的画面效果更棒、颜值更高,反而还更省带宽,直接帮助我节省了不少流量,让满额限速来的更晚一些。

 

8、展望未来,5G让视频编解码技术有了更多的想象空间

目前,首批应用 AV1 的电影已经在爱奇艺上线,用户可以在电脑浏览器端和安卓移动端观看。做到这一步,很难吗?

答案是肯定的。举个例子,终端硬件解码芯片的成熟,与某项标准能否发挥价值有直接关系。比如H.265在硬件支持上比较广泛,就与苹果、高通、英特尔等的芯片都支持H.265的硬件解码器有关。

所以编码器往往需要结合具体的应用场景来进行改进和深度优化。

以AV1在爱奇艺的应用为例,为了更好地适应爱奇艺海量内容,QAV1通过对场景复杂度的预分析,实现了更加合理的码率分配。对于简单场景,QAV1可以自适应地降低码率,在保证画质的情况下节省用户带宽;同时对于复杂场景会适当提高码率,给用户带来更高画质的体验。

 

目前,QAV1已经支持的功能包括多种速度档次、多种码率控制方式、8K视频编码等。这种与差异化环境相匹配的细节打磨,同时兼顾了网络带宽与用户体验。

万众期待的5G,自然也需要与之匹配的视频编码标准来呼应。以爱奇艺为例来说,AVS3应用已经在路上了,用移动智能手机看8K超高清视频、浏览VR新闻资讯、与虚拟偶像互动……这些新娱乐体验,或许都将借助视频编码的技术魔术,被呈现到我们眼前。

从爱奇艺的视频编码探索中,不难看到,技术的时代快车并不容易拿到船票的。唯有长期披荆斩棘,才能顺利摘得王冠。

附录:更多音视频技术方面的资料

[1] 实时音视频开发的精华资料:

即时通讯音视频开发(一):视频编解码之理论概述

即时通讯音视频开发(二):视频编解码之数字视频介绍

即时通讯音视频开发(三):视频编解码之编码基础

即时通讯音视频开发(四):视频编解码之预测技术介绍

即时通讯音视频开发(五):认识主流视频编码技术H.264

即时通讯音视频开发(六):如何开始音频编解码技术的学习

即时通讯音视频开发(七):音频基础及编码原理入门

即时通讯音视频开发(八):常见的实时语音通讯编码标准

即时通讯音视频开发(九):实时语音通讯的回音及回音消除概述

即时通讯音视频开发(十):实时语音通讯的回音消除技术详解

即时通讯音视频开发(十一):实时语音通讯丢包补偿技术详解

即时通讯音视频开发(十二):多人实时音视频聊天架构探讨

即时通讯音视频开发(十三):实时视频编码H.264的特点与优势

即时通讯音视频开发(十四):实时音视频数据传输协议介绍

即时通讯音视频开发(十五):聊聊P2P与实时音视频的应用情况

即时通讯音视频开发(十六):移动端实时音视频开发的几个建议

即时通讯音视频开发(十七):视频编码H.264、VP8的前世今生

即时通讯音视频开发(十八):详解音频编解码的原理、演进和应用选型

即时通讯音视频开发(十九):零基础,史上最通俗视频编码技术入门

实时语音聊天中的音频处理与编码压缩技术简述

网易视频云技术分享:音频处理与压缩技术快速入门

学习RFC3550:RTP/RTCP实时传输协议基础知识

基于RTMP数据传输协议的实时流媒体技术研究(论文全文)

声网架构师谈实时音视频云的实现难点(视频采访)

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

还在靠“喂喂喂”测试实时语音通话质量?本文教你科学的评测方法!

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

移动端实时视频直播技术实践:如何做到实时秒开、流畅不卡

如何用最简单的方法测试你的实时音视频方案

技术揭秘:支持百万级粉丝互动的Facebook实时视频直播

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

移动端实时音视频直播技术详解(一):开篇

移动端实时音视频直播技术详解(二):采集

移动端实时音视频直播技术详解(三):处理

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

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

移动端实时音视频直播技术详解(六):延迟优化

理论联系实际:实现一个简单地基于HTML5的实时视频直播

IM实时音视频聊天时的回声消除技术详解

浅谈实时音视频直播中直接影响用户体验的几项关键技术指标

如何优化传输机制来实现实时音视频的超低延迟?

首次披露:快手是如何做到百万观众同场看直播仍能秒开且不卡顿的?

Android直播入门实践:动手搭建一套简单的直播系统

网易云信实时视频直播在TCP数据传输层的一些优化思路

实时音视频聊天技术分享:面向不可靠网络的抗丢包编解码器

P2P技术如何将实时视频直播带宽降低75%?

专访微信视频技术负责人:微信实时视频聊天技术的演进

腾讯音视频实验室:使用AI黑科技实现超低码率的高清实时视频聊天

微信团队分享:微信每日亿次实时音视频聊天背后的技术解密

近期大热的实时直播答题系统的实现思路与技术难点分享

福利贴:最全实时音视频开发要用到的开源工程汇总

七牛云技术分享:使用QUIC协议实现实时视频直播0卡顿!

实时音视频聊天中超低延迟架构的思考与技术实践

理解实时音视频聊天中的延时问题一篇就够

实时视频直播客户端技术盘点:Native、HTML5、WebRTC、微信小程序

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

微信多媒体团队访谈:音视频开发的学习、微信的音视频技术和挑战等

腾讯技术分享:微信小程序音视频技术背后的故事

微信多媒体团队梁俊斌访谈:聊一聊我所了解的音视频技术

新浪微博技术分享:微博短视频服务的优化实践之路

实时音频的混音在视频直播应用中的技术原理和实践总结

以网游服务端的网络接入层设计为例,理解实时通信的技术挑战

腾讯技术分享:微信小程序音视频与WebRTC互通的技术思路和实践

新浪微博技术分享:微博实时直播答题的百万高并发架构实践

技术干货:实时视频直播首屏耗时400ms内的优化实践

爱奇艺技术分享:轻松诙谐,讲解视频编解码技术的过去、现在和将来

>> 更多同类文章 ……

[2] 开源实时音视频技术WebRTC的文章:

开源实时音视频技术WebRTC的现状

简述开源实时音视频技术WebRTC的优缺点

访谈WebRTC标准之父:WebRTC的过去、现在和未来

良心分享:WebRTC 零基础开发者教程(中文)[附件下载]

WebRTC实时音视频技术的整体架构介绍

新手入门:到底什么是WebRTC服务器,以及它是如何联接通话的?

WebRTC实时音视频技术基础:基本架构和协议栈

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

[观点] WebRTC应该选择H.264视频编码的四大理由

基于开源WebRTC开发实时音视频靠谱吗?第3方SDK有哪些?

开源实时音视频技术WebRTC中RTP/RTCP数据传输协议的应用

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

实时通信RTC技术栈之:视频编解码

开源实时音视频技术WebRTC在Windows下的简明编译教程

网页端实时音视频技术WebRTC:看起来很美,但离生产应用还有多少坑要填?

了不起的WebRTC:生态日趋完善,或将实时音视频技术白菜化

腾讯技术分享:微信小程序音视频与WebRTC互通的技术思路和实践

>> 更多同类文章 ……

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

posted @ 2020-06-10 11:54 Jack Jiang 阅读(236) | 评论 (0)编辑 收藏

本文中文译文由作者“ably.io”发布于公众号“高可用架构”,译文原题:《深入解读HTTP3的原理及应用》、英文原题:《HTTP/3 deep dive》(文末有译文和原文链接),即时通讯网收录时有少许改动,感谢原作者和译者的分享。

1、引言

HTTP3是HTTP协议的最新版本。从诞生之初,HTTP就是交换超文本文档的首选应用层协议。多年来,为了跟上互联网的发展,以及WWW上交换的内容种类增加,HTTP进行了几次重大升级,而HTTP/3就是目前的最新版本。

本文将从HTTP/3的基本概念、技术原理、应用场景和如何使用它等方面进行介绍,确保在有限的篇幅内,能让你通俗地理解它。


 

本文是系列文章中的第12篇,本系列文章的大纲如下:

网络编程懒人入门(一):快速理解网络通信协议(上篇)

网络编程懒人入门(二):快速理解网络通信协议(下篇)

网络编程懒人入门(三):快速理解TCP协议一篇就够

网络编程懒人入门(四):快速理解TCP和UDP的差异

网络编程懒人入门(五):快速理解为什么说UDP有时比TCP更有优势

网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门

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

网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接

网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

网络编程懒人入门(十):一泡尿的时间,快速读懂QUIC协议

网络编程懒人入门(十一):一文读懂什么是IPv6

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

学习交流:

- 即时通讯/推送技术开发交流5群:215477170 [推荐]

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

欢迎关注“即时通讯技术圈”,更多好文会同步发布在公众号:

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

2、相关文章

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

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

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

网络编程懒人入门(十):一泡尿的时间,快速读懂QUIC协议》(推荐)

技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解》(推荐)

3、HTTP协议的演进史

在万维网诞生之时,万维网仅仅是一群交换超文本文件的计算机。在计算机之间交换文件是一个简单的程序,包括请求和响应。在此基础上设计了一个简单的基于文本的协议。HTTP(超文本传输协议)应运而生。后来,它被起草成了一个标准化的IETF协议,定义在RFC 1945中,也被称为HTTP/1.0。

多年来,HTTP从HTTP/1.0发展到HTTP/1.1,再到HTTP/2。在每一次迭代中,协议都增加了新的功能,以处理大量的需求,如应用层需求、安全考虑、会话处理和媒体类型等。要深入了解HTTP/2及其演进史,可详读《从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路》。

尽管经历了几次修订,但HTTP的底层传输机制基本没有变化。但是,随着互联网流量的激增,在移动电话的推动下,HTTP的传输机制在保证网页浏览体验的流畅性方面变得问题重重。

HTTP/3是为了处理HTTP/2.0的传输相关问题而生的,可以在各种设备上更快地访问Web。它基于一个新的传输层协议,称为QUIC(Quick UDP Internet Protocol),在UDP之上工作。这一选择与之前版本的HTTP截然不同,之前版本都是基于TCP。TCP是一个比UDP更可靠的协议,那么为什么要在UDP之上重新设计HTTP的传输层呢?


 

让我们来看看在TCP上运行HTTP的局限性,并深入了解一下基于QUIC协议的HTTP/3的设计思想。

4、什么是HTTP/3

当IETF正式标准化HTTP/2时,Google正在独立构建一个新的传输协议,名为gQUIC。它后来成为新互联网草案,并被命名为QUIC。gQUIC最初的实验证明,在网络条件较差的情况下,gQUIC在增强网页浏览体验方面的效果非常好。因此,gQUIC的发展势头越来越好,IETF的大多数成员赞成建立一个在QUIC上运行的HTTP新规范。这个新的倡议被称为HTTP/3,以区别于当前的HTTP/2标准。


 

从语法和语义上看,HTTP/3与HTTP/2相似。HTTP/3遵循相同的请求和响应消息交换顺序,其数据格式包含方法、标题、状态码和body。然而,HTTP/3的显著的偏差在于协议层在UDP之上的堆叠顺序。


 

有关QUIC的更多资料,可以看看《网络编程懒人入门(十):一泡尿的时间,快速读懂QUIC协议》、《技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解》。

5、HTTP/3 是如何工作的?

HTTP/3功能的核心是围绕着底层的QUIC协议来实现的。在讨论QUIC和UDP之前,我们有必要先列出TCP的某些限制,这也是导致QUIC发展的原因。

5.1 TCP可能会间歇性地挂起数据传输

如果一个序列号较低的数据段还没有接收到,即使其他序列号较高的段已经接收到,TCP的接收机滑动窗口也不会继续处理。这将导致TCP流瞬间挂起,在更糟糕的情况下,即使所有的段中有一个没有收到,也会导致关闭连接。这个问题被称为TCP流的行头阻塞(HoL)。


 

5.2 TCP不支持流级复用

虽然TCP确实允许在应用层之间建立多个逻辑连接,但它不允许在一个TCP流中复用数据包。使用HTTP/2时,浏览器只能与服务器打开一个TCP连接,并使用同一个连接来请求多个对象,如CSS、JavaScript等文件。在接收这些对象的同时,TCP会将所有对象序列化在同一个流中。因此,它不知道TCP段的对象级分区。

5.3 TCP会产生冗余通信

TCP连接握手会有冗余的消息交换序列,即使是与已知主机建立的连接也是如此。


 

QUIC协议在以下设计选择的基础上,通过引入一些底层传输机制的改变,解决了这些问题。

1)选择UDP作为底层传输层协议:在TCP之上建立新的传输机制,将继承TCP的上述所有缺点。因此,UDP是一个明智的选择。此外,QUIC是在用户层构建的,所以不需要每次协议升级时进行内核修改。

2)流复用和流控:QUIC引入了连接上的多路流复用的概念。QUIC通过设计实现了单独的、针对每个流的流控,解决了整个连接的行头阻塞问题。


 

3)灵活的拥塞控制机制:TCP的拥塞控制机制是刚性的。该协议每次检测到拥塞时,都会将拥塞窗口大小减少一半。相比之下,QUIC的拥塞控制设计得更加灵活,可以更有效地利用可用的网络带宽,从而获得更好的吞吐量。

4)更好的错误处理能力:QUIC使用增强的丢失恢复机制和转发纠错功能,以更好地处理错误数据包。该功能对于那些只能通过缓慢的无线网络访问互联网的用户来说是一个福音,因为这些网络用户在传输过程中经常出现高错误率。

5)更快的握手:QUIC使用相同的TLS模块进行安全连接。然而,与TCP不同的是,QUIC的握手机制经过优化,避免了每次两个已知的对等者之间建立通信时的冗余协议交换。


 

通过在QUIC之上构建基于HTTP/3的应用层,您可以获得增强型传输机制的所有优势,同时保留HTTP/2的语法和语义。但是,你也必须注意到,HTTP/2不能直接与QUIC集成,因为从应用到传输的底层帧映射是不兼容的。因此,IETF的HTTP工作组建议将HTTP/3作为新的HTTP版本,并根据QUIC协议的帧格式要求修改了帧映射。

除此之外,HTTP/3还使用了一种新的HTTP头压缩机制,称为QPACK,是对HTTP/2中使用的HPACK的增强。在QPACK下,HTTP头可以在不同的QUIC流中不按顺序到达。与HTTP/2中的TCP确保数据包的按顺序传递不同,QUIC流是不按顺序传递的,在不同的流中可能包含不同的HTTP头。因此,QPACK使用查找表机制对报头进行编码和解码。

6、为什么HTTP/3很重要?

TCP已经有40多年的历史了。它在1981年通过RFC 793从而标准化。多年来,它经历了多次更新,是一个非常强大的传输协议,可以支持互联网流量的增长。然而,由于设计上的原因,TCP从来就不适合处理有损无线环境中的数据传输。在互联网的早期,有线网络将网络中的每一台计算机连接起来。

现在,随着智能手机和便携式设备的数量超过台式机和笔记本电脑的数量,超过50%的互联网流量已经通过无线传输。这种趋势给整体的网络浏览体验带来了问题,其中最重要的是在无线覆盖率不足的情况下,TCP中的行头阻塞(关于TCP在移动网络下的不足,请阅读《5G时代已经到来,TCP/IP老矣,尚能饭否?》)。

Google的一些初步实验证明,QUIC作为Google部分热门服务的底层传输协议,极大地提高了速度和用户体验。部署QUIC作为YouTube视频的底层传输协议,导致YouTube视频流的缓冲率下降了30%,这直接影响了用户的视频观看体验。在显示谷歌搜索结果时,也有类似的改善。

网络条件较差的情况下提升非常明显,这促使谷歌更加积极地完善该协议,并最终向IETF提出标准化。

由于这些早期的试验所带来的所有改进,QUIC已经成为带领万维网走向未来的重要因素。在QUIC的支持下,HTTP从HTTP/2到HTTP/3的改头换面,朝着这个方向合理地迈出了一步。


 

7、HTTP/3的最佳用例

HTTP/3将改善我们上网的体验,特别是在仍无法使用高速无线网络的地区。尽管HTTP/2已经解决了一部分问题,然而HTTP/3更进一步。

7.1 物联网(IoT)

HTTP可能不是物联网的首选协议,但在某些情况下,基于HTTP的通信非常适合特定的应用。HTTP/3可以解决从传感器收集数据的移动电话的无线连接损耗问题。这个问题同样适用于安装在车辆或可移动资产上的独立IoT设备。通过HTTP来访问这些设备,可以更加可靠。

7.2 大数据

全球各地的企业都在觉醒,意识到从多个部门收集数据的潜力,并将其整合成更大的信息共享API,供内部和外部受众共享。这些API也为数据的货币化铺平了道路,通过托管这些数据作为流API服务可以实现数据的货币化。随着时间的推移,这些服务会吐出海量的数据。通过HTTP/3托管的流API将使它们比HTTP/2更健壮、更有弹性。

7.3 Web VR

随着浏览器能力的提升,内容格局正在快速变化。其中一个领域就是基于网络的VR。虽然还处于起步阶段,但有很多的用例可以让VR在加强协作方面发挥关键作用。网络在促进VR互动方面占据了核心位置。VR应用需要更多的带宽来渲染虚拟场景中的复杂细节,因此迁移到HTTP/3会大有收获。

8、HTTP/3的局限性

过渡到HTTP/3不仅涉及到应用层的变化,还涉及到底层传输层的变化。因此,与它的前身HTTP/2相比,HTTP/3的采用更具挑战性,因为后者只需要改变应用层。传输层承受着网络中的大量中间层审查。这些中间层,如防火墙、代理、NAT设备等会进行大量的深度数据包检查,以满足其功能需求。因此,新的传输机制的引入对IT基础设施和运维团队来说有一些影响。

然而,HTTP/3被广泛采用的另一个问题是,它是基于QUIC的,在UDP上运行。大多数的Web流量,以及IETF定义的知名服务都是在TCP之上运行的。这也是为什么长时间运行HTTP/3的UDP会话会被防火墙的默认数据包过滤策略所影响的原因。

随着IETF正在进行的标准化工作,这些问题最终都会得到解决。此外,考虑到Google在早期QUIC实验所显示的积极结果,人们对HTTP/3的支持是压倒性的,这将最终迫使中间层厂商标准化。

针对受限的IoT设备,HTTP/3由于过于繁琐从而无法采用。许多IoT应用部署的设备的外形尺寸非常小。因此,它们的RAM和CPU功率都是有限的。为了使设备在电池功率、低比特率和有损连接等限制条件下高效运行,必须执行此要求。HTTP/3在现有的UDP之上,以QUIC的形式在传输层处理,增加了HTTP/3在整个协议栈中的占用空间。这使得HTTP/3较为笨重,不适合那些IoT设备。但这种情况很少出现,而且存在专门的协议,这就避免了直接在此类设备上支持HTTP的需要。此外,还有以物联网为核心的协议,如MQTT

9、开始使用HTTP/3

IETF的HTTP工作组正致力于在2020年后期发布HTTP/3。因此它还没有被NGINX和Apache等主流web服务器正式支持。不过,有几个lib可以用来实验这个新协议,也提供了非官方的补丁。

以下是支持HTTP/3和QUIC传输lib的列表。请注意,这些实现都是基于互联网标准草案某一个版本,而这个版本很可能会被更高的版本所取代,最终的标准会在RFC中发布。

1)Quiche :

Quiche提供了通过QUIC协议发送和接收数据包的底层编程接口。它还支持HTTP/3模块,通过其QUIC协议实现发送HTTP数据包。除此之外,它还为NGINX服务器提供了一个非官方的补丁,可以安装和托管一个能够运行HTTP/3的Web服务器。除此以外,还提供了额外的程序来支持Android和iOS移动应用上使用HTTP/3。

2)Aioquic

Aioquic是QUIC的python实现。它还内置HTTP/3的测试服务器和客户端库。Aioquic建立在asyncio模块之上,asyncio模块是Python的标准异步I/O框架。

3)Neqo

Neqo 是 Mozilla 使用 Rust 实现 QUIC 和 HTTP/3。

如果你想尝试QUIC,请查看这个由QUIC工作组维护的QUIC协议的开源实现链接:https://github.com/quicwg/base-drafts/wiki/Implementations

(本文英文原文链接:点此进入、中文译文链接:点此进入

附录:更多有关HTTP协议的文章

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

技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解

让互联网更快:新一代QUIC协议在腾讯的技术实践分享

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

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

脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)

Comet技术详解:基于HTTP长连接的Web端实时通信技术

WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)

WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)

快速理解高性能HTTP服务端的负载均衡技术原理

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

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

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

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

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

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

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

小白必读:闲话HTTP短连接中的Session和Token

IM开发基础知识补课:正确理解前置HTTP SSO单点登录接口的原理

基于APNs最新HTTP/2接口实现iOS的高性能消息推送(服务端篇)

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

美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

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

移动端网络优化之HTTP请求的DNS优化

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

posted @ 2020-06-03 23:18 Jack Jiang 阅读(298) | 评论 (0)编辑 收藏

     摘要: 1、引言网络优化对于移动端App产品的用户体验至关重要,也与公司的运营和营收息息相关。这里列举两个公开的数据:“《页面加载超过3秒,57%的用户会离开》”“《Amazon页面加载延长1秒,一年就会减少16亿美金营收》”网络性能对于用户体验的影响,将非常直接地反馈到业务的运营上。而且,移动网络固有的弱网问题、DNS问题、连接性能等等都无法跟传统的固定网...  阅读全文

posted @ 2020-05-29 12:06 Jack Jiang 阅读(225) | 评论 (0)编辑 收藏

     摘要: 1、引言网络优化对于移动端App产品的用户体验至关重要,也与公司的运营和营收息息相关。这里列举两个公开的数据:“《页面加载超过3秒,57%的用户会离开》”“《Amazon页面加载延长1秒,一年就会减少16亿美金营收》”网络性能对于用户体验的影响,将非常直接地反馈到业务的运营上。而且,移动网络固有的弱网问题、DNS问题、连接性能等等都无法跟传统的固定网...  阅读全文

posted @ 2020-05-29 12:05 Jack Jiang 阅读(147) | 评论 (0)编辑 收藏

1、引言

IM应用的初学者们,在补全了各种基础技术知识后(如果您仍不具备这些知识,建议马上阅读《新手入门一篇就够:从零开发移动端IM》),在动手编码实践时,很多时候纠结的并不是功能该如何实现,而是这个功能该实现成什么样(没有经验,我特玛能找谁问问?)。

比如,最常见的纠结有以下这些:

  • 1)离线聊天消息该保存多久?
  • 2)好友请求应该保存多久?
  • 3)短视频消息中的视频时长设为多大合适?
  • 4)图片、短视频、语音这些多媒体消息中,未读的文件数据保存多久?
  • 5)群管理的逻辑该怎么弄?参考微信?还是参考QQ?(关键是参考资料哪里有?)
  • 6)朋友圈限制最多发几张照片合适?
  • ... ...

嗯,这些问题,老板认为并不是问题,因为可以“参考微信”啊!

然而,微信又不会亲口说出来它的这些规则到底是多少?难不成要一个一个去试?那太扯了!

本文将根据微信官方目前已公开的资料,将它的一些常用功能参数和逻辑规则资料进行了汇总整理,希望能助力你的IM开发!(本文已发布于:http://www.52im.net/thread-3008-1-1.html

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

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

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:https://mp.weixin.qq.com/s/F-pVE9vN21h0Vm8LwnYplg

2、资料来源

本文中整理的所有内容均来自微信官方知识库,如果存在不全或不准确的情况,请在评论中回复,我会逐条核实并修订。

* 特别申明:本文内容仅供研究和学习使用,请勿用作其它用途。如有不妥之处,请指出,我会及时处理。

3、阅读对象

本文适合作为新老IM开发者的备查资料。本文不适合不懂技术的普通用户阅读,因为所有内容都尽量以技术人员的视解整理和表述。

移动端IM产品中,微信是标杆,也是事实的用户体验标准。所以,无论是被老板或产品经理怼,直接说“微信也这样”,能省去很多口水仗(经验啊)。这也是整理本文的初衷,以及价值所在。

4、相关资源

微信本地数据库破解版(含iOS、Android),仅供学习研究 [附件下载]》(* 推荐研究)

仿微信的IM聊天时间显示格式(含iOS/Android/Web实现)[图文+源码]

5、微信的好友关系规则汇总

5.1 好友验证请求有效期限

有效期限为 3 天。

* 补充规则:微信的好友验证请求只保存在手机本地,当卸载重装后,好友请求会消失且无法找回。

5.2 通讯录分组/好友排序

微信通讯录分组、好友排序,是根据微信通讯录朋友昵称的首字母(或首个汉字拼音首字母)由A-Z排序。

* 补充规则:如果好昵称是特殊符号、数字或Emoji表情(比如爱心、气球等),将会归到#类中。

 

5.3 好友验证规则

  • 1)当开启“加我为朋友时需要验证”后,需你同意接受请求后,才能成为好友;
  • 2)未开启“加我为朋友时需要验证”时,任何人都能添加你为好友(无需你确认)。

* 补充规则:如果不想被他人添加好友时搜索到,微信中可以设置关闭“微信号/手机号/QQ号”等搜索方式。

 

5.4 微信有4种添加好友方式

1)搜索加好友:

输入对方的微信号/QQ号/手机号搜索添加即可,但不支持搜索昵称。

* 补充规则:如果对方将关闭了“通过QQ/手机号/微信号搜索到我”,则没有办法通过此种方法添加好友。

2)雷达加朋友:

当被添加者物理距离很近时,一起按住手机,就可以添加对方为朋友。

3)扫二维码加朋友:

扫描对方的二维码名片,就可以添加对方为朋友。

4)手机联系人:

绑定手机联系人的微信帐号,可以查看到手机通讯录联系人已开通了微信的朋友,并直接添加对方为微信好友。

5.5 好友人数上限

微信最多可以添加 5000 个好友。

5.6 通讯录黑名单功能逻辑

将对方加入黑名单后,与对方的关系逻辑如下:

  • 1)在自己的会话列表不再显示与其聊天记录,解除黑名单后会重新出现在会话列表中;
  • 2)在对方的通讯录好友列表中仍然会显示;
  • 3)将不再接收到对方的消息;
  • 4)对方无法给你发消息,会提示“对方拒绝接收您的消息”,自己可以给对方正常发送消息;
  • 5)互相无法查看更新后的头像、个性签名;
  • 6)对方将无法查看你的微信个人相册和对照片进行评论;
  • 7)互相看不到朋友圈更新,拉黑之前在朋友圈分享的照片也不在对方朋友圈展示。

5.7 当被对方删除或“拉黑”后的聊天效果

当好友将你删除或加入黑名单后,你给他发消息时,微信将出现以下提示。

对方将我加入黑名单后,我发消息时的微信提示:

对方把我删除后,我发消息时的微信提示: 

6、微信的群聊规则汇总

6.1 微信群的功能定位

微信群相当于QQ中的讨论组,所以没有QQ里的群号码这种东西。

6.2 群主规则

群的创建者默认是群主。

* 补充规则:当创建者退出该群时,群成员列表中的第一位(也就是建群以来第2个加群的人)将自动成为新群主(好奇葩的规则!)。

另外:当原群创建者(即原群主)再次加群时,身份将会是普通群员。

6.3 群员邀请规则

群成员可以拉其他人加入群,群主不能取消普通群员的这个能力。

* 补充规则:群主可以设置邀请需确认,即需群主确认后才可以让被邀请的好友加到群内。

6.4 群名称规则

每个人(不只是群主)都可以修改群名称。

* 补充规则:当群超过 100 人时,只有群主可以修改群名称。

6.5 群公告规则

只有群主可编辑群公告。

* 补充规则:群公告字数限制为最大 2000 个字(即4000字节)。

6.6 群保存规则

微信群需要手动添加到通讯录才会永久保存,否则它只会保存在本地,一旦你卸载APP后,它就会消失。除非有群内成员发送消息,你才能再次看到,除次之外,你没有别的方法可以找回它。

6.7 群人数限制

微信群最大上限为 500 人。而且,100 人以上的微信群只有已通过实名验证的微信用户才能加入。

6.8 加群验证规则

  • 1)当群人数小于40人时,好友可以自由加入或被邀请加入;
  • 2)当群人数超过40人时,加群邀请需要对方同意;
  • 3)当群人数超过100人时,对方需要通过实名验证才能接受邀请(微信中可以通过绑定银行卡进行实名验证)。

6.9 解散或退出群规则

微信没有像QQ那样的“一键解散群”功能。

可以通过中列方法实现解散群或退出群的能力:

1)如果是群主(创建者或群成员列表第一位),可以将群成员全部删除;

2)如果是普通群员,可以退出群聊。

6.10 群二维码的有效期限

微信群的二维码有效期为 7 天(从二维码生成时开始计算),失效后的2维码扫描时将提示“该二维码已过期”。

6.11 微信群消息屏蔽规则

微信没有屏蔽群聊消息的功能,如果要达到这样的效果,你只能设置不提醒新消息或退出此群。

7、微信的朋友圈规则汇总

7.1 照片数和文字数限制

  • 1)朋友圈照片单次最多可添加 9 张照片,上传照片没有文件数量限制,也没有存储容量限制。
  • 2)最多可输入 1500 个汉字(即 3000 个字节)。

7.2 朋友圈新动态提醒规则

如果关闭了朋友圈更新提醒,当好友有发布新的朋友圈动态时,“发现”按钮上将不会再出现红点提示,否则将提示。

 

7.3 朋友圈查看权限规则

当你未作任何权限设置的情况下:

  • 1)你的所有朋友可以,查看到你在朋友圈发表的所有动态;
  • 2)陌生人可以查看你最近的10条动态。

发新朋友圈时,可以设置回避的人(即设置“谁可以/不可以看”):

  • 1)公开:所有朋友可见;
  • 2)私密:仅自己可见;
  • 3)部分可见:可在通讯录中选择哪些好友可见;
  • 4)不给谁看:可在通讯录中选择哪些好友不可见。
 

可以允许或禁止陌生人查看:

可以允许或禁止陌生人(可能来自扫码但未添加好友、附近的人、摇一摇、群聊时)看到10张最近发的照片。

可以设置朋友圈查看时间范围:

可选择允许好友查看朋友圈最近三天、最近半年或者全部的内容。

可以关闭朋友圈功能:

之前通过朋友圈发表的照片,可在个人相册里查看。但好友仍可以看到。

7.4 朋友圈的评论可见规则

  • 1)评论时,只会通知发布者;
  • 2)当评论时“@”某评论者,只会通知被回复者;
  • 3)评论者只能看到朋友的所有评论(当该条朋友圈的回复者不是朋友时,是看不到他的回复的)。

7.5 朋友圈隐私规则

1)陌生人查看十张照片:

当禁止“允许陌生人查看十张照片”时,陌生人将看不到你发布的任何朋友圈动态。微信默认是允许。

2)不看他(她)的朋友圈(即屏蔽好友的朋友圈):

在您的朋友圈中不会显示对方发送的朋友圈消息。

3)不让他(她)看我的朋友圈(即内容不更新给好友):

对方查看您的朋友圈显示是空白的,不会显示您发送过的任何朋友圈消息。

 

8、微信的聊天消息规则

8.1 聊天记录保存规则

  • 1)微信聊天记录保存在本地手机,一旦卸载微信,则聊天记录永久消失;
  • 2)微信不支持聊天记录漫游功能,一旦更新手机,新手机上无法看到之前手机上的聊天记录。

点评:这里有份完整的微信本地数据库样本,可以用来研究和学习:《微信本地数据库破解版(含iOS、Android),仅供学习研究 [附件下载]》。

8.2 离线消息保存规则

  • 1)微信服务器只保存 72 小时内的离线普通消息(从对方发消息时间开始算起),过期会被服务端清理;
  • 2)微信服务器只保存 72 小时内的多媒体数据(图片、短视频、大文件),即使你的手机已收到该条消息,只要未点击查看,即被视为未读,服务器会在此期限后清理掉多媒体数据。

8.3 “对方正在输入”的显示规则

给对方发送消息后,对方在 10 秒内回复才可以看到该提示。

 

8.4 聊天消息撤回时限

微信的规则是可以撤回2分钟内发送的消息。

8.5 消息已读回执规则

微信不支持已读回执功能。微信认为已读或未读状态属于个人隐私,不希望打破这种自由沟通的感觉。

8.6 语音消息规则

  • 1)最长可录制为 60 秒的语音消息;
  • 2)语音文件格式为:AMR;
  • 3)语音文件压缩比率:60秒语音文件约为45KB。

点评:如果你的IM中,语音文件大大超过微信的这个数据量,就表达存在较大优化空间,可以从采样率等方面进行设置。

8.7 短视频消息规则

  • 1)最长可录制为 10 秒的语音消息;
  • 2)语音文件格式为:MP4;
  • 3)语音文件压缩比率:10秒短视频约文件红为1.5MB至2.0MB。

点评:如果你的IM中,短视频文件大大超过微信的这个数据量,就表达存在较大优化空间,可以从采样率等方面进行设置。

8.8 文件消息规则

微信限制最大可以上传的文件大小为 25 MB。

8.9 聊天消息时间显示规则

  • 1)当天的消息,以每5分钟为一个跨度显示时间(即格式:HH:mm);
  • 2)超过1天、小于1周的消息,将显示“星期+收发消息的时间”;
  • 3)超过1周的消息,将显示手机收发时间的日期(即格式:yyyy-MM-dd)。

点评:这里有一份仿微信的聊天界面时间显示规则代码,可以下载用一用:《仿微信的IM聊天时间显示格式(含iOS/Android/Web实现)[图文+源码]》。

9、微信的其它规则

9.1 收藏功能规则

  • * 收藏的内容:可以收藏文字、语音、图片、视频、地理位置等。
  • * 保存的位置:收藏里面的内容是保存在服务器中的,只要你不主动删除,会一直存在。
  • * 单个文件大小限制:可以收藏的单个文件大小不能超过 25 M。
  • * 存储总容量限制:微信限制收藏数据的总容量为 2 GB,当总收藏容量超出2G后,超出容量的内容,将不能再上传。

9.2 “附近的人”功能规则

  • * 技术实现:当你查看附近的人功能时,微信将通过手机GPS获取你的位置信息,同时会被保留一段时间。
  • * 位置缓存:当你使用过“附近的人”时,服务器就会留下您的地理位置信息一段时间,周围的人可以再次搜到您。

9.3 “摇一摇”功能规则

当距离很近的两个同时“摇一摇”时,不一定能摇到对方。因为微信的“摇一摇”没有距离限制,而且是由服务器随机匹配。

10、电脑版微信的特殊规则

10.1 可以发送的消息类型

微信电脑端,可以发送文字、默认表情、符号表情、动画表情(兔斯基表情)、截图、图片消息,并能同步手机上已收藏的表情并发送。

10.2 可能接收的消息类型

可以接收文字、默认表情、emoji表情、动画表情、图片、文件、语音、视频、公众号消息、名片类型消息、小视频、地理位置消息、转账消息、合并转发的聊天记录消息。

10.3 可以接收但不能查看的的消息类型

红包消息、AA收款消息(收到此类消息会提示请在手机上查看)。

10.4 发送文件的大小限制

微信电脑端,上传文件大小最大为 100 MB,一次最多可以选择10个文件同时发送。

* 补充规则:如果发送的是视频,则文件大小不能超过 25 MB。

附录:微信团队分享技术资料汇总

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

微信团队分享:微信移动端的全文检索多音字问题解决方案

微信团队分享:iOS版微信的高性能通用key-value组件技术实践

微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?

微信团队原创分享:iOS版微信的内存监控系统技术实践

iOS后台唤醒实战:微信收款到账语音提醒技术总结

腾讯技术分享:社交网络图片的带宽压缩技术演进之路

微信团队分享:视频图像的超分辨率技术原理和应用场景

微信团队分享:微信每日亿次实时音视频聊天背后的技术解密

微信团队分享:微信Android版小视频编码填过的那些坑》 

微信手机端的本地数据全文检索优化之路》 

企业微信客户端中组织架构数据的同步更新方案优化实战

微信团队披露:微信界面卡死超级bug“15。。。。”的来龙去脉

月活8.89亿的超级IM微信是如何进行Android端兼容测试的

一篇文章get微信开源移动端数据库组件WCDB的一切!

微信客户端团队负责人技术访谈:如何着手客户端性能监控和优化

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

微信团队原创分享:Android版微信的臃肿之困与模块化实践之路

微信后台团队:微信后台异步消息队列的优化升级实践分享

微信团队原创分享:微信客户端SQLite数据库损坏修复实践》 

腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率》 

腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)》 

腾讯原创分享(三):如何大幅压缩移动网络下APP的流量消耗(上篇)》 

微信Mars:微信内部正在使用的网络层封装库,即将开源》 

如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源》 

开源libco库:单机千万连接、支撑微信8亿用户的后台框架基石 [源码下载]》 

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

微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)》 

微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)》 

Android版微信从300KB到30MB的技术演进(PPT讲稿) [附件下载]》 

微信团队原创分享:Android版微信从300KB到30MB的技术演进》 

微信技术总监谈架构:微信之道——大道至简(演讲全文)

微信技术总监谈架构:微信之道——大道至简(PPT讲稿) [附件下载]》 

如何解读《微信技术总监谈架构:微信之道——大道至简》

微信海量用户背后的后台系统存储架构(视频+PPT) [附件下载]

微信异步化改造实践:8亿月活、单机千万连接背后的后台解决方案》 

微信朋友圈海量技术之道PPT [附件下载]》 

微信对网络影响的技术试验及分析(论文全文)》 

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

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

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

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

微信团队原创分享:Android内存泄漏监控和优化技巧总结》 

全面总结iOS版微信升级iOS9遇到的各种“坑”》 

微信团队原创资源混淆工具:让你的APK立减1M》 

微信团队原创Android资源混淆工具:AndResGuard [有源码]》 

Android版微信安装包“减肥”实战记录》 

iOS版微信安装包“减肥”实战记录》 

移动端IM实践:iOS版微信界面卡顿监测方案》 

微信“红包照片”背后的技术难题》 

移动端IM实践:iOS版微信小视频功能技术方案实录》 

移动端IM实践:Android版微信如何大幅提升交互性能(一)

移动端IM实践:Android版微信如何大幅提升交互性能(二)

移动端IM实践:实现Android版微信的智能心跳机制》 

移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)

移动端IM实践:iOS版微信的多设备字体适配方案探讨》 

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

IPv6技术详解:基本概念、应用现状、技术实践(上篇)

IPv6技术详解:基本概念、应用现状、技术实践(下篇)

微信多媒体团队访谈:音视频开发的学习、微信的音视频技术和挑战等

腾讯技术分享:微信小程序音视频技术背后的故事

微信多媒体团队梁俊斌访谈:聊一聊我所了解的音视频技术

腾讯技术分享:微信小程序音视频与WebRTC互通的技术思路和实践

手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

微信技术分享:微信的海量IM聊天消息序列号生成实践(容灾方案篇)

微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅

社交软件红包技术解密(二):解密微信摇一摇红包从0到1的技术演进

社交软件红包技术解密(三):微信摇一摇红包雨背后的技术细节

社交软件红包技术解密(四):微信红包系统是如何应对高并发的

社交软件红包技术解密(五):微信红包系统是如何实现高可用性的

社交软件红包技术解密(六):微信红包系统的存储层架构演进实践

QQ设计团队分享:新版 QQ 8.0 语音消息改版背后的功能设计思路

微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结

IM“扫一扫”功能很好做?看看微信“扫一扫识物”的完整技术实现

微信团队分享:微信支付代码重构带来的移动端软件架构上的思考

IM开发宝典:史上最全,微信各种功能参数和逻辑规则资料汇总

>> 更多同类文章 ……

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

posted @ 2020-05-21 13:23 Jack Jiang 阅读(226) | 评论 (0)编辑 收藏

本文引用了公众号“鲜枣课堂”的《5G消息(RCS),到底是什么?》和公众号“InfoQ”的《5G消息来了,它会干掉微信还是变成另一个飞信?》两篇文章的部分内容,感谢原作者的分享。

1、引言

上个月3大运营商(移动、电信、联通)发布了《5G消息白皮书》(此白皮书PDF版 ▶ 点此附件下载),宣布将共同启动5G消息业务。

 

简单理解,5G消息相当于是原先短消息服务的全新升级。与以前的短消息相比,5G消息具有多媒体、能互动服务的能力,不仅有文字、图片,还能发视频、位置,甚至进行支付。

嗯,听起很熟悉——这不就是微信、支付宝们现在干的活吗?

没错!在移动互联网时代已经沦为微信这类IM巨头的管道工的运营商们,正在试图通过5G消息这个新工具抢回失去的话语权。

那么,5G消息到底是什么?是完全的创新技术还是旧式短信技术的新瓶装旧酒?它是否真的具有可以取代现时移动端主流IM产品的能力?请跟着本文,一起读懂5G消息的前世今生!

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

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

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注: 

▲ 本文在公众号上的链接是:https://mp.weixin.qq.com/s/BF3ja1Uui6Pn32z0zI0H2g

2、5G消息是全新技术?

No,并不是!

“5G消息”,其实和5G并没有什么关系。它既不是5G特有的功能,也不是5G时代新开发出来的业务。它的真实身份,是诞生已有 10 多年的 RCS 技术。

3大运营商之所以要把它名名为“5G消息”,很大原因应该还是想借5G这个热点,从营销推广的角度进行的考虑,与技术无关。

RCS,全称是“Rich Communication Suite”,中文翻译过来就是“富媒体通讯套件”。

什么是“富媒体(Rich Media)”?传统电话只有语音,传统短信只有文本。而“富媒体”,包括文本、语音、图片、视频、动画、表情、位置等多种媒体形式。我们天天在用的微信,就是一种富媒体通信工具。

 

RCS,也被称为融合通信。所谓“融合”,既可以理解为多种媒体形式融合,也可以理解为IP业务和传统电信网业务的融合。

大白话来说,RCS可以理解为它是升级了传统的短信产品,使“短信”丰富化。

3、RCS技术的发展历程

我们先了解一下RCS技术的发展历程。

3.1 传统PC端IM的兴起,让电信厂商们蠢蠢欲动

我们把时间拨回到20多年前。当时,PC互联网以惊人的速度发展壮大,给人类带来了前所未有的信息大爆炸。

尤其是ICQ、MSN、OICQ(即QQ)等即时通讯工具的出现,让人们见识到多媒体通讯的无限乐趣。

 

▲ 能认全这3个IM的,都是老网民

于是,人们想到,这么有趣的通讯方式,是不是可以移植到手机上?

3.2 IMS的出现

3G移动通信标准,就是在这样的背景下建立起来的(2000年5月)。从3G起,手机的重点发展方向变成了数据业务,以满足人们日益增长的多媒体通信需求。

3G向4G的发展过程中,负责牵头标准制定的3GPP组织,考虑到传统语音通话及短信业务也需要向多媒体演进。于是,在2002年的3GPP Release 5版本中正式提出了IMS。

搞通信的读者一定对IMS这个词非常熟悉。如果是非通信专业的读者,我可以告诉你另外一个和IMS密切相关的词,那就是这几年特别火的VoLTE(Voice over LTE)。

是的,VoLTE业务,就是基于IMS实现的。

IMS的全称,叫做IP多媒体子系统(IP Multimedia Subsystem)。它包括了一系列不同的通信设备网元。

IMS的网络结构和业务流程非常复杂。对于IMS的作用,我们可以这么理解——它帮助4G LTE这个纯数据网络,实现对语音通话和短信的支持,并对它们进行强化(升级为多媒体形式)。

 

▲ IMS就是4G LTE网络的一个“插件”。有了它,4G才能打电话和发短信

在IMS的基础上,才有了VoLTE和RCS。

 

3.3 RCS的出现

2007年,RCS由一小部分GSMA(全球移动通信系统协会)成员提出,目的是为了运营商之间的多媒体消息互通。

2008年2月,GSMA正式成立RCS项目,并将其命名为“home”。此后,GSMA发布了多个版本的RCS、RCS-e(enhance,增强型)规范。

 

▲ GSMA,可以理解为全球运营商协会,主要代表运营商利益

RCS发布之后,得到了全球众多运营商的拥护。尤其是2008年4G LTE标准发布之后,RCS成为运营商们建设4G的标配。

3.4 RCS在移动端IM的挤压下持续演进

同样是2008年前后,iPhone和安卓相继问世,移动通信进入智能机时代,移动互联网市场开始井喷。

2011年左右,以WhatsApp、LINE、Facebook Message为代表的OTT通讯工具出现并迅速崛起,大量蚕食了传统运营商的语音、短信收入。

 

于是,海外运营商更加仰仗RCS,希望借此与OTT软件进行竞争。当时Vodafone、Orange、SKT、Verizon、O2等海外知名运营商都推出了自己的RCS解决方案和品牌。

2016年,为了进一步推动RCS的产品开发及全球部署,GSMA推出了RCS Universal Profile(通用配置文件,简称UP,相当于是一个规范标准),并陆续更新了多个版本。目前最新的版本,就是2019年10月发布的Version 2.4。

 

▲ RCS和UP的版本演进

3.5 RCS在国内的发展

我们回过头来看看RCS在国内的发展。

中国的3G和4G建设启动普遍晚于欧美日韩。3G就不用说了,晚了8年。4G是晚了5年。2013年底,工信部才发放了LTE商用牌照。

作为LTE的积极建设者,中国移动在2014年LTE大规模建网的同时,就非常看重IMS、VoLTE、RCS的商业价值。

因为飞信的前车之鉴,中国移动已经充分意识到传统运营商正在出现管道化的趋势,利润空间将不断被挤压,急需和OTT抢占流量入口,寻找新的业务增长点。

 

2015年,就在国内LTE网络覆盖初具规模之后,中国移动大幅提前了国内各省IMS和VoLTE网络的建设进度,并积极推动广州研究院的RCS业务验证和测试。

其实国内的三大运营商也都没有闲着,在 2017 年 4 月就完成了 RCS 三方(3大运营商)互通测试规范编制。其中,中国移动较为积极,在 2017 年 12 月即商用 RCS,包含 Native、App、PC 以及 SDK 四种终端形态。2019 年中移终端公司要求,所有在终端公司入库销售的机型都要支持 RCS Native 功能。

随着5G的到来,情况又发生了不同。

为了给5G网络腾挪更多的频谱空间,运营商必须加速2/3G网络的退网。而依附在2/3G网络上的传统语音和短信业务,必须尽快迁移到LTE和IMS网络上。(国内LTE网络的成熟覆盖,IMS的建设完成,使得RCS的推出具备了很好的时机。)

与此同时,面对OTT业务的持续打压,运营商也希望通过RCS进行最后一搏。于是,就有了这次“5G消息”业务的联合发布。

之所以叫“5G消息”,主要是希望借助5G的品牌,体现RCS业务和传统消息业务之间的代差。

4、RCS到底能实现什么样的功能和体验?

接下来我们讲讲RCS到底能实现什么样的功能,以及用户体验,何以让3大运营商重燃对搞微信等IM巨头的信心。

4.1 运营商对RCS的功能定位

中国移动在2014年曾经基于RCS提出了「三新」目标。这里面的三新,指的是:新通话、新消息以及新联系,分别指代了手机上的电话,短信,通讯录这三大入口。

  1. “新通话”以VoLTE为核心,增强用户通话质量和体验;
  2. “新消息”无缝融合多种媒体和消息格式,无缝与传统短/彩信互通;
  3. “新联系”以真实手机号码为前提,构建全新的社交、公众信息服务入口。

其实,这已经很明确地给出了RCS的功能和定位。

从总体上来看,运营商对RCS的应用场景定位分为两种:

  • 一种是个人用户与个人用户之间的消息交互;
  • 一种是企业用户与个人用户之间的消息交互。
 

4.2 RCS在普通用户间的消息交互与微信等IM相比,优势并不明显

针对场景1(即个人用户与个人用户之间的消息交互),RCS支持点对点消息,支持群发、群聊,支持语音、图片、视频多媒体消息,还支持发送位置、名片等,甚至还支持消息云备份和阅后即焚。

RCS的个人用户聊天时可以支持以下消息类型(跟IM很像): 

这些功能和我们目前的微信都差不多,RCS并没有体现出什么优势。考虑到用户习惯等原因,RCS估计很难撬动微信的霸主地位,未来可能主要是处于一个辅助性的地位。

更受运营商及整个产业关注的,其实是场景2(即企业用户与个人用户之间的消息交互)。

4.3 RCS在企业与个人的消息交互场景下,有很大的想象空间

2017年,GSMA在UP2.0规范中引入MaaP,还发布了MaaP白皮书,明确提出了面向A2P(Application to Person)行业消息的“RCS商业富媒体消息(RCS Business Messaging)”,也就是我们所说的场景2。

 

▲ RCS商业富媒体消息

MaaP,就是Messaging as a Platform,消息即平台。

RCS商业富媒体消息,为企业和个人用户之间提供消息交互接口,在图片和视频等基础上增加了交互能力,方便企业向用户输出个性化服务。

例如机票酒店预订查询、物流查询、网购订单查询等一系列轻应用功能,都可以通过RCS商业富媒体消息实现。

 

RCS商业富媒体消息的价值在于,它为企业和用户提供了一条新通道。借助这条通道,企业可以触达用户。用户也可以触达服务。

从某种意义上来说,它很像小程序、微信公众号(服务号),甚至电话客服中心。

为了实现RCS商业富媒体消息,运营商在自身网络上架设了MaaP能力增强开放平台和Chatbot聊天机器人。平台面向企业开放API接口,以提供服务。

技术架构大概是这样的: 

4.4 RCS拥有普通IM所不具备的优势

运营商对于“5G消息”(即RCS技术)这么有信心,源码它的一些独特的优势。

4.4.1)RCS优势1:它需要单独安装APP

它不需要单独安装第三方APP,手机原生就可以支持。这大幅降低了用户使用门槛,也节约了推广成本。

 

▲ 每个人的手机,都少不了这三个图标

虽然目前大部分手机并不支持5G消息,但后续各大厂商对手机进行软件升级,支持RCS UP 2.4规范之后,都可以支持。即使你不是5G手机(但至少是4G手机),也可以支持。

4.4.2)RCS优势2:无需注册账号

RCS业务和手机号码直接关联,用户号码就是账号,无需注册。

这同样降低了用户使用业务的复杂度,不仅解决了身份认证问题,还打通了“平台孤岛”(无需在每个商户单独注册账号)。

 

▲ 手机号即账号,一号通用

4.4.3)RCS优势3:无需添加好友

RCS牢牢掌握住了用户通信录这个社交金钥匙,无需添加好友,即刻就能建立社交网络。

尽管RCS拥有以上优势,但真正决定它能否走向成功的,并不是这些优势,而是它的生态和商业模式。

RCS的产业链既包括运营商、设备商、终端厂商,也包括平台服务商、内容提供商等。

设备商和终端厂商还好说,关键是平台服务商和内容服务商。它们愿不愿意投入,平台和应用该如何开发,开发能不能获得回报,如何吸引商户,要不要收费,如何收费,商户愿不愿意买单,这些都是未知数。

如果生态不能做大做强,就无法孵化更多的5G消息应用场景,也就谈不上商业价值回报。

5、现在才统一起来做“5G消息”,是否有点迟了?

从 3G 时代开始,全球电信运营商就受到 OTT(“OverTheTop”的缩写,指通过互联网向用户提供各种应用服务)厂商的冲击,国内三大运营商也不例外,传统的话音和短信业务收入大幅下降,OTT 服务虽然能带来流量收入,但也难以掩盖其增量不增收的尴尬。

随着微信等移动端IM互联网应用的不断扩张,运营商虽手握数亿用户,期间也有过大大小小的尝试与挣扎,例如中国移动的飞信、中国联通的沃友以及中国电信的易信,但最终都被边缘化。对 RCS 也有不少投入和试点,却还是雷声大雨点小,掀不起水花。三大运营商依然沦为主要提供语音、短信、流量等基础通信服务的“管道工”。

 

似乎,过度的竞争是导致运营商们错失机遇的主因之一。

某运营商直言:“过去,移动披靡一切。但后来对内‘弄不死’电信和联通,对外干不过阿里腾讯,对上交代不了国资委的考核。”。三大运营商终于联手便是 5G 消息的最大意义。

与采用私有协议的 App“孤岛式”的现状相比,由于三家运营商基于同一的国际标准(GSMA RCS UP 2.4),5G 消息在互联互通上的优势更为明显。

对比过去传统的短信业务,5G 消息可快速迭代——相关技术标准在 3 年内已迭代 5 大版本,从 UP1.0(2016 年 Q4)到最新的 UP2.4(2020 年 Q4)。

6、RCS看起来很美,但并非无懈可击

RCS确实具体先天优势,但也并非无懈可击。

RCS 仍面临三大挑战:

  • 1)用户的服务体验不一致,也给终端互联互通带来挑战(它无法做到像微信这样的IM一样,每款手机上安装的都是同一个应用);
  • 2)消息业务将会不断创新演进,需要终端快速跟进和支持,传统的技术研究、标准制定,终端研发,运营商测试等运营商长周期的流程,难以适应 RCS 快速发展;
  • 3)行业客户对 RCS 业务仍不熟悉,开发门槛较高。

另一方面,要培养用户使用短信入口的服务也不是件易事。

5G 时代,是多终端连接的物联网时代,小程序也被视为物联网众多的入口之一,谁都不会想放过这个机遇。

但 5G 消息能否拿回被微信这种IM应用抢走的市场,又或者在新的物联网增量市场分得一杯羹,尚需时日见证。可以肯定的是,对于客户来说,尤其是行业客户,多了一个选择。一个不是腾讯系,不是阿里系,也不是头条系的选择。

7、虽有不确定性,但RCS未来可期

目前,国内运营商的5G消息业务还处于试点大区联调测试阶段。

2020年4月10日,中兴通讯助力中国移动在杭州成功打通了基于GSMA UP2.4标准的5G消息first call,标志着国内5G消息商用进入正式倒计时。

据业内消息,2020年6月份国内就可以推出5G消息的正式商用。国内手机的升级支持,估计需要3个月到1年的时间。

相信随着5G建设的深入,RCS很快会成为大家手机中的标配。

“5G消息”到底会发展成什么样,作为IM开发者和普通用户来说,商业终究不是普通人该考虑的。从功能和体验上来说,多一种选择也未偿不是件好事,我们期待它早日到来!

 

8、最新动态:中国移动已于2020年5月10日上线“5G消息”APP

“5G消息”App是中国移动基于国际RCS标准打造的一款通讯及服务软件,支持发送文本、图片、音视频、地理位置等丰富消息;还可与商户的聊天机器人进行交互,获取7*24小时的智能服务。已于5月10日上线到苹果App store。

 

不幸的是,“5G消息”App上线仅一天就被下架(下架时间为5月11日)。

中国移动回应下架事件时说:因当前一些终端尚未支持5G消息功能,中国移动开发了“5G消息”APP,可以让开发者完成Chatbot(智能聊天机器人)应用开发后,真实体验消息交互服务,吸引广大开发者积极参与5G消息的合作生态构建,并非面向客户商用发布的产品。

中国移动表示:由于前期三家运营商联合发布5G消息白皮书,引发较高舆论关注,为保护“5G消息”名称不被恶意抢占,中国移动近日在应用市场进行上线(指的就是上线“5G消息”App)。因存在一些技术问题,该APP目前临时下线,稍后会重新上线。

在过去数年里,运营商与苹果公司的沟通讨论一直在进行中。目前通过安装App体验的做法,可以帮助苹果公司和苹果手机用户体验和使用5G消息。

9、《“5G消息”白皮书》附件下载

(附件无法上传,请从此链接下载:http://www.52im.net/thread-3001-1-1.html

10、参考资料

[1] 5G消息白皮书

[2] 中国移动率先发布5G消息APP:支持iOS/Android

[3] “5G消息”来了,App小心了!

[4] 中国移动、中国电信、中国联通联合发布《5G消息白皮书》

[5] 5G消息(RCS),到底是什么?

[6] 5G消息来了,它会干掉微信还是变成另一个飞信?

附录:更多IM产品方面的文章

技术往事:微信估值已超5千亿,雷军曾有机会收编张小龙及其Foxmail

QQ和微信凶猛成长的背后:腾讯网络基础架构的这些年

闲话即时通讯:腾讯的成长史本质就是一部QQ成长史

腾讯开发微信花了多少钱?技术难度真这么大?难在哪?

技术往事:史上最全QQ图标变迁过程,追寻IM巨人的演进历史》 

开发往事:深度讲述2010到2015,微信一路风雨的背后》 

开发往事:记录微信3.0版背后的故事(距微信1.0发布9个月时)》 

微信七年回顾:历经多少质疑和差评,才配拥有今天的强大

前创始团队成员分享:盘点微信的前世今生——微信成功的必然和偶然

QQ的成功,远没有你想象的那么顺利和轻松

[技术脑洞] 如果把14亿中国人拉到一个微信群里技术上能实现吗?》 

QQ和微信止步不前,意味着即时通讯社交应用创业的第2春已来?

那些年微信开发过的鸡肋功能,及其带给我们的思考

为什么说即时通讯社交APP创业就是一个坑?

即时通讯创业必读:解密微信的产品定位、创新思维、设计法则等

老罗最新发布了“子弹短信”这款IM,主打熟人社交能否对标微信?

盘点和反思在微信的阴影下艰难求生的移动端IM应用

QQ现状深度剖析:你还认为QQ已经被微信打败了吗?

那些年微信开发过的鸡肋功能,及其带给我们的思考

渐行渐远的人人网:十年亲历者的互联网社交产品复盘和反思

中国互联网社交二十年:全民见证的互联网创业演义

读懂微信:从1.0到7.0版本,一个主流IM社交工具的进化史

王欣回应微信封禁,解释为何取名“马桶MT”

同为IM社交产品中的王者,QQ与微信到底有什么区别

还原真实的腾讯:从最不被看好,到即时通讯巨头的草根创业史

知识科普:IM聊天应用是如何将消息发送给对方的?(非技术篇)

QQ设计团队分享:新版 QQ 8.0 语音消息改版背后的功能设计思路

社交应用教父级人物的张小龙和马化腾的同与不同

技事往事:你知道IM聊天软件中的“对方正在输入…”功能的起源吗?

盘点移动互联网时代的社交产品进化史(上篇):谁主沉浮

盘点移动互联网时代的社交产品进化史(下篇):大浪淘沙

IM热门功能思考:为什么微信里没有消息“已读”功能?

IM热门功能思考:聊天中加入“对方正在输入…”真的好吗?

别做梦了,社交产品哪有那么容易成功

微信那么牛,为什么海外成功的却是抖音?

专访马化腾:首次开谈个人经历、管理心得、技术创新、微信的诞生等

一文读懂微信之父张小龙:失败天才、颠覆者、独裁者、人性操控师

新技术展望:5G消息能取代IM应用?一文读懂5G消息的前世今生!

>> 更多同类文章 ……

欢迎关注我的“即时通讯技术圈”公众号:

(本文同步更新于:http://www.52im.net/thread-3001-1-1.html

posted @ 2020-05-14 11:47 Jack Jiang 阅读(219) | 评论 (0)编辑 收藏

本文引用了后端技术指南针公众号“浅谈RPC那些事儿1”和即时通讯网的“即时通讯新手入门:快速理解RPC技术——基本概念、原理和用途”两篇文章的部分内容。

1、引言

经常有开发者在纠结怎么开发IM集群,虽然真正的使用人数,可能用个人电脑单机都能支撑。

你也许会说,明明不需要用到IM集群,干吗要自找麻烦?答曰:“老板说这个得有!”、“万一产品做成了,用户量达到百万、千万级呢?”,各种回答,反此种种。总之,IM集群就是得整一个(先甭管用不用的上...)。

当然,玩笑归玩笑,真正要做到可投入到生产级别的IM集群系统,难度还是相当大的。必竟IM这种长连接应用相比传统Http这种短连接应用太不标准。

我们以一个典型的IM聊天消息传输为例:

假设存在两个正在聊天的用户(用户A和用户B),当A连接的是IM集群中的IM实例1、B连接的是IM集群中的IM实例2,此时当用户A向用户B发送一条聊天消息时,这条消息应该如何传递呢?

我们梳理一下上面这个例子的消息流转过程:

  • 1)IM聊天消息首先会由用户A发往IM实例1;
  • 2)IM实例1会将此条消息转交给IM实例2;
  • 3)IM实例2会将此条消息最终投递给连接在本实例上的用户B。

如上述流程所示,这就是一个IM集群系统中典型的聊天消息投递过程。

那么,这其中涉及到一个关键步骤:即第2)步中如何实现“IM实例1会将此条消息转交给IM实例2”?

此时,RPC技术出场了!

 

▲ 上图是个典型的分布式IM架构,注意中间的“RPC通信”字样本图引用自《基于Go的马蜂窝旅游网分布式IM系统技术实践

本文将以通俗易懂的白话形式,帮你快速理解IM集群中的关键技术——RPC。

推荐阅读:另一篇RPC基础知识文章也值得一读《即时通讯新手入门:快速理解RPC技术——基本概念、原理和用途》。

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:

▲ 本文在公众号上的链接是:https://mp.weixin.qq.com/s/0RXTUWHXDmMddsPVWej2Qg

2、相关文章

▼ 以下两篇文章有助于您对RPC和IM集群有个初步的概念:

即时通讯新手入门:快速理解RPC技术——基本概念、原理和用途》(推荐)

即时通讯新手入门:一文读懂什么是Nginx?它能否实现IM的负载均衡?

▼ IM开发干货系列文章(本文是其第24篇):

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

IM消息送达保证机制实现(二):保证离线消息的可靠投递

如何保证IM实时消息的“时序性”与“一致性”?

IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?

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

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

移动端IM登录时拉取数据如何作到省流量?

通俗易懂:基于集群的移动端IM接入层负载均衡方案分享

浅谈移动端IM的多点登陆和消息漫游原理

IM开发基础知识补课(一):正确理解前置HTTP SSO单点登陆接口的原理

IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?

IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议

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

IM群聊消息的已读回执功能该怎么实现?

IM群聊消息究竟是存1份(即扩散读)还是存多份(即扩散写)?

IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

一个低成本确保IM消息时序的方法探讨

IM开发基础知识补课(六):数据库用NoSQL还是SQL?读这篇就够了!

IM里“附近的人”功能实现原理是什么?如何高效率地实现它?

IM开发基础知识补课(七):主流移动端账号登录方式的原理及设计思路

IM开发基础知识补课(八):史上最通俗,彻底搞懂字符乱码问题的本质

IM的扫码登功能如何实现?一文搞懂主流应用的扫码登陆技术原理

IM要做手机扫码登陆?先看看微信的扫码登录功能技术原理

IM开发基础知识补课(九):想开发IM集群?先搞懂什么是RPC!》(本文)

如果您是IM开发初学者,强烈建议首先阅读《新手入门一篇就够:从零开发移动端IM》。

3、正文概述

限于篇幅原因,本文不会深入展开RPC的底层技术原理,会尽量用通俗白话的方式对概念性的东西进行讲解。

通过本文你将主要了解到以下内容:

  • 1)什么是RPC;
  • 2)为什么需要RPC;
  • 3)RPC的重要组件;
  • 4)常见RPC框架和各自特点。

4、什么是RPC?

RPC 是1984年代由 Andrew D. Birrell & Bruce Jay Nelson 提出的(见二位大佬的论文《Implementing Remote Procedure Calls),所以它并不是最近才有的技术概念。

关于RPC的介绍,正经的资料上大概是这样介绍的:

RPC(Remote Procedure Call)远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。

大白话理解RPC就是:RPC让你用别人家的东西就像自己家的一样。

看得我似懂非懂,于是我不得不问几个问题:

  • 1)为啥要用别人家的东西——请求其他服务);
  • 2)我怎么可以借到别人家的东西——其他服务调用;
  • 3)要是借用的话哪种形式更好——确定一个合适的调用方法);
  • 4)怎么让我用别人东西像自己的一样——屏蔽底层细节透明通信)。

在解答这些问题之前,我们必须达到一个共识问题:RPC只是一种通信模式,和http并不冲突对立,相反http可以作为RPC传输数据的一种协议,把RPC当作一种模式和思想,我们才能更好地理解它。

更严谨的RPC基础知识介绍,请阅读:《即时通讯新手入门:快速理解RPC技术——基本概念、原理和用途》。

5、为什么需要RPC?

以大家最熟悉的电商系统为例,这样规模的分布式系统,需要拆分出用户服务、商品服务、优惠券服务、支付服务、订单服务、物流服务、售后服务等等。这些服务之间都相互调用,这时内部调用最好使用 RPC ,同时每个服务都可以独立部署,独立上线。 

也就说当我们的项目太大,需要解耦服务,扩展性强、部署灵活,这时就要用到 RPC ,这主要是解决了分布式系统中,服务与服务之间的调用问题。

 

▲ 上图中的分布系统内部,就是用RPC实现的本图引用自《从新手到架构师,一篇就够:从100到1000万高并发的架构演进之路

对于IM集群这样的分布式系统来说,不同IM实例间的用户聊天消息,就是通过RPC进行流转的。

6、为什么不直接使用HTTP,而要搞RPC?

在日常业务中我们可以把功能封装成静态库、动态库、sdk、独立服务等,最常见也最方便的还是HTTP这种形式的调用。

HTTP服务把需要提供的服务暴露成接口(也就是通常所说的http rest接口啦),使用方直接按约定的HTTP方法和URI进行数据交互。

我们都知道HTTP协议是应用层协议,是个非常标准的协议,在HTTP协议之下还有网络层、传输层、数据链路层等,一个数据包packet除了净荷payload之外还有很多header,由于标准和通用性的设计目标也使得HTTP一次数据交互真正传输的payload只是其中一部分。

 

HTTP是我们用的最多最熟悉的交互模式,在系统内部各个服务之间接口较少,交互不多的情况下工作得还不错。

但如果在内部系统调用很复杂的前提下,HTTP调用的效率和安全性就不那么理想了。

 

以IM系统为例,单个IM实例的吞吐效率至少可以达到几万甚至数十万QPS,使用HTTP这种短连接(调用时建立socket连接,完成后释放连接)方式显的相当低效(每次调用都要重新经历TCP的3次握手、4次挥手过程),在分布式的情况下势必拉低整个IM集群的吞吐效率。而对于RPC,这种socket长连接方式对于高性能场景来说,效果是显而易见的。

更重要的是面对众多的服务我们需要的不仅仅是一个通信方式,而是一个内部服务的管理系统,这也就是我们今天说的RPC框架。注意:RPC是一种模式策略和框架,并不是单纯的通信协议。

题外话:实际上,HTTP在RPC系统中,并不是个你死我活的关系,必竟HTTP只是个通信协议,而HTTP有某些性能要求不敏感的场景来说,是完全可以作为RPC的具体实现协议之一来使用的。

7、RPC的调用过程是什么样的?

 

▲ 典型的RPC调用过程

如上图所示,一个典型的RPC调用过程是这样(过程序号对应上图中的数字):

  • 1)客户端(client)以本地调用方式调用服务;
  • 2)客户端存根(client stub)接收到调用后,负责将方法、参数等组装成能够进行网络传输的消息体(将消息体对象序列化为二进制);
  • 3)客户端通过 sockets 将消息发送到服务端;
  • 4)服务端存根(server stub)收到消息后进行解码(将消息对象反序列化);
  • 5)服务端存根(server stub)根据解码结果调用本地的服务;
  • 6)本地服务执行并将结果返回给服务端存根(server stub);
  • 7)服务端存根(server stub)将返回结果打包成消息(将结果消息对象序列化);
  • 8)服务端(server)通过 sockets 将消息发送到客户端;
  • 9)客户端存根(client stub)接收到结果消息,并进行解码(将结果消息发序列化);
  • 10)客户端(client)得到最终结果。

RPC的作用,其实就是要把上述2、3、4、7、8、9 这些步骤都封装起来。是不是很神奇?

8、关于HTTP和RPC的一些争议

HTTP和RPC是两个很容易混淆的概念,对于刚开始接触RPC的人来说,通常都会困惑:有HTTP了为什么还要用RPC?

在知乎上看到了这个很有趣的问题:《既然有http请求,为什么还要用rpc?

其中一个大佬的回答感觉很有意思: 

换个角度来说:HTTP 与 RPC 的关系就好比普通话与方言的关系。要进行跨企业服务调用时,往往都是通过 HTTP API,也就是普通话,虽然效率不高,但是通用,没有太多沟通的学习成本。但是在企业内部还是 RPC 更加高效,同一个企业公用一套方言进行高效率的交流,要比通用的 HTTP 协议来交流更加节省资源。整个中国有非常多的方言,正如有很多的企业内部服务各有自己的一套交互协议一样。虽然国家一直在提倡使用普通话交流,但是这么多年过去了,你回一趟家乡探个亲什么的就会发现身边的人还是流行说方言。

如果再深入一点说,普通话本质上也是一种方言,只不过它是官方的方言,使用最为广泛的方言,相比而言其它方言都是小语种,小语种之中也会有几个使用比较广泛比较特色的方言占比也会比较大。这就好比开源 RPC 协议中 Protobuf 和 Thrift 一样,它们两应该是 RPC 协议中使用最为广泛的两个。

总之:RPC是一种编程模式和概念,并不是非常具体的一种技术,实际上和HTTP没有明确的冲突,HTTP可以作为RPC传输协议,原因还是RPCpid际上是一种内部服务框架而不是一个具体的通信协议,它可以涉及服务注册、服务治理、服务发现、熔断机制、负载均衡等。

9、典型的RPC框架

一个典型RPC框架中,包含了服务发现、负载、容错、网络传输、序列化等组件,其中“RPC 协议”就指明了程序如何进行网络传输和序列化。

 

▲ 一个典型的 RPC 架构原理图本图引用自《即时通讯新手入门:快速理解RPC技术——基本概念、原理和用途

 

▲ 著名RPC框架Dubbo的架构图本图引用自《即时通讯新手入门:快速理解RPC技术——基本概念、原理和用途

一个 RPC 最重要的功能模块,就是上图中的”RPC 协议”部分: 

其中的序列化和反序列化的意思是:

  • 1)序列化:将数据结构或对象转换成二进制串的过程;
  • 2)反序列化:将序列化中所生成的二进制串转换成数据结构或者对象的过程。

在网络消息传输中可以基于TCP、UDP、http来实现,各自都有各自的特点。

基于 TCP 实现的 RPC 调用,能够灵活对协议字段进行定制,减少网络开销提高性能,实现更大的吞吐量和并发数,但要关注底层细节,在进行数据解析时更加复杂一些(比如最受欢迎的Protobuf的使用)。

基于 HTTP 实现的 RPC 可以使用 JSON 和 XML 格式的请求或响应数据,解析工具很成熟,在其上进行二次开发会非常便捷和简单。但是 HTTP 是上层协议,所占用的字节数会比使用 TCP 协议传输所占用的字节数更高。

对于其他部分,本文不再展开。

10、市面上常见的RPC框架及其特点

常见 RPC 技术和框架有:

  • 1)应用级的服务框架:阿里的 Dubbo/Dubbox、Google gRPC、Spring Boot/Spring Cloud。
  • 2)远程通信协议:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)。
  • 3)通信框架:MINA 和 Netty。

目前流行的开源 RPC 框架还是比较多的,有阿里巴巴的 Dubbo、Facebook 的 Thrift、Google 的 gRPC、Twitter 的 Finagle 等。

下面重点介绍当前最流行的三种RPC框架主要特点:

  • 1)gRPC:是 Google 公布的开源软件,基于最新的 HTTP 2.0 协议,并支持常见的众多编程语言。RPC 框架是基于 HTTP 协议实现的,底层使用到了 Netty 框架的支持;
  • 2)Thrift:是 Facebook 的开源 RPC 框架,主要是一个跨语言的服务开发框架。用户只要在其之上进行二次开发就行,应用对于底层的 RPC 通讯等都是透明的。不过这个对于用户来说需要学习特定领域语言这个特性,还是有一定成本的;
  • 3)Dubbo:是阿里集团开源的一个极为出名的 RPC 框架,在很多互联网公司和企业应用中广泛使用。协议和序列化框架都可以插拔是极其鲜明的特色。

11、本文小结

小结一下,简单地理解RPC就是:

RPC 就是从一台机器(客户端)上通过参数传递的方式调用另一台机器(服务器)上的一个函数或方法(可以统称为服务)并得到返回的结果。

RPC 会隐藏底层的通讯细节(不需要直接处理Socket通讯或Http通讯)。

RPC 是一个请求响应模型。客户端发起请求,服务器返回响应(类似于Http的工作方式)。

RPC 在使用形式上像调用本地函数(或方法)一样去调用远程的函数(或方法)。

12、参考资料

[1] 什么是 RPC 框架

[2] 谁能用通俗的语言解释一下什么是 RPC 框架?

[3] 浅谈RPC那些事儿[1]

[4] 即时通讯新手入门:快速理解RPC技术——基本概念、原理和用途

[5] 即时通讯新手入门:一文读懂什么是Nginx?它能否实现IM的负载均衡?

附录:有关IM架构设计的文章

浅谈IM系统的架构设计

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

一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

一套原创分布式即时通讯(IM)系统理论架构方案

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

蘑菇街即时通讯/IM服务器开发之架构选择

腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT

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

微信技术总监谈架构:微信之道——大道至简(演讲全文)

如何解读《微信技术总监谈架构:微信之道——大道至简》

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

17年的实践:腾讯海量产品的技术方法论

移动端IM中大规模群消息的推送如何保证效率、实时性?

现代IM系统中聊天消息的同步和存储方案探讨

IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?

IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议

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

WhatsApp技术实践分享:32人工程团队创造的技术神话

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

王者荣耀2亿用户量的背后:产品定位、技术架构、网络方案等

IM系统的MQ消息中间件选型:Kafka还是RabbitMQ?

腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面

以微博类应用场景为例,总结海量社交系统的架构设计步骤

快速理解高性能HTTP服务端的负载均衡技术原理

子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技术实践

知乎技术分享:从单机到2000万QPS并发的Redis高性能缓存实践之路

IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

微信技术分享:微信的海量IM聊天消息序列号生成实践(容灾方案篇)

新手入门:零基础理解大型分布式架构的演进历史、技术原理、最佳实践

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

阿里技术分享:深度揭秘阿里数据库技术方案的10年变迁史

阿里技术分享:阿里自研金融级数据库OceanBase的艰辛成长之路

社交软件红包技术解密(一):全面解密QQ红包技术方案——架构、技术实现等

社交软件红包技术解密(二):解密微信摇一摇红包从0到1的技术演进

社交软件红包技术解密(三):微信摇一摇红包雨背后的技术细节

社交软件红包技术解密(四):微信红包系统是如何应对高并发的

社交软件红包技术解密(五):微信红包系统是如何实现高可用性的

社交软件红包技术解密(六):微信红包系统的存储层架构演进实践

社交软件红包技术解密(七):支付宝红包的海量高并发技术实践

社交软件红包技术解密(八):全面解密微博红包技术方案

社交软件红包技术解密(九):谈谈手Q红包的功能逻辑、容灾、运维、架构等

社交软件红包技术解密(十):手Q客户端针对2020年春节红包的技术实践

即时通讯新手入门:一文读懂什么是Nginx?它能否实现IM的负载均衡?

即时通讯新手入门:快速理解RPC技术——基本概念、原理和用途

多维度对比5款主流分布式MQ消息队列,妈妈再也不担心我的技术选型了

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

从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结

IM开发基础知识补课(六):数据库用NoSQL还是SQL?读这篇就够了!

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

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

从游击队到正规军(三):基于Go的马蜂窝旅游网分布式IM系统技术实践

微信后台基于时间序的新一代海量数据存储架构的设计实践

IM开发基础知识补课(九):想开发IM集群?先搞懂什么是RPC!

>> 更多同类文章 ……

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注:


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

posted @ 2020-05-09 11:54 Jack Jiang 阅读(208) | 评论 (0)编辑 收藏

     摘要: 本文为开源工程:“github.com/GuoZhaoran/fastIM”的配套文章,原作者:“绘你一世倾城”,现为:猎豹移动php开发工程师,感谢原作者的技术分享。0、引言阅读提示:本文适合有一定网络通信技术基础的IM新手阅读。如果你对网络编程,以及IM的一些理论知识知之甚少,请务必首先阅读:《新手入门一篇就够:从零开发移动端IM》,按需补充相关...  阅读全文

posted @ 2020-04-28 12:05 Jack Jiang 阅读(277) | 评论 (0)编辑 收藏

阿里巴巴技术团队于2020年04月22日发布《Java开发手册v1.6.0-泰山版》。

1、概述

2017年开春之际,阿里诚意献上重磅大礼:《阿里巴巴Java开发手册(规约)》,首次公开阿里官方Java代码规范标准。这套Java统一规范标准将有助于提高行业编码规范化水平,帮助行业人员提高开发质量和效率、大大降低代码维护成本。

《阿里巴巴Java开发手册(规约)》是阿里内部Java工程师所遵循的开发规范,涵盖编程规约、单元测试规约、异常日志规约、MySQL规约、工程规约、安全规约等,这是近万名阿里Java技术精英的经验总结,并经历了多次大规模一线实战检验及完善。这是阿里回馈给Java社区的一份礼物,希望能够帮助企业开发团队在Java开发上更高效、容错、有协作性,提高代码质量,降低项目维护成本。

另外,《作者谈《阿里巴巴Java开发手册(规约)》背后的故事》一文,可以看看作者怎么说。

下载方式:详见文末 “6、历史版及最新版下载地址” !

2、价值意义

《阿里巴巴Java开发手册(规约)》的愿景是码出高效,码出质量。它结合作者的开发经验和架构历程,提炼阿里巴巴集团技术团队的集体编程经验和软件设计智慧,浓缩成为立体的编程规范和最佳实践。众所周知,现代软件行业的高速发展对开发者的综合素质要求越来越高,因为不仅是编程相关的知识点,其他维度的知识点也会影响软件的最终交付质量,比如,数据库的表结构和索引设计缺陷可能带来软件的架构缺陷或性能风险;单元测试的失位导致集成测试困难;没有鉴权的漏洞代码易被黑客攻击等。所以,本手册以开发者为中心视角,划分为编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约七个维度,每个条目下有相应的扩展解释和说明,正例和反例,全面、立体、形象地帮助到开发者的成长和团队代码规约文化的形成。

从严格意义上讲,《阿里巴巴Java开发手册(规约)》超越了Java语言本身,明确作为一名合格开发者应该具备的基本素质,因此本手册适合计算机相关行业的管理者和研发人员、高等院校的计算机专业师生、求职者等阅读,希望成为大家如良师益友般的工作手册、工具字典。

3、最新动态

关于泰山版(v1.6.0):

此版发布于2020年04月22日,此版升级内容包括:

1)发布错误码统一解决方案,详细参考手册的“附表 3”。

2)新增 34 条新规约。如:日期时间的闰年、闰月问题,三目运算的自动拆箱,SQL查询的表别名限定,Collectors 类的 toMap()方法使用注意等。

3)修改描述 90 处。如:阻塞等待锁、建表的小数类型等。

4)完善若干处示例。如:ISNULL 的示例等

4、主要作者

杨冠宝: 

杨冠宝:花名孤尽,取自《笑傲江湖》中风清扬的“独孤九剑,破尽天下武功”之意,是《阿里巴巴Java开发手册》的主要作者。在阿里巴巴集团历任研发、架构师、技术主管等不同的角色,承担过双11、国际化、代码中心等大型项目,有着丰富的一线编程经验,目前是研发协同平台Aone代码中心负责人。乐于分享与总结,在阿里巴巴集团内部大型分享多达30余次,不懈地追求技术创新,勇于挑战技术难度,在大数据、高并发、研发效能领域均有较深的造诣。

2016年3月,孤尽带领约码项目组编写《阿里巴巴Java开发手册(规约)》,码出高效,码出质量,推动阿里系与业界一起进步,让代码变得更舒服,更清澈,更好维护。

5、部分内容截图预览

 
 
 

6、历史版及最新版下载地址

请从此下载:阿里技术结晶:阿里巴巴Java开发手册-v1.6.0-泰山版》[附件下载]

posted @ 2020-04-23 11:44 Jack Jiang 阅读(900) | 评论 (0)编辑 收藏

本文原始内容由爱奇艺技术产品团队原创分享,本次有修订和改动。

1、引言

由于移动网络的复杂性特点,编写高质量、体验好的具备网络通信能力的移动端应用(尤其是即时通讯这类网络质量高度敏感的应用)有很大的挑战性。

我们平时看到的移动网络主要有如下三个典型特点:

1)移动状态网络信号不稳定,高时延、易抖动丢包、通道狭窄;

2)移动状态网络接入类型和接入点变化频繁;

3)移动状态用户使用高频化、碎片化、非WIFI流量敏感。

(▲ 上述文字,引用自《移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”》)

正是由于上述特点,移动端应用在进行网络数据通信时会面临各种复杂多变的问题。

无论后面的技术有多复杂,但对于普通用户使用APP来说,能顺畅的完成网络请求,是理所当然的事。换句话说,APP网络请求成功率,重要性直接体现在它能直接决定APP服务的可用性,直接影响到数据通信、视频播放、广告展现、支付便捷等服务质量。

本文将以爱奇艺的iOS端APP为例,分享对移动网络请求成功率优化方面的技术实践之路。

本文将同时发布于“即时通讯技术圈”公众号,欢迎关注:

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

2、相关文章

现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障

移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”》(* 必读好文

移动端IM开发者必读(二):史上最全移动弱网络优化方法总结

全面了解移动端DNS域名劫持等杂症:技术原理、问题根源、解决方案等

美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

百度APP移动端网络深度优化实践分享(一):DNS优化篇

百度APP移动端网络深度优化实践分享(二):网络连接优化篇

百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇

3、导致移动端网络请求失败的因素

想要优化移动端网络请求成功率,先来了解移动端网络请求全链条可能导致请求失败的环节有哪些。

这些环节往往由以下两类因素导致:

 
 

第一类:不可改善因素:

1)iOS系统对APP的网络访问权限控制、飞行模式或者无网络连接。检测和识别这三种情况,通过适当方式提示用户;

2)路由器故障。

第二类:可以改善因素:

1)蜂窝/Wifi信号的强弱、连接拥堵的假连接状态;

2)DNS故障(比如DNS劫持等);

3)运营商局部节点故障;

4)自有运营负载均衡故障;

5)业务服务器故障:HTTP响应错误,对应APM的HTTP响应错误率;

6)业务逻辑错误:监控子类解析结果,对应APM的解析错误率监控。

对于不可改善因素:目前只能通过网络诊断识别出故障类型,引导用户手动去授权访问网络或者连接可用网络。

其中,如果是路由器故障,可以引导用户重启路由器或者切换4G。通过爱奇艺APP的数据监控,大致可以看到用户无网连接的时长占比有3.8%左右,这说明提供好的无网提示变得十分重要,而从用户使用蜂窝信号的弱信号(0格和1格信号)时长占比有9%左右时长,也可以看出移动端网络环境的复杂性。

 
 

针对可以改善的因素,解决方法可大致分为三类:

1)网络层错误,对应因素1到4。主要体现为超时报错;

2)HTTP响应错误,对应因素5。HTTP状态码为400及以上;

3)解析错误,对应因素6。由基线网络库定义的重载接口进行监控。

为了提高网络请求成功率,首先需要建立监控体系,从而使得基线网络库能够通过网络统计模块向APM投递各种维度的网络请求数据。有了APM的数据统计后,才能有效的发现导致端上网络失败的原因,进而解决问题。

除此之外,由于端上网络请求数据巨大,存储空间的限制使得APM只能采样2%的用户,因此针对重点业务的网络请求(比如首页)则进行了全量采集,从而对成功率的优化实现更客观全面的评估。

4、在基线网络库这一层针对不同业务提供不同的补偿思路

在优化之前,通过APM的归类分析可以得出:请求失败的主要报错是超时(-1001)的占比达到九成,与此同时SSL错误,DNS解析错误占比紧随其后。根据这一数据统计,重试成为最主要的请求成功率优化的措施。

经过不断探索和实践总结,基线网络库针对不同业务需求提供了四种不同的重试手段。

1)IP直连重试,通过配置直连IP数来控制重试次数:

Scheme不变,Host改为直接使用IP(消除域名解析风险)。由于此举需要各个业务线自己提供直连的IP,目前接入的业务主要是登录等强制要求HTTPS连接的业务。

2)超级管道重试,可以配置1~3次重试:

公司自研基于HTTP的网关代理服务(类似于远程charles代理)。Host改为代理IP(消除域名解析风险),Scheme改为HTTP(消除SSL风险,h2降级为HTTP1.1)。由于该措施需要付出流量成本,目前接入的业务都是关键核心业务,比如首页等。

3)HTTP重试,可以配置1~3次重试:

Scheme修改为HTTP(消除SSL风险,h2降级为HTTP1.1),其他不变。鉴于其为普惠性重试手段,目前接入非关键核心的一般业务。

4)原url重试,可以配置1~3次重试:

Scheme和host等都不变,通常意义上理解的重试,单纯的再请求一次。此举目前不是推荐重试手段,由业务方自主决定。

 
 

除了单个重试手段可以重试多次,基础网络库也支持多种重试手段的组合,四种重试手段的优先次序为:IP直连重试 > 超级管道重试 > HTTP重试 > 原URL重试。扣除无网情况,首页推荐页CARD接口成功率通过组合重试在2020第一季度末达到了99.76%。

 

5、其它影响移动端网络请求成功率的因素

除了重试,还有以下因素对网络请求成功率有直接影响。

1)HTTP/2 vs HTTP/1.1:推荐的请求策略是首次请求走H2,当失败重试时走HTTP/1.1:

HTTP/2对HTTP/1.1最大改进是共用一个TCP连接(详见《从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路》),其在网络顺畅时,为HTTP/2带来了速度上的优势。但当网络变坏时,TCP包的绝对顺序编号会导致一个包的丢失而堵住后面所有的请求。这样单TCP连接反而扩大了拥堵,增大了请求失败的可能性。

NSURLSession是HTTP协议自适应的,不能控制请求使用HTTP/2或者HTTP/1.1。不过由于业界事实上的标准要求HTTP/2必须是HTTPs的,这样通过将URL Scheme改为HTTP可以间接降级到HTTP/1.1。

2)适当的超时设置是一个重要影响因素:

NSURLSession的超时实际上是TCP的包间超时,并不是整体请求耗时的超时。

 

推荐的超时设置策略是:首次请求的超时可以小一点,而重试的超时应该大一些。

3)接口请求过于密集并发可能降低请求成功率:

比如播放记录的upload接口在加上多次重试后,成功率仍然只有98.2%。APM监控此接口在IPv4环境失败率只有0.47%,而IPv6失败率高达7.07%。通过端上优化请求策略,降低接口的并发密度后,IPv6环境和IPv4环境同时提高到99.85%的成功率。

4)接口数据体积越小,请求成功率越高:

HTTP/2和HTTP/1.1都是基于TCP连接的,接口数据体积越小,需要传输的TCP包越少,传输失败的概率也就降低了。目前爱奇艺APP正在从gzip转向压缩率更高的br(指的是Brotli压缩算法,详见:《启用 Brotli 压缩算法,对比 Gzip 压缩 CDN 流量再减少 20%)。

6、提高鲁棒性并防止故障的优化措施

在经过各种优化措施提高网络成功率后,我们还通过下面几个措施成功的防止线上故障造成的成功率瞬时下降,提高了网络请求的鲁棒性。

1)超级管道本身的鲁棒性:

下面案例显示使用了超级管道重试的接口错误率只有3.95%,而没有使用超级管道重试的接口错误率高达28.96%。这个案例的时间点还没有使用异地容灾IP,在叠加异地容灾IP之后,错误率曲线几乎可以抹平。

 
 

2)HTTP重试和原URL重试在v4v6双栈环境下,优先IPv4:

由于IPv6仍在建设中,有些接口在IPv6的表现弱于IPv4,那么可以指定重试走IPv4。

3)TLS1.3– 1RTT的节省:

TLS1.3将SSL握手2个RTT降为1个RTT,降低了SSL握手失败的概率。iOS12.2开始,NSURLSession支持TLS1.3。只需要服务器升级支持TLS1.3即可,端上无须改动。

4)IP复合连接竞速:

使用TCP连接测速,目的是剔除坏IP,选择最优IP,从而提高请求的成功概率。

经上述措施的持续优化,爱奇艺APP在2020Q1末,扣除无网情况后,业务成功率达到了99.7%,而网络层成功率达到了99.77%。

▲ 业务成功率 = 网络层成功率+HTTP响应成功率+解析成功率

在完成优化后,爱奇艺APP基础网络库的构成如下:

 

如上图所示,基础网络库各模板的功能作用如下:

1)统一网络库:提供一个网络接口层,所有业务接口都对接使用网络接口层;

2)统一网络库:提供一个网络封装层,对接了iOS系统网络层NSURLSession、ASIHTTPRequest(基于CFNetwork)、和公司自研的长连接网关;

3)网络统计模块:将从业务调用开始到回调给业务方的各个环节的耗时及状态值,变成统计数据,上传到APM汇合;

4)网络诊断模块:对关键业务进行诊断,包括dns解析,ping,tcpconnect,trace等工具对具体IP进行分析,分析结果上传到APM汇合;

5)弱网检测模块:通过借鉴Facebook的弱网检测是基于网速拟合的网络等级分级,分为网络情况非常差(2G或者无网)、网络情况较差(3G)、网络情况一般、网络情况较好、网络情况非常好五个等级;

6)HTTPDNS模块:有效的解决了运营商劫持问题;

7)超级管道重试:基于HTTP的网关代理,具有异地容灾代理能力;

8)ipv4/ipv6模块:识别端上是ipv4 only环境、v4/v6双栈还是ipv6 only环境;

9)复合连接模块:可以在server IP缓存池选出最佳IP,手段包括目标IP连接竞速,IP历史请求统计数据排序;

10)网络日志模块:记录了最近发生的失败网络请求详细数据和网络诊断数据。随反馈一并提交,可以便捷的排查线上网络问题。

7、未来的目标与可能的优化措施

为了持续优化网络成功率,下一步目标是扣除无网情况,重点业务成功率达到99.9%。后续考虑的优化措施如下。

1)Multipath:

当Wifi假连接的时可以走蜂窝流量,iOS 7开始支持Multipath特性(详见:《揭开 iOS 7 之 Multipath TCP 的面纱》)。

2)QUIC:

QUIC是基于UDP的,由于运营商对UDP有针对性的丢包,实测QUIC并没有体现出优势。然而,考虑到libcurl在2019已提供完整QUIC能力,NSURLSession不久也会支持QUIC。随着运营商对UDP包的干扰减少,QUIC的优势将得到体现。

如果对QUIC协议感兴趣,可以读一读下面这些文章:

网络编程懒人入门(十):一泡尿的时间,快速读懂QUIC协议

技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解

让互联网更快:新一代QUIC协议在腾讯的技术实践分享

七牛云技术分享:使用QUIC协议实现实时视频直播0卡顿!

3)智能调度并发:

更精准更灵敏的弱网识别,弱网下对关键核心业务进行倾斜。

4)HTTPDNS的push能力:

HTTPDNS打通APM的质量监控体系后,通过push及时下线故障IP。

关于移动端DNS问题上的优化,业内已经有了很多总结,有兴趣可以深入研究:

全面了解移动端DNS域名劫持等杂症:技术原理、问题根源、解决方案等

美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

百度APP移动端网络深度优化实践分享(一):DNS优化篇

移动端网络优化之HTTP请求的DNS优化

附录:更多网络通信方面的技术资料

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

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

TCP/IP详解 - 第18章·TCP连接的建立与终止

TCP/IP详解 - 第21章·TCP的超时与重传

技术往事:改变世界的TCP/IP协议(珍贵多图、手机慎点)

通俗易懂-深入理解TCP协议(上):理论基础

通俗易懂-深入理解TCP协议(下):RTT、滑动窗口、拥塞处理

理论经典:TCP协议的3次握手与4次挥手过程详解

理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程

计算机网络通讯协议关系图(中文珍藏版)

UDP中一个包的大小最大能多大?

P2P技术详解(一):NAT详解——详细原理、P2P简介

P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解(基本原理篇)

P2P技术详解(三):P2P中的NAT穿越(打洞)方案详解(进阶分析篇)

P2P技术详解(四):P2P技术之STUN、TURN、ICE详解

通俗易懂:快速理解P2P技术中的NAT穿透原理

高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少

高性能网络编程(二):上一个10年,著名的C10K并发连接问题

高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了

高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索

高性能网络编程(五):一文读懂高性能网络编程中的I/O模型

高性能网络编程(六):一文读懂高性能网络编程中的线程模型

Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!

不为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)

不为人知的网络编程(二):浅析TCP协议中的疑难杂症(下篇)

不为人知的网络编程(三):关闭TCP连接时为什么会TIME_WAIT、CLOSE_WAIT

不为人知的网络编程(四):深入研究分析TCP的异常关闭

不为人知的网络编程(五):UDP的连接性和负载均衡

不为人知的网络编程(六):深入地理解UDP协议并用好它

不为人知的网络编程(七):如何让不可靠的UDP变的可靠?

不为人知的网络编程(八):从数据传输层深度解密HTTP

不为人知的网络编程(九):理论联系实际,全方位深入理解DNS

网络编程懒人入门(一):快速理解网络通信协议(上篇)

网络编程懒人入门(二):快速理解网络通信协议(下篇)

网络编程懒人入门(三):快速理解TCP协议一篇就够

网络编程懒人入门(四):快速理解TCP和UDP的差异

网络编程懒人入门(五):快速理解为什么说UDP有时比TCP更有优势

网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门

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

网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接

网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

网络编程懒人入门(十):一泡尿的时间,快速读懂QUIC协议

网络编程懒人入门(十一):一文读懂什么是IPv6

技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解

让互联网更快:新一代QUIC协议在腾讯的技术实践分享

现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障

聊聊iOS中网络编程长连接的那些事

移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端IM开发者必读(二):史上最全移动弱网络优化方法总结

IPv6技术详解:基本概念、应用现状、技术实践(上篇)

IPv6技术详解:基本概念、应用现状、技术实践(下篇)

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

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

脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

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

脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)

脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

脑残式网络编程入门(六):什么是公网IP和内网IP?NAT转换又是什么鬼?

脑残式网络编程入门(七):面视必备,史上最通俗计算机网络分层详解

脑残式网络编程入门(八):你真的了解127.0.0.1和0.0.0.0的区别?

以网游服务端的网络接入层设计为例,理解实时通信的技术挑战

迈向高阶:优秀Android程序员必知必会的网络基础

全面了解移动端DNS域名劫持等杂症:技术原理、问题根源、解决方案等

美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

Android程序员必知必会的网络通信传输层协议——UDP和TCP

IM开发者的零基础通信技术入门(一):通信交换技术的百年发展史(上)

IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)

IM开发者的零基础通信技术入门(三):国人通信方式的百年变迁

IM开发者的零基础通信技术入门(四):手机的演进,史上最全移动终端发展史

IM开发者的零基础通信技术入门(五):1G到5G,30年移动通信技术演进史

IM开发者的零基础通信技术入门(六):移动终端的接头人——“基站”技术

IM开发者的零基础通信技术入门(七):移动终端的千里马——“电磁波”

IM开发者的零基础通信技术入门(八):零基础,史上最强“天线”原理扫盲

IM开发者的零基础通信技术入门(九):无线通信网络的中枢——“核心网”

IM开发者的零基础通信技术入门(十):零基础,史上最强5G技术扫盲

IM开发者的零基础通信技术入门(十一):为什么WiFi信号差?一文即懂!

IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!

IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!

IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!

IM开发者的零基础通信技术入门(十五):理解定位技术,一篇就够

百度APP移动端网络深度优化实践分享(一):DNS优化篇

百度APP移动端网络深度优化实践分享(二):网络连接优化篇

百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇

技术大牛陈硕的分享:由浅入深,网络编程学习经验干货总结

可能会搞砸你的面试:你知道一个TCP连接上能发起多少个HTTP请求吗?

知乎技术分享:知乎千万级并发的高性能长连接网关技术实践

5G时代已经到来,TCP/IP老矣,尚能饭否?

爱奇艺移动网络优化实践分享:网络请求成功率优化篇(iOS端)

>> 更多同类文章 ……

欢迎关注我的“即时通讯技术圈”公众号:

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

posted @ 2020-04-21 14:20 Jack Jiang 阅读(189) | 评论 (0)编辑 收藏

本文同时发布于“即时通讯技术圈”公众号,链接是:https://mp.weixin.qq.com/s/cS5xB2DrjF52rmz6EGVJ6A

本文参考了公众号鲜枣课堂的“IPv6,到底是什么?”一文的部分内容,感谢原作者。

1、引言

现在IPv6的技术应用已经越来越普及了,很多应用都开始支持IPv6。

 

▲ 去年开始,支付宝的官网上就已出现“支持IPv6”标识

对于即时通讯技术(尤其是IM应用)的开发者来说,新产品上架苹果的App Store因IPv6问题被拒的情况,很常见。每次也都能根据网上的资料一一解决,并顺利通过审核。

然而几次下来,到底什么是IPv6,还是有点云里雾里。

那么,IP协议在TCP/IP体系中到底有多重要?看看下图便知(原因清晰版:从此处进入下载)。

 

▲ 红圈处就是IP协议,它几乎是整个TCP/IP协议簇的支撑(图引用自《计算机网络通讯协议关系图》)

总之,IP协议在TCP/IP体系中,是非常重要的一环(可以认为,没它,也就没有了互联网),作为IPv4的下一代协议,了解IPv6非常有必要。而作为即时通讯开发者来说,了解IPv6就显的尤为迫切,说不定某天你的IM就会因为IPv6问题而导致无法通信的局面出现。

本文将用浅显易懂的文字,带你了解到底什么是IPv6。

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

2、系列文章

本文是系列文章中的第11篇,本系列文章的大纲如下:

网络编程懒人入门(一):快速理解网络通信协议(上篇)

网络编程懒人入门(二):快速理解网络通信协议(下篇)

网络编程懒人入门(三):快速理解TCP协议一篇就够

网络编程懒人入门(四):快速理解TCP和UDP的差异

网络编程懒人入门(五):快速理解为什么说UDP有时比TCP更有优势

网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门

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

网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接

网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

网络编程懒人入门(十):一泡尿的时间,快速读懂QUIC协议

网络编程懒人入门(十一):一文读懂什么是IPv6》(本文)

3、复习一下什么是IPv4?

IPv4是Internet Protocol version 4的缩写,中文翻译为互联网通信协议第四版,通常简称为网际协议版本4。

IPv4使用32位(4字节)地址,因此地址空间中只有 4,294,967,296(即2^32) 个地址。

IPv4地址可被写作任何表示一个32位整数值的形式,但为了方便人类阅读和分析,它通常被写作点分十进制的形式,即四个字节被分开用十进制写出,中间用点分隔。

通常IPv4地址的地址格式为 nnn.nnn.nnn.nnn,就像下面这样:

172.16.254.1

下图看起来更清晰一些:

4、IPv6又是什么?

IPv6是Internet Protocol version 6的缩写,中文翻译为互联网通信协议(TCP/IP协议)第6版,通常简称为网际协议版6。IPv6具有比IPv4大得多的编码地址空间,用它来取代IPv4主要是为了解决IPv4地址枯竭问题,同时它也在其他方面对于IPv4有许多改进。

其实,IPv6并不是新技术,从IPv6最早的工作组成立1992年到现在,已过去27年。在互联网技术的发展历程中,IPv6年龄甚至有些太大了。

IPv6的“6”表示的是TCP/IP协议的第六个版本,IPv4的“4”表示的是TCP/IP协议的第四个版本。其实除了这两个版本,当然还有其它版本,TCP/IP协议其实从IPv1开始,到现在IPv10都已经出现了,这些不同版本之间并没有关联,也不是简单IP地址长度的长短。

IPv6地址由八组、每组四位16进制数字组成,每组之间由":"来分隔。

看个简单的例子:

2610:00f8:0c34:67f9:0200:83ff:fe94:4c36,每个“:”前后都是4位16进制的数字,共分隔成8组。

如下图所示: 

 

小知识:如何查看手机或者电脑的网络是否支持IPv6呢?

可以在你手机或者电脑上的浏览器中打开:Ipv6-test.com,就像下图这样: 

5、为什么要使用IPv6?

最主要的原因,就是地址数量不够用了。

IPv4迄今为止已经使用了30多年。最早期的时候,互联网只是设计给美国军方用的,根本没有考虑到它会变得如此庞大,成为全球网络。

尤其是进入21世纪后,随着计算机和智能手机的迅速普及,互联网开始爆发性发展,越来越多的上网设备出现,越来越多的人开始连接互联网。这就意味着,需要越来越多的IP地址。

IPv4的地址总数是2的32次方,也就是约42.9亿个。而全球的网民总数早已超过这个数目。

 

所以说,IPv4地址池接近枯竭,根本无法满足互联网发展的需要。人们迫切需要更高版本的IP协议,更大数量的IP地址池。(有点像固定电话号码升位。)

6、IPv6会带给我们什么?

首先,最重要的一点,就是前面所说的地址池扩容。IPv4的地址池是约42.9亿,IPv6能达到多少呢?

数量如下:

340282366920938463463374607431768211456个…

不用数了,太多了… 简单说,是2的128次方。

这个数量,即使是给地球上每一颗沙子都分配一个IP,也是妥妥够用的。

 

▲ 这图你看懂了吗?嗯,我也没看懂,反正就是很多的样子

这个数量值是怎么得来的呢?还是它的地址位长决定的。

如果以二进制来写,IPv6的地址是128位。不过,这样写显然不太方便(一行都写不下)。所以,通常用十六进制来写,也就缩短成32位(32位会分为8组,每组4位)。 

下面就是一个标准、合法的IPv6地址示例:

2001:0db8:85a3:08d3:1319:8a2e:0370:7344

注意:IPv6的地址是可以简写的,每项数字前导的0可以省略。

例如,下面这个地址:

2001:0DB8:02de:0000:0000:0000:0000:0e13

粉红的“0”就可以省略,变成:

2001: DB8:2de:0:0:0:0:e13

如果有一组或连续几组都是0,那么可以简写成“::”,也就是:

2001: DB8:2de::e13

注意:一个IPv6地址,只能有一个“::”。

为什么?很简单,你看下面这四个地址,如果所有0全都缩写,会变成什么样?

2001:0000:0000:0000:0000:25de:0000:cade

2001: 0000: 0000:0000:25de:0000:0000:cade

2001: 0000: 0000:25de:0000:0000:0000:cade

2001: 0000: 25de:0000:0000:0000:0000:cade

是的,都是2001::25de::cade,冲突了。所以,这个地址是非法的,不允许存在的。

关于IPv6还有很多技术细节,因篇幅原因,不再赘述。

除了地址数量之外,IPv6还有很多优点,例如:

1)IPv6使用更小的路由表。使得路由器转发数据包的速度更快;

2)IPv6增加了增强的组播支持以及对流的控制,对多媒体应用很有利,对服务质量(QoS)控制也很有利;

3)IPv6加入了对自动配置的支持。这是对DHCP协议的改进和扩展,使得网络(尤其是局域网)的管理更加方便和快捷;

4)IPv6具有更高的安全性。用户可以对网络层的数据进行加密并对IP报文进行校验,极大地增强了网络的安全性;

5)IPv6具有更好的扩容能力。如果新的技术或应用需要时,IPV6允许协议进行扩充;

6)IPv6具有更好的头部格式。IPV6使用新的头部格式,就简化和加速了路由选择过程,提高了效率;

……

7、IPv6的优点这么多,为什么之前普及却这么慢?

IPv6优点这么多,为什么它问世已经20年了,还是没有完全替代IPv4呢?这里面的水就很深了。。。说白了,主要还是和利益有关。

7.1 NAT这类技术,让IPv4得以续命

如果按照本世纪初专家们的预测,我们IPv4的地址早已枯竭几万次了。但是,一直挺到现在,大家仍然还在用IPv4,对老百姓来说,并没有因为地址不够而无法上网。

这是为什么呢? 就是因为除了IPv6之外,我们还有一些技术,可以变相地缓解地址不足。

例如NAT(Network Address Translation,网络地址转换)。

NAT是什么意思?当我们在家里或公司上网时,你的电脑肯定有一个类似192.168.0.1的地址,这种地址属于私网地址,不属于公共的互联网地址。

▲ 一个典型的NAT应用场景(图自《IPv6,到底是什么?》)

每一个小的局域网,都会使用一个网段的私网地址,在与外界连接时,再变换成公网地址。这样一来,几十个或几百个电脑,都只需要一个公网地址。

甚至还可以私网套私网,NAT套NAT,一层一层套。这样一来,大大节约了公网IP地址数量。正因为如此,才让我们“续命”到了今天,不至于无法上网。

但是,NAT这种方式也有很多缺点,虽然私网地址访问互联网地址方便,但互联网地址访问私网地址就困难了。很多服务,都会受到限制,你只能通过复杂的设置才能解决,也会影响网络的处理效率。

▲ NAT内网的计算机是不能被外网直接访问的(图自《IPv6,到底是什么?》)

7.2 升级IPv6涉及运营商的利益

物以稀为贵,地址越稀缺,就越值钱。掌握地址的人,就越开心。谁开心?运营商和ISP(互联网服务提供商)。

他们就像是经销商,从上游(互联网域名与号码分配机构,即ICANN)申请到IP地址,再卖给下游用户。稀缺没关系,反正,他一定能赚取更多的差价。

如果大家去找运营商或ISP买带宽,或者租赁云服务,带公共地址的,一定比不带公共地址的贵很多很多。

除了地址可以赚钱之外,如果升级支持IPv6,对运营商和ISP来说,也意味着很大的资金投入。现在新设备基本都是支持的,但毕竟还是有一些老设备,如果在使用寿命到期之前就换,就是亏钱。

所以,运营商和ISP都没有动力去启用IPv6。 

至于设备商或手机电脑厂商,出于提前考虑,早已普遍支持了IPv6,意见并不是很大,也决定不了什么。必竟,提供基础设施服务的运营商们更强势。

8、IPv6未来会怎样

随着5G时代的到来,有了IPv6的加持,万物互联或许会成为现实。对于我等实时通信类软件的开发人员来说,某些场景下,或许再也不需要为“P2P打洞”这种事情烦恼了。 

▲ 5G+IPv6,万物互联不是梦

未来已来,你准备好了吗?

9、参考资料

[1] IPv6入门教程

[2] IPv6,到底是什么?

[3] 关于IPv6的发展史!IPv6的秘密史!

[4] 科普:一文读懂IPv6是什么?

[5] 漫话:全球IPv4地址正式耗尽?到底什么是IPv4和IPv6?

附录:更多网络编程基础知识文章

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

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

TCP/IP详解 - 第18章·TCP连接的建立与终止

TCP/IP详解 - 第21章·TCP的超时与重传

技术往事:改变世界的TCP/IP协议(珍贵多图、手机慎点)

通俗易懂-深入理解TCP协议(上):理论基础

通俗易懂-深入理解TCP协议(下):RTT、滑动窗口、拥塞处理

理论经典:TCP协议的3次握手与4次挥手过程详解

理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程

计算机网络通讯协议关系图(中文珍藏版)

UDP中一个包的大小最大能多大?

P2P技术详解(一):NAT详解——详细原理、P2P简介

P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解(基本原理篇)

P2P技术详解(三):P2P中的NAT穿越(打洞)方案详解(进阶分析篇)

P2P技术详解(四):P2P技术之STUN、TURN、ICE详解

通俗易懂:快速理解P2P技术中的NAT穿透原理

高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少

高性能网络编程(二):上一个10年,著名的C10K并发连接问题

高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了

高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索

高性能网络编程(五):一文读懂高性能网络编程中的I/O模型

高性能网络编程(六):一文读懂高性能网络编程中的线程模型

Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!

不为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)

不为人知的网络编程(二):浅析TCP协议中的疑难杂症(下篇)

不为人知的网络编程(三):关闭TCP连接时为什么会TIME_WAIT、CLOSE_WAIT

不为人知的网络编程(四):深入研究分析TCP的异常关闭

不为人知的网络编程(五):UDP的连接性和负载均衡

不为人知的网络编程(六):深入地理解UDP协议并用好它

不为人知的网络编程(七):如何让不可靠的UDP变的可靠?

不为人知的网络编程(八):从数据传输层深度解密HTTP

不为人知的网络编程(九):理论联系实际,全方位深入理解DNS

技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解

让互联网更快:新一代QUIC协议在腾讯的技术实践分享

现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障

聊聊iOS中网络编程长连接的那些事

移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端IM开发者必读(二):史上最全移动弱网络优化方法总结

IPv6技术详解:基本概念、应用现状、技术实践(上篇)

IPv6技术详解:基本概念、应用现状、技术实践(下篇)

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

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

脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

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

脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)

脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

脑残式网络编程入门(六):什么是公网IP和内网IP?NAT转换又是什么鬼?

脑残式网络编程入门(七):面视必备,史上最通俗计算机网络分层详解

脑残式网络编程入门(八):你真的了解127.0.0.1和0.0.0.0的区别?

以网游服务端的网络接入层设计为例,理解实时通信的技术挑战

迈向高阶:优秀Android程序员必知必会的网络基础

全面了解移动端DNS域名劫持等杂症:技术原理、问题根源、解决方案等

美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

Android程序员必知必会的网络通信传输层协议——UDP和TCP

IM开发者的零基础通信技术入门(一):通信交换技术的百年发展史(上)

IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)

IM开发者的零基础通信技术入门(三):国人通信方式的百年变迁

IM开发者的零基础通信技术入门(四):手机的演进,史上最全移动终端发展史

IM开发者的零基础通信技术入门(五):1G到5G,30年移动通信技术演进史

IM开发者的零基础通信技术入门(六):移动终端的接头人——“基站”技术

IM开发者的零基础通信技术入门(七):移动终端的千里马——“电磁波”

IM开发者的零基础通信技术入门(八):零基础,史上最强“天线”原理扫盲

IM开发者的零基础通信技术入门(九):无线通信网络的中枢——“核心网”

IM开发者的零基础通信技术入门(十):零基础,史上最强5G技术扫盲

IM开发者的零基础通信技术入门(十一):为什么WiFi信号差?一文即懂!

IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!

IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!

IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!

IM开发者的零基础通信技术入门(十五):理解定位技术,一篇就够

百度APP移动端网络深度优化实践分享(一):DNS优化篇

百度APP移动端网络深度优化实践分享(二):网络连接优化篇

百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇

技术大牛陈硕的分享:由浅入深,网络编程学习经验干货总结

可能会搞砸你的面试:你知道一个TCP连接上能发起多少个HTTP请求吗?

知乎技术分享:知乎千万级并发的高性能长连接网关技术实践

5G时代已经到来,TCP/IP老矣,尚能饭否?

>> 更多同类文章 ……

欢迎关注我的“即时通讯技术圈”公众号: 

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

posted @ 2020-04-17 11:21 Jack Jiang 阅读(286) | 评论 (0)编辑 收藏

本文已同时发布于我的“即时通讯技术圈”公众号。

1、引言

哈罗,大家好,我是Jack Jiang。。。(一股浓浓的自媒体视频旁白味道)。

对于经常看我文章的即时通讯开发者来说,今天要讨论的这个话题,貌似有点不着边际。

是的,自从我整理完《IM开发者的零基础通信技术入门》系列文章之后,对于网络编程的理解,开始有点飘了。

言归正传。现在,5G技术离我们的生活越来越近了,号称网络延迟1ms、下行速度10Gb/s的5G,在这样逆天的网络性能指标下,老骥伏枥的TCP/IP是否仍能Hold的住?带着这个思考,便有了本文的内容。

 

▲ 5G网速有多快?看图感受一下(图自《零基础,史上最强5G技术扫盲》)

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

2、学好TCP/IP够用吗?

对于即时通讯技术的开发者,从技术栈来说,一条最普通的聊天消息的送达,肯定要涉及到网络编程技术,而网络编程最核心的也就是TCP/IP协议(准确的说是TCP/IP协议簇,见《TCP/IP详解》),毫无疑问深入的学习TCP/IP协议肯定是非常有必要了。

基本上,对于普通的IM或消息推送系统开发来说,对TCP/IP相关的计算机网络基础比较熟悉的话,完全够用了。

 

▲ 这本书很多人都读过

3、移动网络问题,只能赖我代码烂?

亲手写过即时通讯的网络通信层的同学都很清楚,在移动网络中(我说的移动网络具体指的是运营商的2g/3g/4g/5g这些),因为无线通信的介质和技术实现特殊性,出现了很多传统有线互联网不曾有过的网络通信问题。

就拿IM在移动弱网中出现的各种问题来说,多数开发者都不自信的认为这应该是自已的网络层代码写的不够优秀,是的,很多时候也确实是这样。

我收集整理的下面这几篇资料,就讨论的是这些,有兴趣可以读一下:

现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障

百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇

微信移动端应对弱网络情况的探索和实践PPT [附件下载]

YY直播在移动弱网环境下的深度优化实践分享(视频+PPT)[附件下载]

其实,很少有人会去思考,在TCP/IP协议被发明出来的50年后,对于现代的移动网络来说,是否仍然能工作的好?以弱网问题为例,难道我写的IM总是丢消息、掉线就仅仅是“我”的代码太烂? 

没错,这不仅仅是应用层的代码编写问题,它或许涉及到TCP/IP的设计局限,甚至移动网络的底层设计也并不是最完美的。

下面这两篇文章,对于弱网问题思考,已经深入到运营商的通信技术这一层,强烈建议读一读:

移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端IM开发者必读(二):史上最全移动弱网络优化方法总结

如果你的认知,已经开始对底层的网络通信技术有所困惑,下面这几篇就是为你准备的:

IM开发者的零基础通信技术入门(六):移动终端的接头人——“基站”技术

IM开发者的零基础通信技术入门(七):移动终端的千里马——“电磁波”

IM开发者的零基础通信技术入门(八):零基础,史上最强“天线”原理扫盲

IM开发者的零基础通信技术入门(九):无线通信网络的中枢——“核心网”

IM开发者的零基础通信技术入门(十):零基础,史上最强5G技术扫盲

IM开发者的零基础通信技术入门(十一):为什么WiFi信号差?一文即懂!

IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!

IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!

IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!

4、简单复习一下TCP/IP

从字面意义上讲,有人可能会认为 TCP/IP 是指 TCP 和 IP 两种协议。实际生活当中有时也确实就是指这两种协议。

然而在很多情况下,它只是利用 IP 进行通信时所必须用到的协议簇的统称。

具体来说,IP 或 ICMP、TCP 或 UDP、TELNET 或 FTP、以及 HTTP 等都属于 TCP/IP 协议。他们与 TCP 或 IP 的关系紧密,是互联网必不可少的组成部分。TCP/IP 一词泛指这些协议,因此,有时也称 TCP/IP 为网际协议簇。

互联网进行通信时,需要相应的网络协议,TCP/IP 原本就是为使用互联网而开发制定的协议簇。因此,互联网的协议就是 TCP/IP,TCP/IP 就是互联网的协议。 

▲ 上图反映了TCP/IP协议族的关系(图片引用自《计算机网络通讯协议关系图》)

5、TCP/IP或许太老了

对于现代移动网络来说,TCP/IP或许太老了。我们简单了解一下TCP/IP协议的产生过程。

1973年:卡恩与瑟夫开发出了TCP/IP协议中最核心的两个协议:TCP协议和IP协议。

1974年:卡恩与瑟夫正式发表了TCP/IP协议并对其进行了详细的说明。同时,为了验证TCP/IP协议的可用性,使一个数据包由一端发出,在经过近10万km的旅程后到达服务端。在这次传输中,数据包没有丢失一个字节,这充分说明了TCP/IP协议的成功。

1983年:TCP/IP协议正式替代NCP,从此以后TCP/IP成为大部分因特网共同遵守的一种网络规则。

1984年:TCP/IP协议得到美国国防部的肯定,成为多数计算机共同遵守的一个标准。 

是的,你没有看错,TCP/IP协议设计于距今50年前!

 

▲ 罗伯特·卡恩(左者)与文特·瑟夫(右者)(图片引用自《技术往事:改变世界的TCP/IP协议》)

6、TCP/IP原本是为固定网络设计的

虽然TCP/IP自上世纪70年代发明以来,连接了无数的计算机,推动了互联网的蓬勃发展。

但不可回避的现实是,基于TCP/IP的互联网,它的初衷是为固定网络和网络互连而设计,而今天我们已经发展到了移动互联时代。

再往后看,未来5G将面临AR/VR、超高清视频、物联网、车联网等各种应用、用例纷呈,加之网络安全的紧迫性越发凸显,TCP/IP或许难以适应未来。

7、TCP/IP或许并不适合移动网络

7.1 TCP/IP设计之初无法预见高速移动网时代

在TCP/IP刚被设计的年代,即传统固定互联网的公元元年,主机是固定的,用于编址的IP也是固定的,世界是平的。

可是随着应用程序以及芯片技术的活力涌现,设备越来越小,App越来越丰富,当你觉得浑身憋得慌的时候,移动互联网时代来了。

但传统的TCP/IP并不适合移动网络,以TCP/IP协议簇中我们最常用的TCP协议来说,传统的TCP基于TCP/IP协议头字段的五元组,而标识设备的IP地址仅仅标识了设备位置,并没有标识设备本身(实际上不管到了什么年代,IP地址都不应该标识设备本身,它就是标识位置的!问题是,TCP不应该用一个标识位置的元素来标识设备)。

而对于移动互联网来说,一旦移动设备(比如智能手机)换了位置(通信基站切换了),其IP地址也会改变,进而既有的TCP连接将全部中断。

 

▲ 运营商的基站是有覆盖范围的,而且覆盖范围并不大

对于底层的移动网络通信技术有所了解的开发人员或许知道,手机的通信是由基站进行代理的,而基站是固定的。换句话说,当你移动到下一个基站的位置时,手机就得自动切换到新的基站,进而重新进行一系列的跟运营商的无线体系进行连接建立的过程。

这在日常生活中使用并没有什么问题,但在时速达到350公里每小时的复兴号高铁上用手机上网时,这就会导致严重的问题。因为基站的信号覆盖范围有限,在手机移动速度如此之快的情况下,基站的切换也将频繁到让网络工程师们崩溃(有兴趣可以读一下《IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!》)。

TCP/IP和网络的关系,可以作个有趣的类比。

假设互联网是公路,那么TCP/IP这就是这条公路上的一套交通规则。这套规则在制定时,可能考虑到的只是普通的市场内道路(最多是高速公路使用),而现在的5G时代,就好比时速350公里的高速铁路,试想普通的市内交通规则套用在高速铁路上,那难道不算是灾难吗。

必竟普通的市内交通速度不会很快,各种规则的制定误差和余量可以比较大,但高速铁路上,速度飞快、交通信号控制精确无比的情况下,这套规则,对于开高铁的司机来说,肯定是胆颤心惊。而TCP/IP对于5G来说,就好比这套老的交通规则,用它来驾驭这么快速的5G快车,是不是很疯狂?

 

7.2 TCP/IP与电信网的基因不同

基于TCP/IP的互联网原本是为固定网络和网络互联设计,而运营商的移动网络是为移动性连接而生。互联网的连接是分布式的,而移动通信网络是集中控制的。

这两者的技术基因确实有很大不同,在早期移动网络网络性能较慢的情况下,这两者的结合,矛盾似乎并不突出。

实际上,在传统电信网(就是大家最常用的电话、短信网络)与IT互联网是两拨人各自有玩耍(电信网为代表的就是3GPP标准化组织,互联网为代表的就是IETF标准化组织)。

在那个移动网还不发达的年代,这两拨人各自玩各自的,大家谁也不用鸟谁。

随着人们对移动上网需求越来越旺盛,搞电信网的这拨人只能想办法接入传统的互联网,必竟在当时传统互联网太强势,而移动网的应用场景还在摸索阶段,为了能快速解决移动上网的问题,与是也不好麻烦IETF这拨人,所有痛苦默默承受——虽然TCP/IP在移动网上的实施并不合适,但只能想办法缝缝补补,把移动网的标准制定,往它上面靠。

这就好比,TCP/IP这辆车已经造好了,至于你搞移动网的人,是修一条普通马路(2G)、还是一条高速公司路(3G)、或者是现在的高速铁路(5G),反正你只能将就这辆车。原本应该是什么路上跑什么车,而现在是不管你什么路,只能跑这辆车。反正车子跑不好,不怪车子,怪路。。

好奇葩的逻辑,而这个逻辑就好比是现在的TCP/IP跟移动网的关系。

所以,在5G,甚至未来的6G、7G时代,这种“勉强”的结合,抛必带来网络低效、基础设施成本高昂等问题。

8、移动运营商们已经意识到问题

是的,大佬们已经意识到了问题的严重性,正在着手解决。

2020年4月初,欧洲电信标准协会(ETSI)已成立了一个新的行业规范工作组“Non-IP Networking”(ISG NIN),以解决新服务、尤其是5G服务面临的老式网络协议所存在的问题。

▲ 详细新闻内容《点此查看

该工作组的目标是为5G网络研究开发新的网络协议,以替代TCP/IP。

是的,这些移动运营商已经发现在4G、甚至5G网络中使用的基于TCP/IP的技术存在一些问题。

由于TCP/IP协议最初是为互联网设计,而非为移动通信网络而生,当移动通信网络引入TCP/IP后,增加了移动性、安全性、QoS等功能,这使得网络更复杂,频谱使用效率较低。为了解决这些问题,后续的修补和替代方案又导致了成本、时延和功耗增加。

大佬们终于承认,对于5G的某些高级服务,TCP/IP确实被认为不是最佳的。

9、移动网络未来会怎样?

虽然TCP/IP可能越来越难以适应移动网络的发展,但不可否认,短期内TCP/IP的不可替代性。

必竟,基于TCP/IP的传统互联网所构建的软件和硬件世界(尤其是硬件)并不是一朝一夕的事,而替换掉这些,无论是从成本还是各方利益来说,都是个需要反复权衡和博弈的事。

一个很好的例子是,IPv4和IPv6,虽然谁都知道IPv4的困境,但IPv6喊了这么多年目前想要普及,仍然还比较遥远,要知道IPv6已经喊了10年了。因为这小小的IP地址,牵涉的是互联网从硬到软几乎所有环节,影响之大,无出其右。

对于IM开发者来说,因为移动网络的特殊性,而技术改朝换代也并不鲜见。

比如众所周之的XMPP协议,设计之初也是野心勃勃——“要让上IM就像打开网页一样简单!”。确实,XMPP无论是肉眼可读性,还是数据结构的优雅,都非常优秀,但悲剧的是,设计者们从来没有想过移动网会发展成今天这样,或者说设计者们从未考虑过XMPP在移动网下的使用。于是,后面的故事,大家都很清楚——每个人都在抱怨XMPP臃肿、冗余(是的,这里我收集了一大堆这样的文章),这算个是把优点做成缺点的典型案例了。

或许,未来会有那么一天,移动网络终有属于为自已定制的网络协议标准。而对于搞网络通信的程序员来说,如果这套新的标准让能基于移动网络的代码编写,变的愉快起来,那真是谢天谢地了!

10、参考资料

[1] TCP/IP 已完 ?New IP 之后,又来一个 Non-IP

[2] 5G:再见,TCP/IP

[3] 重新设计TCP/IP协议栈以支持设备移动性

[4] 5G要抛弃TCP/IP?

[5] ETSI LAUNCHES NEW GROUP ON NON-IP NETWORKING ADDRESSING 5G NEW SERVICES

附录:更多网络编程基础资料

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

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

TCP/IP详解 - 第18章·TCP连接的建立与终止

TCP/IP详解 - 第21章·TCP的超时与重传

技术往事:改变世界的TCP/IP协议(珍贵多图、手机慎点)

通俗易懂-深入理解TCP协议(上):理论基础

通俗易懂-深入理解TCP协议(下):RTT、滑动窗口、拥塞处理

理论经典:TCP协议的3次握手与4次挥手过程详解

理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程

计算机网络通讯协议关系图(中文珍藏版)

UDP中一个包的大小最大能多大?

P2P技术详解(一):NAT详解——详细原理、P2P简介

P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解(基本原理篇)

P2P技术详解(三):P2P中的NAT穿越(打洞)方案详解(进阶分析篇)

P2P技术详解(四):P2P技术之STUN、TURN、ICE详解

通俗易懂:快速理解P2P技术中的NAT穿透原理

高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少

高性能网络编程(二):上一个10年,著名的C10K并发连接问题

高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了

高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索

高性能网络编程(五):一文读懂高性能网络编程中的I/O模型

高性能网络编程(六):一文读懂高性能网络编程中的线程模型

Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!

不为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)

不为人知的网络编程(二):浅析TCP协议中的疑难杂症(下篇)

不为人知的网络编程(三):关闭TCP连接时为什么会TIME_WAIT、CLOSE_WAIT

不为人知的网络编程(四):深入研究分析TCP的异常关闭

不为人知的网络编程(五):UDP的连接性和负载均衡

不为人知的网络编程(六):深入地理解UDP协议并用好它

不为人知的网络编程(七):如何让不可靠的UDP变的可靠?

不为人知的网络编程(八):从数据传输层深度解密HTTP

不为人知的网络编程(九):理论联系实际,全方位深入理解DNS

网络编程懒人入门(一):快速理解网络通信协议(上篇)

网络编程懒人入门(二):快速理解网络通信协议(下篇)

网络编程懒人入门(三):快速理解TCP协议一篇就够

网络编程懒人入门(四):快速理解TCP和UDP的差异

网络编程懒人入门(五):快速理解为什么说UDP有时比TCP更有优势

网络编程懒人入门(六):史上最通俗的集线器、交换机、路由器功能原理入门

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

网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接

网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

网络编程懒人入门(十):一泡尿的时间,快速读懂QUIC协议

技术扫盲:新一代基于UDP的低延时网络传输层协议——QUIC详解

让互联网更快:新一代QUIC协议在腾讯的技术实践分享

现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障

聊聊iOS中网络编程长连接的那些事

移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端IM开发者必读(二):史上最全移动弱网络优化方法总结

IPv6技术详解:基本概念、应用现状、技术实践(上篇)

IPv6技术详解:基本概念、应用现状、技术实践(下篇)

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

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

脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?

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

脑残式网络编程入门(四):快速理解HTTP/2的服务器推送(Server Push)

脑残式网络编程入门(五):每天都在用的Ping命令,它到底是什么?

脑残式网络编程入门(六):什么是公网IP和内网IP?NAT转换又是什么鬼?

脑残式网络编程入门(七):面视必备,史上最通俗计算机网络分层详解

脑残式网络编程入门(八):你真的了解127.0.0.1和0.0.0.0的区别?

以网游服务端的网络接入层设计为例,理解实时通信的技术挑战

迈向高阶:优秀Android程序员必知必会的网络基础

全面了解移动端DNS域名劫持等杂症:技术原理、问题根源、解决方案等

美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

Android程序员必知必会的网络通信传输层协议——UDP和TCP

IM开发者的零基础通信技术入门(一):通信交换技术的百年发展史(上)

IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)

IM开发者的零基础通信技术入门(三):国人通信方式的百年变迁

IM开发者的零基础通信技术入门(四):手机的演进,史上最全移动终端发展史

IM开发者的零基础通信技术入门(五):1G到5G,30年移动通信技术演进史

IM开发者的零基础通信技术入门(六):移动终端的接头人——“基站”技术

IM开发者的零基础通信技术入门(七):移动终端的千里马——“电磁波”

IM开发者的零基础通信技术入门(八):零基础,史上最强“天线”原理扫盲

IM开发者的零基础通信技术入门(九):无线通信网络的中枢——“核心网”

IM开发者的零基础通信技术入门(十):零基础,史上最强5G技术扫盲

IM开发者的零基础通信技术入门(十一):为什么WiFi信号差?一文即懂!

IM开发者的零基础通信技术入门(十二):上网卡顿?网络掉线?一文即懂!

IM开发者的零基础通信技术入门(十三):为什么手机信号差?一文即懂!

IM开发者的零基础通信技术入门(十四):高铁上无线上网有多难?一文即懂!

IM开发者的零基础通信技术入门(十五):理解定位技术,一篇就够

百度APP移动端网络深度优化实践分享(一):DNS优化篇

百度APP移动端网络深度优化实践分享(二):网络连接优化篇

百度APP移动端网络深度优化实践分享(三):移动端弱网优化篇

技术大牛陈硕的分享:由浅入深,网络编程学习经验干货总结

可能会搞砸你的面试:你知道一个TCP连接上能发起多少个HTTP请求吗?

知乎技术分享:知乎千万级并发的高性能长连接网关技术实践

5G时代已经到来,TCP/IP老矣,尚能饭否?

>> 更多同类文章 ……

欢迎关注我的“即时通讯技术圈”公众号: 

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

posted @ 2020-04-13 23:41 Jack Jiang 阅读(327) | 评论 (0)编辑 收藏

     摘要: 本文作者腾讯WXG后台开发工程师jeryyzhang,收录时有改动,感谢原作者的分享。1、引言大约3年前,微信技术团队分享了《微信后台基于时间序的海量数据冷热分级架构设计实践》一文,文中总结了微信这种超级IM基于时间序的海量数据存储架构的设计实践,也得以让大家了解了微信后台的架构设计思路。时隔3年,微信再次分享了基于时间序的新一代海量数据存储架构的设计实践(可以认为是《微信后台基于时间序的海量数据...  阅读全文

posted @ 2020-04-09 15:07 Jack Jiang 阅读(222) | 评论 (0)编辑 收藏

     摘要: 一、引言2020年春节早已过去两月有余,回顾本次腾讯手Q春节红包活动的玩法,主要以答题形式结合中国传统文化(成语、诗词、对联、历史等)的方式进行,达到寓教于乐的效果。 ▲ 2020年春节QQ的红包活动对于这种大体量的IM社交应用运营活动,技术上除了前端、后台的大力支撑,对于手Q客户端来说,又是从哪些方面来保证整个红包活动的灵活性、稳定性和用户体验的呢?带着这个问题,我们一起来...  阅读全文

posted @ 2020-04-06 23:41 Jack Jiang 阅读(194) | 评论 (0)编辑 收藏

     摘要: 本文原文由微信客户端高级工程师方秋枋原创发表于WeMobileDev公众号,收录时有修订和加工,感谢作者的无私分享。1、引言作为一个重要业务,微信支付在客户端上面临着各种问题。其中最核心问题就是分平台实现导致的问题:1)iOS 和安卓实现不一致:容易出 Bug、通过沟通保证不了质量;2)扩展性差且无法快速响应业务需求:需求变更迭代周期长、数据上报不全面;3)质量保障体系不完善:缺少业务及设计知识沉...  阅读全文

posted @ 2020-03-25 17:00 Jack Jiang 阅读(310) | 评论 (0)编辑 收藏

     摘要: 1、引言很多人一想到IM应用开发,第一印象就是“长连接”、“socket”、“保活”、“协议”这些关键词,没错,这些确实是IM开发中肯定会涉及的技术范畴。但,当你真正开始编写第一行代码时,最现实的问题实际上是“聊天消息ID该怎么生成?”这个看似微不足道的小事情。说它看似微不足道,...  阅读全文

posted @ 2020-03-19 17:34 Jack Jiang 阅读(252) | 评论 (0)编辑 收藏

本文原文由作者Amazing10原创发布于公众号业余码农,收录时有改动,感谢原作者的技术分享。

1、引言

某天中午,吃完午饭,摊在自己的躺椅上,想趁吃饱喝足的午后时间静静享受独自的静谧。

 
 

干点什么好呢?于是单手操作鼠标打开了一个陌生而隐秘的网站。正开着某个视频起劲。。。

突然浏览器弹出了一个提示:

请使用微信扫码登录账号,继续观看

这...

 
 

但是由于强烈的好奇驱使,迫于无奈,只好选择登录再继续观看。于是熟练的掏出手机,打开微信扫一扫对准上面的二维码,只听见 “叮” 的一声,网页上的二维码放佛活过来了,直接刷新出了本尊的微信头像,同时手机上也弹出登录的提醒。

 
 

心中略微惊叹,但没来得及多想。忙点击手机界面中登录按钮。此时网页刷新,恢复了正常,表示可以继续观看。

上网冲浪的时间总是过得很快,很快就有些疲倦。于是闭上眼睛,脑海中却浮现出了刚刚微信扫描二维码,然后登录网页的场景,心中再次惊叹,并开始思考起其中的原理来。。。

言归正传,本文将以轻松活泼的语言形式,为你分析和讲解微信手机扫码登录的技术原理,希望在你的IM中开发此功能时有所启发。

推荐阅读:另一篇同类文章《IM的扫码登录功能如何实现?一文搞懂主流的扫码登录技术原理》也值得一读。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170[推荐]

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

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

2、IM开发干货系列文章

本文是系列文章中的第23篇,总目录如下:

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

IM消息送达保证机制实现(二):保证离线消息的可靠投递

如何保证IM实时消息的“时序性”与“一致性”?

IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?

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

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

移动端IM登录时拉取数据如何作到省流量?

通俗易懂:基于集群的移动端IM接入层负载均衡方案分享

浅谈移动端IM的多点登录和消息漫游原理

IM开发基础知识补课(一):正确理解前置HTTP SSO单点登录接口的原理

IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?

IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议

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

IM群聊消息的已读回执功能该怎么实现?

IM群聊消息究竟是存1份(即扩散读)还是存多份(即扩散写)?

IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列

一个低成本确保IM消息时序的方法探讨

IM开发基础知识补课(六):数据库用NoSQL还是SQL?读这篇就够了!

IM里“附近的人”功能实现原理是什么?如何高效率地实现它?

IM开发基础知识补课(七):主流移动端账号登录方式的原理及设计思路

IM开发基础知识补课(八):史上最通俗,彻底搞懂字符乱码问题的本质

IM的扫码登功能如何实现?一文搞懂主流应用的扫码登录技术原理

IM要做手机扫码登陆?先看看微信的扫码登录功能技术原理》(本文)

3、原理解析

微信扫码登录现在在日常生活中已经是常见不能再常见的场景之一了,但是要知道微信首次公开这项功能时,却是惊艳众人。移动端与PC端以这样一种巧妙的方式链接在了一起,的确是让人惊叹。

以下是一个典型的微信扫码登录全过程: 

本来想在Web版微信上截图,但扫码登陆后出现了下面的提示(貌似很多人都碰到过): 

好吧,这很微信,反正就是不想让你好好用,用户爱咋咋滴。。。

如上图所示,操作过程如下:

1)第一步:电脑上打开PC端(出现2维码);

2)第二步:拿出手机,扫码2维码;

3)第三步:PC端显示扫码成功;

4)第四步:手机端“确认”登录;

5)第五步:成功登陆PC端。

上述实际操作过程,用户体验相当顺滑,也难怪刚出来那会,能惊艳到很多人。

那么,对于上述操作过程的技术实现原理是什么样的呢?

想起来之前听过的前后端的概念,知道账户的数据信息一般都是放在服务器上,前端负责向后端 “讨要数据” 并显示,后端则是对前端的 “讨要” 做出反应。

这样一来,猜测微信登录的过程可能就是:

1)网页前端向微信后台请求账号数据;

2)微信后台接受网页前端的请求,然后将他的账号数据返回;

3)网页前端接收到了数据后,在浏览器里进行显示。

于是,手脚麻利的画了个示意图:

当我正准备沾沾自喜的时候,突然看到桌面上的手机。咦,如果就只是这么个过程,那手机的作用是啥。于是才开始意识到,问题没这么简单。

好吧,我们城要再深入一点探秘微信扫码登录的过程。

4、过程分析

为了更深入的分析整个过程,我们可以去看看微信网页版,地址是:https://wx.qq.com/

 

笔者看着网页中硕大的二维码陷入了沉思——这个二维码跟手机账号有没有什么对应关系呢?如果没有,那它又是怎么生成的呢?

思考间,于是打开了浏览器的开发者工具。

在网络监控一览找到了这幅二维码,与之对应的链接是:

https://login.weixin.qq.com/qrcode/gaO8cOQweA==

如下图所示:

然后习惯性地,尝试多次刷新页面,发现二维码不断发生变化,链接也不断更改:

https://login.weixin.qq.com/qrcode/AencxgKNFQ==

https://login.weixin.qq.com/qrcode/YcD7f_DxvA==

https://login.weixin.qq.com/qrcode/QblN8lCn2g==

似乎发现了些东西:二维码不断变化,其对应的链接尾的代码也相应变化,并且是随机性的变化。

这也就是说,每一次页面刷新都会随机且唯一地生成一个二维码。这或许可以与手机登录的过程联系起来。

似乎开始明白了,于是再次拿起手机,熟练的使用微信扫描了此时的二维码。

“叮” 的一声,网页上的二维码顿时变成了我帅气的微信头像。这个时候,我才突然意识到,是扫码之后网页才与他的微信账号建立起了联系。

如下图所示: 

也就是说:

1)没有扫码之前,页面上的二维码只是随机生成的且与用户无关的码;

2)而当用户扫码之后,二维码便与用户帐号绑定在了一起。

原来手机扫码的用处是这样!

此时注意到,手机微信上弹出了『微信登录确认』的提醒。这个时候谨慎地点击了下方的登录按钮。

如下图所示: 

随着平滑的动画一闪而过,网页上已经显示出了我的微信账号信息,显示微信账号已经登录。再一次体验这个过程,心中开始思索手机微信在登录过程中所起到的具体作用。

首先需要明白几个过程:

1)进入网页登陆界面,随机生成一个二维码;

2)通过手机扫描二维码,将微信账号与二维码绑定;

3)在手机微信点击登录按钮,授权网页登录微信账号;

4)网页获得的账号信息,将数据显示。

5、原理解释

回顾上述过程,结合最开始的原理猜测,开始思索整个环节,是哪里理解的不对。。。

1)网页的二维码到底从何而来?

2)是谁向微信后台请求了账号数据?

实际上:不同的网站可能都需要通过微信后台进行数据的获取,那么每一个网站必然也存在它的后台来给微信后台发送请求。

这样一来,整个过程就能解释得通了:

1)网站页面刷新,网页后台向微信后台请求授权登录;

2)微信后台返回登录所需二维码;

3)用户通过手机扫描二维码,并在手机上授权登录后,微信后台告知网页后台已授权;

4)网页后台向微信后台请求微信账号数据;

5)微信后台返回账号数据;

6)网页后台接收数据并通过浏览器显示;

6、技术剖析

正如上节所述,想清楚了整个过程后,我们应该对整个过程的技术实现进行进一步的探究。

在微信开发官方文档中,我找到了第三方网站应用微信登录开发指南:

https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

我将整个过程梳理了一遍,画出了这个图: 

如上图所示,整个技术实现如下。

(1)二维码的获得:

  • 1)用户打开网站后,网站后台根据微信OAuth2.0协议向微信开发平台请求授权登录,并传递事先在微信开发平台中审核通过的AppID和AppSecrect等参数;
  • 2)微信开发平台对AppID等参数进行验证,并向网站后台返回二维码;
  • 3)网站后台将二维码传送至网站前端进行显示。

(2)微信客户端授权登录:

  • 1)用户使用微信客户端扫描二维码并授权登录;
  • 2)微信客户端将二维码特定的uid与微信账号绑定,传送至微信开发平台;
  • 3)微信开发平台验证绑定数据,调用网站后台的回调接口,发送授权临时票据code;

(3)网站后台请求数据:

  • 1)网站后台接收到code,表明微信开发平台同意数据请求;
  • 2)网站后台根据code参数,再加上AppID和AppSecret请求微信开发平台换取access_token;
  • 3)微信开发平台验证参数,并返回access_token;
  • 4)网站后台收到access_token后即可进行参数分析获得用户账号数据。

在上述过程中,有几个参数值得解释一下(来源官方文档):

  • 1)AppID:应用唯一标识,在微信开放平台提交应用审核通过后获得;
  • 2)AppSecret:应用密钥,在微信开放平台提交应用审核通过后获得;
  • 3)code:授权临时票据,第三方通过code进行获取access_token的时候需要用到,code的超时时间为10分钟,一个code只能成功换取一次access_token即失效。code的临时性和一次性保障了微信授权登录的安全性。

整个过程从网站后台向微信开发平台请求授权登录开始,最终目的是为了获得access_token:

access_token:用户授权第三方应用发起接口调用的凭证

在获得了access_token后就可以解析用户的一些基本信息,包括头像、用户名、性别、城市等。这样一来,整个微信扫描登录的过程就完成了。

7、写在最后

研究到这,终于大体上对微信扫码登录的整个过程有了清晰的认知。看起来似乎也不难,开发者只需要在网页后端做好对微信公众平台的接口调用即可实现扫码登录。

伸了伸懒腰,忽然又想到在整个过程中还需要考虑超时的问题。比如二维码超时未扫描、二维码扫描后超时授权、获得access_token后超时等等问题。

我发现一个简单的功能实现起来还是需要考虑许多细节,真的是纸上得来终觉浅呀。于是我下定决心,下次得少上网冲浪了,花点时间搭个服务器先把微信扫码登录过程实现看看。

不过,还得先去在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret才行。

想了想,还是让我先趟一会儿吧。。。

 

附录:更多IM开发相关文章

[1] IM开发热门文章:

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

移动端IM开发者必读(一):通俗易懂,理解移动网络的“弱”和“慢”

移动端IM开发者必读(二):史上最全移动弱网络优化方法总结

从客户端的角度来谈谈移动端IM的消息可靠性和送达机制

现代移动端网络短连接的优化手段总结:请求速度、弱网适应、安全保障

腾讯技术分享:社交网络图片的带宽压缩技术演进之路

小白必读:闲话HTTP短连接中的Session和Token

移动端IM开发需要面对的技术问题

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

请问有人知道语音留言聊天的主流实现方式吗?

通俗易懂:基于集群的移动端IM接入层负载均衡方案分享

微信对网络影响的技术试验及分析(论文全文)

即时通讯系统的原理、技术和应用(技术论文)

开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀

QQ音乐团队分享:Android中的图片压缩技术详解(上篇)

QQ音乐团队分享:Android中的图片压缩技术详解(下篇)

腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率

腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(上篇)

腾讯原创分享(三):如何大幅压缩移动网络下APP的流量消耗(下篇)

如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源

基于社交网络的Yelp是如何实现海量用户图片的无损压缩的?

腾讯技术分享:腾讯是如何大幅降低带宽和网络流量的(图片压缩篇)

腾讯技术分享:腾讯是如何大幅降低带宽和网络流量的(音视频技术篇)

字符编码那点事:快速理解ASCII、Unicode、GBK和UTF-8

全面掌握移动端主流图片格式的特点、性能、调优等

子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技术实践

微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)

自已开发IM有那么难吗?手把手教你自撸一个Andriod版简易IM (有源码)

融云技术分享:解密融云IM产品的聊天消息ID生成策略

适合新手:从零开发一个IM服务端(基于Netty,有完整源码)

拿起键盘就是干:跟我一起徒手开发一套分布式IM系统

>> 更多同类文章 …… 

[2] 有关WEB端即时通讯开发:

新手入门贴:史上最全Web端即时通讯技术原理详解

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

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

Comet技术详解:基于HTTP长连接的Web端实时通信技术

新手快速入门:WebSocket简明教程

WebSocket详解(一):初步认识WebSocket技术

WebSocket详解(二):技术原理、代码演示和应用案例

WebSocket详解(三):深入WebSocket通信协议细节

WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)

WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)

WebSocket详解(六):刨根问底WebSocket与Socket的关系

socket.io实现消息推送的一点实践及思路

LinkedIn的Web端即时通讯实践:实现单机几十万条长连接

Web端即时通讯技术的发展与WebSocket、Socket.io的技术实践

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

开源框架Pomelo实践:搭建Web端高性能分布式IM聊天服务器

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

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

MobileIMSDK-Web的网络层框架为何使用的是Socket.io而不是Netty?

理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性

微信小程序中如何使用WebSocket实现长连接(含完整源码)

八问WebSocket协议:为你快速解答WebSocket热门疑问

快速了解Electron:新一代基于Web的跨平台桌面技术

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

Web端即时通讯基础知识补课:一文搞懂跨域的所有问题!

>> 更多同类文章 ……

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

posted @ 2020-03-13 17:15 Jack Jiang 阅读(250) | 评论 (0)编辑 收藏

     摘要: 一、引言对于后端程序员来说,127.0.0.1和0.0.0.0这两个IP地址再熟悉不过了,看起来好像就那么回事,但真正较起真来,这两个IP地址到底有什么作用以及到底有什么不同?貌似谁可以轻松回答,但张嘴却又不知从何说起。。。(这要是面视,估计真会被这搞砸...)本文将系统地总结127.0.0.1和0.0.0.0这两个IP地址的作用,以及它们之间的区别,希望能为你解惑。  * 推...  阅读全文

posted @ 2020-03-03 15:53 Jack Jiang 阅读(423) | 评论 (0)编辑 收藏

     摘要: 1、引言上个月在知乎上发表的由“袁辉辉”分享的关于TIM进程永生方面的文章(即时通讯网重新整理后的标题是:《史上最强Android保活思路:深入剖析腾讯TIM的进程永生技术》),短时间内受到大量关注,可惜在短短的几十个小时后,就在一股神秘力量的干预下被强行删除了。。。 ▲ 该文在知乎上从发布到删除的时间历程(中间省略了N条读者的评论)在《史上最强And...  阅读全文

posted @ 2020-02-26 22:44 Jack Jiang 阅读(308) | 评论 (0)编辑 收藏

本文由马蜂窝技术团队电商交易基础平台研发工程师"Anti Walker"原创分享。

一、引言

即时通讯(IM)功能对于电商平台来说非常重要,特别是旅游电商。

从商品复杂性来看,一个旅游商品可能会包括用户在未来一段时间的衣、食、住、行等方方面面。从消费金额来看,往往单次消费额度较大。对目的地的陌生、在行程中可能的问题,这些因素使用户在购买前、中、后都存在和商家沟通的强烈需求。可以说,一个好用的 IM 可以在一定程度上对企业电商业务的 GMV 起到促进作用。

本文我们将结合马蜂窝旅游电商IM系统的发展历程,单独介绍基于Go重构分布式IM系统过程中的实践和总结(本文相当于《从游击队到正规军(一):马蜂窝旅游网的IM系统架构演进之路》一文的进阶篇),希望可以给有相似问题的朋友一些借鉴。

另外:如果你对Go在高并发系统中的应用感兴趣,即时通讯网的以下两篇也值得一读:

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

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

系列文章:

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

从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结

从游击队到正规军(三):基于Go的马蜂窝旅游网分布式IM系统技术实践》(* 本文

关于马蜂窝旅游网: 

马蜂窝旅游网是中国领先的自由行服务平台,由陈罡和吕刚创立于2006年,从2010年正式开始公司化运营。马蜂窝的景点、餐饮、酒店等点评信息均来自上亿用户的真实分享,每年帮助过亿的旅行者制定自由行方案。

学习交流:

- 即时通讯/推送技术开发交流5群:215477170 [推荐]

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

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

二、相关文章

一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

一套原创分布式即时通讯(IM)系统理论架构方案

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

蘑菇街即时通讯/IM服务器开发之架构选择

以微博类应用场景为例,总结海量社交系统的架