天天看點

最佳實踐:消息服務中如何多線程共享一個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