[Chat Service] IM 的时间戳

老师,有几个问题?

1.请问消息是在系统设计图的哪个地方打上的时间戳的。是在服务器端,还是在客户端?客户端我觉得不对,因为那样可以操纵时间戳。如果是后者,如果双方都去的是一个data center,虽然不是一台机但是这个时间上的差别我感觉还可以容忍,还可以有一个标准时间,但是你比如说我人在美国,我家人在国内,这个时候双方难道还要都到路由到同一个数据中心去打时间戳么?我感觉这个underlying的标准时间完全就是拿不到的。

  1. 在客户端上面聊天框消息显示接收的消息肯定是从websocket 推送过来的,自己敲出来的消息是立刻从本地直接就上了聊天框的么?那发出去的消息的时间戳怎么搞来的,先奔服务器上,请求一个时间回来append在这个message上么?

  2. 您上课说的conner case,说的好像就是屏幕聊天框上的显示问题,说发出去的消息本地还要把消息排序一下,按本地时间排个顺序,收到的消息按服务器的时间排个顺序。还是说,这个发送出去的消息的这个时间戳是哪来的,本地的么,还是服务器的?我比较困惑如果发送来的和发出去的时间的基准不一样,怎么把他们犬牙交错的按照正常的问答给表现出来呢?比如说极端情况下,我本地发送的时间都搞成了公元元年,岂不是收到的信息全跑最后面去了。

  1. 采用服务器端的时间。服务器之间的时间是需要经常对表的,有专门的 time server 来保证服务器上的时间都是相对一致的,不需要去同一个数据中心就能打到相对精确的时间戳。Clock drift 的问题是暂时存在的,但没有你说的这么普遍和严重。
  2. 自己的消息可以根据本地时间戳。
  3. 要避免你说的情况,App 可以自己维护时间,而不需要使用操作系统的时间。可以像服务器一样时不时跟时间服务器对一下表就可以了。

老师,我看到还有的说用在对话各方之间使用一个局部全局的单调递增的id作为时间的先后顺序。这种方案和直接用时间戳之间的trade off是什么呢?本质上应该都是一个意思吧。

那如果app自己就可以打上时间戳而且和服务器一样能跟time server进行校准的话,也就是说基本上可以认为时间打的是一致的,那我还是有点迷惑,那为啥还要可以强调说,时间用的是服务器时间呢?这个过程是在客户端打上了个时间戳,到了服务器那边再打个时间戳?

现在接收服务器端是可以打合理的时间戳,那么所谓本地排发送的信息,服务器端排收到的消息,意思就是说在客户端对话框显示,ideally就像merge two sorted list一样,merge成一问一答的效果,是这意思么?

有点不一样。如果对话双方共用同一组单调递增的 ID 的话,会造成双方看到的对话顺序是完全一致的。那么如果双方同时发送,就会有一方看到对方的话跳到自己的话之前。

不一样。因为数据到达服务器是需要时间的。

我们提的方案是自己打的内容按本地时间戳,其他人的内容按服务器时间戳,Sort 一下就好。就是一个 List。

老师,我不知道理解的对不对啊,如果是按照时间戳排序的话,那么一条消息从开始在发送方客户端上,到收件方的服务器上,应该经历的data flow,咱们上课说了会经历发送方app,发送方服务器,收件方服务器(有queue),然后收件方的APP,现在咱们在之前的讨论中一直再说本地时间戳,服务器时间戳。我就比较迷糊了,本地时间戳,发送方打出来的message在本地会为了显示在对话框上,会打一个时间戳,之后发出去了,彻底跟发送方的告别了,那究竟来到了是哪个服务器,发送方服务器,还是收件方服务器上拿到了第二个时间戳,就是您说的这个时候这个消息就变成您恢复中其他人的时间戳的这个服务器时间戳,这个时间戳在哪里打上的?

另外一个问题,我想问,如果这个queue是一个普通的队列,如果出现了丢包(会重新发送么?),或者网络延迟,那么进入队列的时候虽然是虽然靠前,但是其实是之前的消息,会有这种现象发生么?那么这个修正顺序的过程有办法解决么?是靠queue来解决么?还是靠客户端的重新排序解决?而且这个重新排序是base on 时间戳,丢包了的时候,乱序的消息的时间戳是重现按照上一个丢包的时间戳给呢,还是另算时间呢。

抱歉老师,细节有点多,卡了一步,过不去。 您受累。

  1. 本地时间戳不用发给服务器,只需要在本地用来排序对话就好。信息发到服务器之后,服务器就把接收到消息的时间戳打在这个消息上,这个时间戳就一直跟着这条消息发送给了对方。
  2. 在 Queue 里面的信息可能时间戳也是一定程度上乱序的,毕竟是分布式系统。可以考虑在 Queue 里进行一定的顺序调整(用到 priority queue),也可以单纯先进先出。我比较倾向与单纯先进先出,到客户端上再排序,系统简单一点。

这次彻底明白了,谢谢您了啊。