背景

CRM系统,销售用的时候感觉整个系统的主动性不够高。待办事项、预警、消息提醒等都没有特别明显的弹窗提示,所以有了这次改造。
原先SSE的方案,每秒钟会进行一次和服务器的交互:

  • 不够灵活,没有必要每1秒问一下有没有消息
  • 新消息不会弹窗提醒
  • 打开多个标签页的时候,其中一个更新已读信息,不会同步给其他的页面

HTTP keep-alive Vs Websocket

  • 两者都是为了减少TCP的三次握手,四次挥手次数,即在一次TCP连接中做更多的事情
  • HTTP keep-alive
    • 在一次TCP连接中,进行多次HTTP的请求,但是这些请求都是无连接和无状态的。
      • 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间;
      • 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
      • keep-alive 可以改善这种特性,在一次TCP连接中可以持续发送多份数据而不会断开连接。通过使用keep-alive机制,避免了建立或者重新建立连接的次数。
    • 所以HTTP虽然开启 keep-alive,每一次请求还是独立的,需要每次都将身份信息放在Header中,告诉服务端,并且需要客户端发起。
  • Websocket
    • 通过第一个 HTTP 请求建立了 TCP 连接之后,之后的交换数据都不需要再发 HTTP 了,使得这个连接变成了一个真正的长连接,直到断开。
    • 双向的通信,可以由服务端发送也可以由客户端发送消息。

通信

  • 每次建立连接时,客户端告诉服务端这个Websocket实例是为谁而建(当前登录的ID),服务端将实例推入一个列表放入内存中。
  • 在有新消息时,服务端(python websockets)向客户端推送消息。
  • 客户端获取新消息对象,包括类型和内容,加入本地的状态中(Redux中原有的消息列表),如果点击查看则发送已读消息像服务端,然后服务端广播已读结果,将同一个用户各个标签页的消息列表都进行更新。

最终效果

同步的消息弹窗

四个标签页同时更新

同步的线索消息

四个标签页同时更新