消息推和拉的区别

对于一个可靠的IM系统,需要保证消息的百分之百到达对端。即使是在极端情况下丢失一条消息也是不能容忍的。一个极其极其低概率的事件,若是放大到分布式系统中,那这个概率事件就成了必然事件。在开发测试中如果发现一次偶然的消息丢失问题而忽略不查,那上线之后就必然会发生消息丢失。所以作为技术,一定不能放过任何一个极端情况下发生的问题。

在服务器给客户端发送消息的过程中,有两种方式,1.主动推送消息给客户端;2.客户端来拉消息。这两种方式都可以达到目的,下面就来分析一下两者的区别。

A   ->  SERVER  -> B

上述描述一种简单模型,A给B发送一条消息,首先会到达服务器,然后服务器将消息转发给客户端B。这是推的方式,服务器是直接将消息推给客户端的。那在复杂的网络环境中,如何保证消息能够到达B端?

这个例子有两处需要做保证,第一是如何保证A发出去的消息成功到达服务器。第二处是服务器推给B的消息如何知道已经成功送达。

本文主要分析第二条。

在正常情况下,服务器直接把消息下发给B端就完事了,这也是大家最希望看到的结果。如果仅仅这样处理,那系统会常常因为这个环节丢消息,而且非常严重。我们需要考虑以下几种情况。第一,对方不在线怎么办。第二,在移动网络下,信号经常会不稳定,比如乘坐地铁过隧道,信号会中断,会导致消息没有成功到达对端。如何保证消息可靠抵达?

1.当知道对端不在线的情况下,将消息存在服务器,等待客户端下次登陆来拉取。

2.对于没推成功的情况,服务器增加重推的机制,客户端收到消息后给服务器回复确认,服务器取消后续推送。

新增的逻辑引入新的复杂度,需要解决。

1.要确保成功将消息存储在服务器,如果存储失败,算是丢失消息。这样就要对存储失败的情况做检测。一种是明确知道存失败了,另一种是后端服务超时,不知道有没有存成功。存储失败可以重试,存储超时也可以简单认为是存储失败,再重试。只要保证多次存储同一消息是幂等操作就可以,防止存了两条。

2.对于重推,服务器要实现重推逻辑,把推送操作加到定时器里面,同时缓存这条消息。超时未收到客户端的确认就再推一次。由于网络原因或者客户端卡住,会导致推送的消息到达了客户端,但是客户端的确认一直没有到达服务器,导致服务器推送了多次消息,所以客户端需要对消息做重复消息的过滤。其次是多次推送后,客户端一直没有回复确认,这个可能是网络原因,客户端真没收到,也可能客户端收到了,客户端的确认还在路上,但是已经到了服务器重推次数,服务器决定要不要将消息存储到服务器?鉴于客户端实现了消息过滤机制,此处可以简单地存储消息到服务器。这就走1的逻辑。后续客户端再上线时拉服务端存储的消息,并做重复过滤。能保证消息不丢失。

3.既然会拉取之前存储在服务器的消息,那拉取完成之后需要将服务器存储的消息删除,这一步客户端在确认收到消息后再发删除请求即可。否则每次都会拉一遍,耗费流量,而且消息多了会导致登陆后的收消息流程越来越卡,由于有过滤机制,不会出现重复消息显示。

上述是推的方式实现消息可靠送达的复杂度。之间还有些逻辑没包含进来,比如push。客户端没收到消息应该改推push。那这样一来推push的情况就有很多。公司之前的老系统是采用推的方式,我们在这一块踩过很多坑,服务端的实现逻辑也相当复杂,各种判断,包括存消息到服务器,重推消息给客户端,推push给客户端,考虑多设备问题,根据客户端的确认做重推取消等等。个人看法是:相信我,如果这样做,后果很严重,你会因频繁的消息丢失问题沉浸在复杂的代码逻辑中无法自拔,甚至,开始怀疑人生。

接下来分析下拉消息的实现方式。

A  -> SERVER ->  B

B <--> SERVER

如果说推的方式是一步到位,那拉消息的实现方式分为两步。第一,A将消息发送到服务器,服务器存储这条消息,并发送一个通知给客户端B,告诉他有消息来了,快来拉取。第二,客户端来拉取这条消息,收到后删除服务器的这条消息。同样的问题,有两点需要注意。第一,网络原因导致通知没到对端,第二,对方不在线怎么办?如何保证消息可靠抵达?

拉的方式下,可以先将消息存储到服务器,再来给发送者和接收者推通知。如果消息存储失败,就可以简单回复消息发送失败给发送者,让发送者手动重发。对于后续流程,如下:

1.如果对方不在线,就不推送通知,直接结束消息发送流程,等待后续对方上线拉消息。这里就不用考虑存储消息失败的情况了,因为存储步骤在之前已保证ok。

2.对方在线,如果通知推送失败怎么处理?对于没推成功的情况,不再重推,等待下次上线拉消息!没错,就是这么暴力和任性。

如此可能出现的问题是消息乱序。客户端可以根据消息在服务端的生成时间排序,可以解决这个问题。就是会出现消息突然跳跃顺序。

在实现中,客户端拉消息应该是按照msgid范围拉一批消息,而且在服务端的实现中,msgid要保证递增,无重复。客户端重新联网后应先保证处理拉服务器消息的流程先走完,再处理新的消息通知。防止新的消息打乱上次的拉取逻辑,中间出现丢消息的情况。

另外一个问题是服务器连续推过来n条消息通知,客户端是不是应答这n条消息通知,去拉n次?因为客户端一次会拉一批消息,或许处理第一条的消息通知就已经把后续的新消息都拉下来了,后面的拉取就成了重复动作,会导致消息拉重复了。这种问题也好解决,从服务器拉取回来后,判断最大msgid是否比收到的通知中msgid要大,如果是,就忽略小的通知,不拉。如果拉到的最大msgid要比通知里的msgid小,就应该继续拉取。当然,客户端对消息的重复过滤逻辑还是要有的。

这样的做法是在网络交互上,多了一步通知和拉取,耗费一些客户端的流量。服务端的实现逻辑复杂度大大降低,客户端需要多处理一些逻辑。

这两种方案,我个人倾向于拉的方式。然后其中有几个技术实现细节后续再写。比如如何保证在分布式环境下msgid连续递增不重复,如何保证客户端对消息的排序,消息同步的具体方案,服务端对消息的存储等。

总体而言,推的方案,服务端需要处理复杂的逻辑,客户端需要处理的相对较少。拉的方案,服务端需要处理的逻辑比较简单,客户端需要配合做一些保证。对于消息可靠的保证方面,个人倾向于拉的方案,更靠谱。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,682评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,277评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,083评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,763评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,785评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,624评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,358评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,261评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,722评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,900评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,030评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,737评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,360评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,941评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,057评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,237评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,976评论 2 355

推荐阅读更多精彩内容