華爲電信軟件技術架構演進
Java NIO框架在技術變遷中起到的關鍵做用
C和C++主導的第一代架構
Spring + Struts + Tomcat 的第二代架構
Java高性能服務端
以SOA爲中心的第三代架構
當垂直應用愈來愈多,應用之間交互不可避免,將核心業務抽取出來,做爲獨立的服務,逐漸造成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。
如何整合異構系統,實現高效企業集成,也是一個巨大的挑戰,此時,企業服務總線(ESB)是個不錯的選擇。
以分佈式、雲化爲核心的第四代架構
基於X86架構的廉價硬件 + 分佈式軟件的模式在互聯網行業獲得了大規模應用,分佈式架構日趨成熟。
傳統SOA架構中的一些缺陷逐步暴露,例如企業集成總線ESB是實體總線,性能線性擴展能力有限;硬件負載均衡器的壓力愈來愈大,不斷擴容致使硬件成本增長;隨着業務規模的不斷增加,傳統的數據庫、配置中心等逐漸成爲單點瓶頸等。
咱們須要經過新的分佈式架構來解決電信軟件面臨的成本高、性能沒法線性增加等問題,以分佈式技術爲核心構建的華爲分佈式中間件應用而生,它主要包括以下組件:
1) 高性能、低時延的分佈式服務框架;
2) 分佈式消息隊列MQ;
3) 分佈式緩存;
4) 分佈式數據庫訪問中間件,支持跨庫操做,支持異構數據庫;
5) 軟負載SLB;
6) 分佈式日誌採集和檢索(Flume + ELK);
7) 分佈式實時流式計算框架;
8) 分佈式消息跟蹤系統;
9) 其它……
第四代技術架構以分佈式、雲化爲核心,相比於前三代架構,它的核心特性以下:
1) 採用分佈式技術構建,全部的中間件都沒有單點,支持線性增加和彈性伸縮;
2) 以微服務架構爲核心,打造電信領域的DevOps(結合華爲PaaS平臺);
3) 由傳統的SOA Governance 向微服務治理和自治演進,提高服務治理效能;
4) 分佈式日誌採集 + 實時流式計算框架,更快的故障定界,提高大規模、分佈式系統中的運維效率;
5) 業務和數據的拆分,分而治之,經過分佈式中間件服務向業務屏蔽拆分細節;
6) 架構雲化帶來的巨大優點:資源池提高硬件利用率、DevOps提高開發和運維效率、應用和服務的自動彈性伸縮、應用和服務故障自動恢復、高HA、自動化運維等。
【以Netty爲表明的NIO框架】
傳統同步阻塞通訊面臨的主要問題以下:
1) 性能問題:一鏈接一線程模型致使服務端的併發接入數和系統吞吐量受到極大限制;
2) 可靠性問題:因爲I/O操做採用同步阻塞模式,當網絡擁塞或者通訊對端處理緩慢會致使I/O線程被掛住,阻塞時間沒法預測;
3) 可維護性問題:I/O線程數沒法有效控制、資源沒法有效共享(多線程併發問題),系統可維護性差
從上圖咱們能夠看出,每當有一個新的客戶端接入,服務端就須要建立一個新的線程(或者重用線程池中的可用線程),每一個客戶端鏈路對應一個線程。當客戶端處理緩慢或者網絡有擁塞時,服務端的鏈路線程就會被同步阻塞,也就是說全部的I/O操做均可能被掛住,這會致使線程利用率很是低,同時隨着客戶端接入數的不斷增長,服務端的I/O線程不斷膨脹,直到沒法建立新的線程。
同步阻塞I/O致使的問題沒法在業務層規避,必須改變I/O模型,才能從根本上解決這個問題。
基於Reactor模型統一調度的長鏈接和短鏈接協議棧,不管是性能、可靠性仍是可維護性,均可以「秒殺」傳統基於BIO開發的應用服務器和各類協議棧,這種指標差別本質上是一種技術代差。
【從Java 原生NIO到NIO框架】
JAVA 原生NIO類庫的複雜性
如今咱們總結一下爲何不建議開發者直接使用JDK的NIO類庫進行開發,具體緣由以下:
(1)NIO的類庫和API繁雜,使用麻煩,你須要熟練掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等;
(2)須要具有其餘的額外技能作鋪墊,例如熟悉java多線程編程。這是由於NIO編程涉及到Reactor模式,你必須對多線程和網路編程很是熟悉,才能編寫出高質量的NIO程序;
(3)可靠性能力補齊,工做量和難度都很是大。例如客戶端面臨斷連重連、網絡閃斷、半包讀寫、失敗緩存、網絡擁塞和異常碼流的處理等問題,NIO編程的特色是功能開發相對容易,可是可靠性能力補齊的工做量和難度都很是大;
(4)JDK NIO的BUG,例如臭名昭著的epoll bug,它會致使Selector空輪詢,最終致使CPU 100%。官方聲稱在JDK1.6版本的update18修復了該問題,可是直到JDK1.7版本該問題仍舊存在,只不過該BUG發生機率下降了一些而已,它並無被根本解決。
Netty是業界最流行的NIO框架之一,它的健壯性、功能、性能、可定製性和可擴展性在同類框架中都是數一數二的,它已經獲得成百上千的商用項目驗證,例如Hadoop的RPC框架avro使用Netty做爲底層通訊框架;不少其餘業界主流的RPC框架,也使用Netty來構建高性能的異步通訊能力。
經過對Netty的分析,咱們將它的優勢總結以下:
1) API使用簡單,開發門檻低;
2) 功能強大,預置了多種編解碼功能,支持多種主流協議;
3) 定製能力強,能夠經過ChannelHandler對通訊框架進行靈活地擴展;
4) 性能高,經過與其餘業界主流的NIO框架對比,Netty的綜合性能最優;
5) 成熟、穩定,Netty修復了已經發現的全部JDK NIO BUG,業務開發人員不須要再爲NIO的BUG而煩惱;
6) 社區活躍,版本迭代週期短,發現的BUG能夠被及時修復,同時,更多的新功能會加入;
7) 經歷了大規模的商業應用考驗,質量獲得驗證。在互聯網、大數據、網絡遊戲、企業應用、電信軟件等衆多行業獲得成功商用,證實了它已經徹底可以知足不一樣行業的商業應用了。
【Netty的非阻塞I/O調度模型】
【高性能的序列化框架】
在華爲軟件,對於序列化框架的選擇,咱們遵循以下幾個原則:
1) 序列化後的碼流大小(網絡帶寬的佔用);
2) 序列化&反序列化的性能(CPU、內存等資源佔用);
3) 是否支持跨語言(異構系統的對接和開發語言切換);
4) 高併發調用時的性能,是否隨着線程併發數線性增加。
基於上述的指標,目前最經常使用的選擇是:Google的ProtoBuf和Apache的Thrift。
Netty原生提供了對ProtoBuf序列化框架的支持,它的優勢以下:
1) 在谷歌內部長期使用,產品成熟度高;
2) 跨語言、支持多種語言,包括C++、Java和Python;
3) 編碼後的消息更小,更加有利於存儲和傳輸;
4) 編解碼的性能很是高;
5) 支持不一樣協議版本的前向兼容;
6) 支持定義可選和必選字段。
Thrift相對複雜一些,須要將編解碼框架從Thrift中剝離出來,而後利用Netty編解碼框架的擴展性定製實現,在此再也不贅述。
【收斂的Reactor線程模型】
若是使用Tomcat等作Web容器,爲了保證吞吐量和性能,HTTP線程池的最大線程數每每配置爲1024。
在系統運行期間咱們Dump線程堆棧,發現大量的線程競爭,這不只致使HTTP協議棧的性能降低,更影響其它業務處理線程的執行效率。
【其它優化】
爲了進一步提高性能,下降時延,咱們還採用了其它一些優化措施,總結以下:
1) 使用Netty 4的內存池,減小業務高峯期ByteBuf頻繁建立和銷燬致使的GC頻率和時間;
2) 在程序中充分利用Netty提供的「零拷貝」特性,減小額外的內存拷貝,例如使用CompositeByteBuf而不是分別爲Head和Body各建立一個ByteBuf對象;
3) TCP參數的優化,設置合理的Send和Receive Buffer,一般建議值爲64K – 128K;
4) 軟中斷:若是Linux內核版本支持RPS(2.6.35以上版本),開啓RPS後能夠實現軟中斷,提高網絡吞吐量;
5) 無鎖化串行開發理念:使用Netty 4.X版本,天生支持串行化處理;業務開發過程當中,遵循Netty 4的線程模型優化理念,防止人爲增長線程競爭。