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就可以了。