网页收发消息是一个常见的系统应用场景,通常我们有两种方式来完成消息的发送,一种是通过客户端来拉取消息,一种是服务端推送消息,到底使用哪种方式好一点呢?
具体使用哪种方式,我们需要根据实际的业务场景来分析,没有绝对正确的方式,只有适不适合。所以,我们分析一下网页端的用户一般都存在哪些应用场景:
我们抛开纯技术实现不谈,只是从解决方案来谈,由于是使用的是网页端,HTTP协议是通过“请求-响应”的方式传递,网页端和服务端之间是没有消息通道的,那么怎么来实现消息的接收呢?
轮询拉取可以说是所有消息的实现方案中最简单的一种,实现起来也非常简单。
大致的实现方法如下:
这种方式最大的优势就是实现非常简单,而且容易理解,早期的聊天室基本都是这种实现方式,我曾经给朋友做过一个答题的系统,有多个终端,每个终端看到的内容需要有所不同,也是使用的这种实现方式。
当然这种实现方式的缺点也是非常明显:
使用这种方式,时效性和效率是矛盾的,我降低timer的间隔时间,就可以提高时效性,但是会降低效率,例如:间隔时间降低到1秒,这种基本就可以趋近于实时了,但是可能300次轮询才会拉到1条消息,有效性只有0.3%了。
所以,由于这个不可调和的矛盾存在,这种解决方案只能适用于一些同时在线用户少,对实时性要求不高的场景中。
如果想要同时保证时效性和效率,其实长连接是一个不错的选择,一般我们的PC端聊天软件都是使用的长连接方式来实现。而网页端的长连接实现方式通常有两种:
FlashSocket就不说了,如果不是网页游戏的话其实很少会用到这个方案来做长连接,它要求用户必须安装了Flash插件。如果是html网页端的话,其实更多会选择WebSocket这种方案,WebSocket的优点非常明显,建立一次握手以后,服务端和网页端就可以双向通信了,摆脱了HTTP的Request-Response的限制,消息的及时性和效率都大幅度的提升了。
但是WebSocket也不是那么简单,其中的坑也非常的多,如何单个生产者推送给多个消费者,如何保证不重复推送,断线以后的重连等等。当然更重要的是,不同的浏览器对于WebSocket的支持可能不同,兼容性也是一大问题,所以使用得并不是很多。
那有没有一种更常用的方法来处理消息的接收呢?
想要建立一条HTTP长轮询的通道,我们需要在浏览器和服务器之间建立一条通知连接。
而这条通知连接不同于普通的HTTP连接,它要有一些特殊性:
怎么来Hold住这个请求呢?
个人认为,长轮询的请求就一直保持对消息队列的数据拉取就行,如果有实时的消息来了,也等到它进入消息队列以后再处理,这样可以防止消息丢失,也可以降低系统的复杂度。
总的来说,网页端的消息接收,用什么方式好呢?拉和推都可以,每种方式有每种方式的优缺点。