作者回复: 整体上没啥大问题哈,首次拉取可以不带时间戳,默认服务端就获取最新的N条即可。
另外时间戳是服务端应用服务器生成的么?多服务器间的时钟差异能接受吗?也可以考虑搭建一套全局的“时间相关的序号生成器”来生成消息ID,使用消息ID作为拉取的cursor,这样时间生成上也相对稳定一些。
作者回复: 这个可能是个结果不是个原因,可能微信产品的设计上就是不想支持多终端消息漫游,所以消息不需要长时间存储在服务端。
作者回复: 第一个问题如果容量超限被淘汰掉仍然取大于版本号的消息下推的话可能会导致消息漏推。比如:客户端当前版本号是1,接下来的消息是2,3,4,假如2被淘汰,那么只会下推3和4,导致2漏推。
第二个问题,是的,离线消息按照用户维度来存储,发送方和接收方都会存,因为发送方也可能有多台设备。
作者回复: 出于可靠性考虑,一般来说服务端接收到消息不管接收方是否在线都会先存到离线存储中,同步再进行消息在线推送,如果接收方不在线或者在线推送失败,等下次接收方再次上线时会从这个离线存储中获取消息进行补推。
作者回复: 是的,推拉结合是一种不错的折中方式。
作者回复: 是的,对于支持多设备同时登陆的场景,用户上线建立长连时是以uid + 设备id 为维度来记录和连接的映射的,所以发消息时携带设备id,服务端就可以区分出具体是用户的哪个设备发送的,下推时就可以区别处理了。
作者回复: 延迟加载能够一定程度缓解突发峰值流量,但对于持续高流量缓降作用有限。可以从提升写入能力角度去考虑,比如写合并。
作者回复: 多终端漫游目前也是有比较成熟的解决方案呀,技术上并不存在问题。
作者回复: 1. mac和手机同时登陆能够同步离线消息这个特性应该上了没多久吧,目前也仅仅是同步一段时间的离线消息,并不是能完全同步所有消息的。
2. 支持一台设备同步到另一台的前提是需要人工干预,不是自动的,实际上是把一台设备的消息打包发送给另一台。
并不是说这种实现方式不好,看个人的需求程度。如果你希望能够随时随地通过任意终端都能看到所有的历史聊天,那微信目前的方案可能存在一定的问题。
作者回复: 返回的header标识告知客户端这个消息是一个压缩过的打包消息,客户端接收到之后对body解压就可以啦。
作者回复: 离线消息不多的情况下,建议打包压缩后一次性推送,如果消息很多,分批也是可以的。离线消息的下推和在线消息的下推不冲突,可以并行的,接收端根据携带的版本号比对来更新收到的最新版本号就可以,一般都是收到一条端上判断后就进行一次更新。
作者回复: 推拉结合没问题的,历史消息的存储如果后续请求量增加的话,最好有会话和最近联系人两个维度,”空间换时间“冗余一点,这样查询联系人的时候性能好一些。
作者回复: 是的,离线库包括所有应该同步给这个用户设备的消息和信令。如果不考虑消息多终端同步的情况是没问题的,类似目前微信的机制,应该就只是有一个离线库。对于多终端消息同步的场景,比如一个新设备要查看和某人的所有消息,这个时候离线库针对接收人的设计就不太方便进行查询了。
作者回复: 也是可以的,递增id的问题是如何保证任何情况下这个id能够连续递增,否则可能不太好做消息连续性检查。
作者回复: 看具体业务场景吧,http轮询实现比较简单,但是资源消耗会多一些,如果有一定的研发能力,可以考虑基于mqtt进行简单的改造来实现,另外,websocket也是一个不错的选择。
作者回复: 有的信令不是消息维度的,比如删除某一个会话,或者删除所有消息等等,这些信令不适合存储在索引表里。另外,索引表是会话维度的,而获取离线消息实际上是需要用户维度的所有消息,所以通过索引表来获取离线消息会比较麻烦和低效。
作者回复: 业务上能接受的话是可以的呀,微博消息箱早期也是没有离线消息buffer的,逐步演进后后慢慢加起来的。