通訊中大量消息廣播的設計和優化 原 薦

消息廣播場在網絡通訊應用還是普遍存在,如遊戲中玩家狀態通知,聊天和公共消息發送等,但在面對大量業務消息廣播的情況可能會面臨一些性能上的問題需要處理;畢竟大量業務不僅在消息序列化上非常損耗CPU,在網絡IO讀寫上因過於頻繁也會引起大量的損耗,如果沒有處理好的情況還是非常影響整全服務性能。

消息廣播場景

一般的設計都是把消息先寫入會話中,然後會話內部進行消息轉化成協議數據最終通過Socket發送出去。這種設計不好的地方在於業務消息比較複雜,廣播的會話數量規模比較大的情況那那整個消息協議數據轉換就非常損耗性能!爲什麼一般這樣設計呢,因爲這樣內部轉換協議對Buffer的控制相對比較容易可控,只需要關心自己會話的消息協轉換髮送回收即可。

廣播應用優化

通過把協議轉換前置,然後再把Buffer轉到會話再由Socket發送出去,這樣做的好處非常明顯就是在大量廣播消息的時候性能非常出色,因爲無論廣播多少個會話只需要協議轉換一次就可以。不過問題也非常明顯,由於Buffer是應用者寫入並共享到不同會話中,這樣就導致Buffr不受內部管制,這樣框架總體性能就不好控制。

整合優化

實際服務應用中,兩種情況都會同時存在,不管誰的重權大小在設計只要傾向一邊那框架都很難在性能上發揮着優勢,畢竟你無法控制上層的應用所面對的情況和應用者的行爲。爲了更好的控制着性能,所以在實現這些基礎功能組件的時候這兩種情況都要有所考慮。

由於轉換協議是一樣的,可以把協議轉換抽象出來,然後在發送消息的時候進行一個閥值判斷;當超過閥值的時候就先轉換消息然後再把buffer寫入到會話中,如果沒超過就由會話內部通過轉換器處理buffer.這樣在通訊中的buffer就可以管控起來,不過對於後者來說由於buffer可以進行共享發送,那在管理上就比較麻煩可以通過發送完成計數來處理;不過由於網絡的不可控制這種控制非常困難(最簡單的方法是內存塊複製到單獨的會話buffer中後回到池中,對於c#這些來說個人建議直接放棄對這一塊的管理,畢竟在大量廣播下已經降低了很多協議轉換的開銷)。

Socket寫入數據層面的優化

對於C#語言來說Socket的Send方法還是比較損耗性能的,如果每秒要向1000個連接廣播10條消息,在正常設計的情況那就意味着觸發10000次的Socket的Send操作。雖然這個數量在現有的硬件資源來說並不會存在什麼壓力,但如果10000個連接或發送的密度更大呢?如果把這方面的損耗壓減下來,留給業務處理那不是一件更好的事情!

在會話內部引用一個消息隊列,發送的消息先寫入隊列,然後通過批量的方式把多個消息寫入Buffer中,在發送完成後繼續監測隊列;發送完成和消息進入會話隊列時會存在一個狀衝突的過程,需要處理好之間的狀態確保隊列消息轉換的一致性即可(使用定時器方式批量寫入發送延時不好控制,特別是會話量比較大的情況下,不建議使用)。通過合併發送在大量小消息的情況下可以達到更高的帶寬利用率和低IO讀寫量,從而讓整體性能更出色。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章