天天看点

最佳实践:消息服务中如何多线程共享一个LongPolling

背景知识:

mns提供了longpolling类型的receivemessage的方法,只需要在receivemessage的时候把waitsecond设为一个1-30之间的数就可以了。使用longpolling可以让request一直挂在server上,等到有message的时候才返回,在保证了第一时间收到消息的同时也避免用户发送大量无效request。longpolling也是mns的推荐用法。

longpolling是需要挂http层的长连接在server上,而对于server来说,http层的长连接的资源是比较有限的。为了避免受到一些恶意攻击,所以mns对单用户的longpolling连接数是有限制的。

问题描述:

有一些用户在单台机器上开了上百个线程同时访问mns server获取消息,遇到队列中没有消息的时候,单台机器上就挂了上百个longpolling的request。如果用户还同时使用了比较多的机器,那么这些用户就可能会需要同时发上千个longpolling的请求。

这种情况下,用户在发longpolling的request的时候,就会比较容易遇到: mns的server直接返回“消息不存在”,而不是request一直挂在server端等待消息。

这会导致用户不能得到预期的longpolling的效果。有一些用户是在一个while循环里面做不停的longpolling请求而没有做一些异常处理,然后一夜醒来发现发出了极大量的请求。

解决方案:

在开了上百个线程同时访问的情况下,如果队列里已经没有消息了,那么其实不需要上百个线程都同时挂longpolling。只需要有1-n个线程挂longpolling就足够了。挂longpolling的线程在发现队列里有消息时,可以唤醒其他线程一起来取消息以达到快速响应的目的。

附件是一个使用messagereceiver获取消息的bestpractice。所有取消息的线程,都是new了一个messagereceiver,然后使用receiver.receivemessage来获取消息。

receiver内部做了longpolling的排他机制,只要有一个线程在做longpolling,那么其他线程只需要wait就可以了。

limitedlongpolling.zip