即时通讯上手必备知识点
很多人在初次接触即时通讯时,会因为一些知识盲区,对技术或者原理的理解不到位,影响工作进度。我将我个人对即时通讯的理解整理出来,希望能帮到更多的人更好地理解即时通讯。
一、什么是即时通讯?
通俗地说,即时通讯就是收发消息,即客户端和服务端可以相互通信。典型的产品有微信、qq、企业微信、钉钉等,另外还包括电商中的客服等。即时通讯一般只是作为一个基础的能力,跟不同的业务功能结合实现不同的产品。
二、什么是长连接?
很多的应用层协议在传输层使用的都是TCP协议(如http、websocket),TCP协议是面向连接的。面向连接通俗地说就是在正式通信之前必须先建立连接(三次握手),结束之后需要释放连接(四次挥手)。http是短链接,每个请求结束后都释放连接。websocket是长连接,连接建立后会一直保持,之后的通信都使用该连接。
三、什么是协议?
以前总有这样的疑惑,协议是什么人制定的?我们写的代码是怎么样支持这些协议的?协议是在计算机发展的过程中,不断总结经验,最终形成的大家一致认可的约定。协议一般都会设计到客户端和服务端,它规定了客户端和服务端的通信方式,统一了交互的消息体。有了协议,就有了规范,大家不需要商量,只需要都按照协议中规定的方式去实现客户端或服务端就可以与其他人的产品进行通信。比如我们也可以基于tcp协议,设计一个自己的应用层协议,只要规定好消息体,客户端与服务端能够相互识别就可以了。
四、什么是websocket协议?
websocket是一个应用层的协议。初学者可能特别疑惑websocket和socket通信什么关系。大学时学到过socket通信的知识,但是至今也不知道那到底是什么。其实socket通信就是个统称,它包括了传输层的tcp协议和udp协议。很多编程语言都支持socket通信,指的是该语言可以使用tcp、udp实现通信功能。而websocket协议则属于应用层协议,它是在socket通信的基础上实现的,具体使用的是tcp协议。具体websocket协议内容可自行查阅。即时通讯不一定是使用websocket协议实现。
五、什么是心跳?为什么要有心跳?
消息通信是需要经过很多层的网络设备的,而很多的网络设备(不论软硬件)出于安全考虑或性能考虑在连接超出一定空闲时间后会强行断开。比如nginx或即时通讯服务端。即时通讯是需要一直保持长连接的,这样才能保证消息实时地推送到各端。因此有了心跳机制,就是如果连接连续空闲几秒或1分钟就主动发一条消息来保证连接的状态。具体心跳的内容有ping-pong也有1-2等非常随意。
六、如何实现一个即时通讯服务端?
借助通信框架比如netty,使用websocket协议或直接用tcp协议监听某个端口,实现一个消息处理器。只要客户端使用同样的协议发送消息到服务端,服务端能解析,服务端能够推送消息到客户端,客户端可以解析就完成了。
七、即时通讯主要功能点介绍
- 单聊:个人与个人的聊天,A发消息到服务端,服务端转发消息到B。
- 群聊:群成员A发一条消息到服务端,服务端将消息转发到其他群成员。
- 窗口管理:新建窗口、删除窗口、窗口排序(根据最后一条消息的时间排序)、消息免打扰、窗口置顶等
- 群管理:新建群、解散群、添加群成员、移除群成员、移交管理员等
八、即时通讯注意点介绍
- 表设计:即时通讯在表设计时不能太拘泥于数据库范式,必要的数据该冗余的要适当冗余,保证读取数据时的效率。
- 表索引:索引的考虑不仅是考虑单表,还要考虑分库分表的情况,时刻考虑大数据量情况下的效率问题。
- 数据库锁:需要充分考虑数据库锁问题,尽量避免锁冲突的情况。比如我们为了读效率,最后一条消息在窗口表里做了冗余,即A与B的最后一条消息会同时保存到A的窗口里和B的窗口里,代码逻辑是发送消息先修改自己的窗口再修改对方的窗口。如果双方同时在发消息,A修改了自己的窗口,想要去修该B的窗口,而B也修改了自己的窗口想要去修改A的窗口,这样就产生了死锁。
- 消息体设计:由于即时通讯会有大量的消息通讯,所以消息体应尽量短小,这样有利于整体的服务性能。
- 群聊已读未读:这是一个难点。场景是这样的,1000人的群,一个人发一条消息,想要知道该消息有哪些人读了,哪些人没读。比较容易想到的思路是发1条消息,存1000条数据,记录每个人的已读状态。可想而知,这种写扩散的恐怖。另一种方案是记录群内每个人读到的消息号,已读消息号比该消息号小的人就认为是未读的。这种方案要比上一个方案好很多。充分利用了消息的时序性。