摘要:比如面向連接的功能包發(fā)送接收數(shù)量包發(fā)送接收速率錯誤計數(shù)連接重連次數(shù)調(diào)用延遲連接狀態(tài)等。你要處理的,就是心跳超時的邏輯,比如延遲重連。發(fā)生異常后,可以根據(jù)不同的類型選擇斷線重連比如一些二進制協(xié)議的編解碼紊亂問題,或者調(diào)度到其他節(jié)點。
在java界,netty無疑是開發(fā)網(wǎng)絡應用的拿手菜。你不需要太多關注復雜的nio模型和底層網(wǎng)絡的細節(jié),使用其豐富的接口,可以很容易的實現(xiàn)復雜的通訊功能。
和golang的網(wǎng)絡模塊相比,netty還是太過臃腫。不過java類框架就是這樣,屬于那種離了IDE就無法存活的編碼語言。
最新的netty版本將模塊分的非常細,如果不清楚每個模塊都有什么內(nèi)容,直接使用netty-all即可。
單純從使用方面來說,netty是非常簡單的,掌握ByteBuf、Channel、Pipeline、Event模型等,就可以進行開發(fā)了。你會發(fā)現(xiàn)面試netty相關知識,沒得聊。但Netty與其他開發(fā)模式很大不同,最主要的就是其異步化。異步化造成的后果就是編程模型的不同,同時有調(diào)試上的困難,對編碼的要求比較高,因為bug的代價與業(yè)務代碼的bug代價不可同日而語。
但從項目來說,麻雀雖小五臟俱全,從業(yè)務層到服務網(wǎng)關,以及各種技術保障,包括監(jiān)控和配置,都是需要考慮的因素。netty本身占比很小。
本文將說明使用netty開發(fā),都關注哪些通用的內(nèi)容,然后附上單機支持100w連接的linux配置。本文并不關注netty的基礎知識。
網(wǎng)絡開發(fā)中最重要的就是其通訊格式,協(xié)議。我們常見的protobuf、json、avro、mqtt等,都屬于此列。協(xié)議有語法、語義、時序三個要素。
我見過很多中間件應用,采用的是redis協(xié)議,而后端落地的卻是mysql;也見過更多的采用mysql協(xié)議實現(xiàn)的各種自定義存儲系統(tǒng),比如proxy端的分庫分表中間件、tidb等。
我們常用的redis,使用的是文本協(xié)議;mysql等實現(xiàn)的是二進制協(xié)議。放在netty中也是一樣,實現(xiàn)一套codec即可(繼承Decoder或Encoder系列)。netty默認實現(xiàn)了dns、haproxy、http、http2、memcache、mqtt、redis、smtp、socks、stomp、xml等協(xié)議,可以說是很全了,直接拿來用很爽。
一個可能的產(chǎn)品結構會是這樣的,對外提供一致的外觀,核心存儲卻不同:
文本協(xié)議在調(diào)試起來是比較直觀和容易的,但安全性欠佳;而二進制協(xié)議就需要依賴日志、wireshark等其他方式進行分析,增加了開發(fā)難度。傳說中的粘包拆包,就在這里處理。而造成粘包的原因,主要是由于緩沖區(qū)的介入,所以需要約定雙方的傳輸概要等信息,netty在一定程度上解決了這個問題。
每一個想要開發(fā)網(wǎng)絡應用的同學,心里都埋了一顆重新設計協(xié)議的夢想種子。但協(xié)議的設計可以說是非常困難了,要深耕相應業(yè)務,還要考慮其擴展性。如沒有特別的必要,建議使用現(xiàn)有的協(xié)議。
連接管理功能做Netty開發(fā),連接管理功能是非常重要的。通信質(zhì)量、系統(tǒng)狀態(tài),以及一些黑科技功能,都是依賴連接管理功能。
無論是作為服務端還是客戶端,netty在創(chuàng)建連接之后,都會得到一個叫做Channel的對象。我們所要做的,就是對它的管理,我習慣給它起名叫做ConnectionManager。
管理類會通過緩存一些內(nèi)存對象,用來統(tǒng)計運行中的數(shù)據(jù)。比如面向連接的功能:包發(fā)送、接收數(shù)量;包發(fā)送、接收速率;錯誤計數(shù);連接重連次數(shù);調(diào)用延遲;連接狀態(tài)等。這會頻繁用到java中concurrent包的相關類,往往也是bug集中地。
但我們還需要更多,管理類會給予每個連接更多的功能。比如,連接創(chuàng)建后,想要預熱一些功能,那這些狀態(tài)就可以參與路由的決策。通常情況下,將用戶或其他元信息也attach到連接上,能夠多維度的根據(jù)條件篩選一些連接,進行批量操作,比如灰度、過載保護等,是一個非常重要的功能。
管理后臺可以看到每個連接的信息,篩選到一個或多個連接后,能夠開啟對這些連接的流量錄制、信息監(jiān)控、斷點調(diào)試,你能體驗到掌控一切的感覺。
管理功能還能夠看到系統(tǒng)的整個運行狀態(tài),及時調(diào)整負載均衡策略;同時對擴容、縮容提供數(shù)據(jù)依據(jù)。
心跳檢測應用協(xié)議層的心跳是必須的,它和tcp keepalive是完全不同的概念。
應用層協(xié)議層的心跳檢測的是連接雙方的存活性,兼而連接質(zhì)量,而keepalive檢測的是連接本身的存活性。而且后者的超時時間默認過長,完全不能適應現(xiàn)代的網(wǎng)絡環(huán)境。
心跳就是靠輪訓,無論是服務端,還是客戶端比如GCM等。保活機制會在不同的應用場景進行動態(tài)的切換,比如程序喚起和在后臺,輪訓的策略是不一樣的。
Netty內(nèi)置通過增加IdleStateHandler產(chǎn)生IDLE事件進行便捷的心跳控制。你要處理的,就是心跳超時的邏輯,比如延遲重連。但它的輪訓時間是固定的,無法動態(tài)修改,高級功能需要自己定制。
在一些客戶端比如Android,頻繁心跳的喚起會浪費大量的網(wǎng)絡和電量,它的心跳策略會更加復雜一些。
邊界 優(yōu)雅退出機制Java的優(yōu)雅停機通常通過注冊JDK ShutdownHook來實現(xiàn)。
Runtime.getRuntime().addShutdownHook();
一般通過kill -15進行java進程的關閉,以便在進程死亡之前進行一些清理工作。
注意:kill -9 會立馬殺死進程,不給遺言的機會,比較危險。
雖然netty做了很多優(yōu)雅退出的工作,通過EventLoopGroup的shutdownGracefully方法對nio進行了一些狀態(tài)設置,但在很多情況下,這還不夠多。它只負責單機環(huán)境的優(yōu)雅關閉。
流量可能還會通過外層的路由持續(xù)進入,造成無效請求。我的通常做法是首先在外層路由進行一次本地實例的摘除,把流量截斷,然后再進行netty本身的優(yōu)雅關閉。這種設計非常簡單,即使沒有重試機制也會運行的很好,前提是在路由層需要提前暴露相關接口。
netty由于其異步化的開發(fā)方式,以及其事件機制,在異常處理方面就顯得異常重要。為了保證連接的高可靠性,許多異常需要靜悄悄的忽略,或者在用戶態(tài)沒有感知。
netty的異常會通過pipeline進行傳播,所以在任何一層進行處理都是可行的,但編程習慣上,習慣性拋到最外層集中處理。
為了最大限度的區(qū)別異常信息,通常會定義大量的異常類,不同的錯誤會拋出不同的異常。發(fā)生異常后,可以根據(jù)不同的類型選擇斷線重連(比如一些二進制協(xié)議的編解碼紊亂問題),或者調(diào)度到其他節(jié)點。
功能限制 指令模式網(wǎng)絡應用就該干網(wǎng)絡應用的事,任何通訊都是昂貴的。在《Linux之《荒島余生》(五)網(wǎng)絡篇》中,我們談到百萬連接的服務器,廣播一個1kb消息,就需要1000M的帶寬,所以并不是什么都可以放在網(wǎng)絡應用里的。
一個大型網(wǎng)絡應用的合理的思路就是值發(fā)送相關指令。客戶端在收到指令以后,通過其他方式,比如http,進行大型文件到獲取。很多IM的設計思路就是如此。
指令模式還會讓通訊系統(tǒng)的擴展性和穩(wěn)定性得到保證。增加指令可以是配置式的,立即生效,服務端不需要編碼重啟。
穩(wěn)定性保證網(wǎng)絡應用的流量一般都是非常大的,并不適合全量日志的開啟。應用應該只關注主要事件的日志,關注異常情況下的處理流程,日志要打印有度。
網(wǎng)絡應用也不適合調(diào)用其他緩慢的api,或者任何阻塞I/O的接口。一些實時的事件,也不應該通過調(diào)用接口吐出數(shù)據(jù),可以走高速mq等其他異步通道。
緩存可能是網(wǎng)絡應用里用的最多的組件。jvm內(nèi)緩存可以存儲一些單機的統(tǒng)計數(shù)據(jù),redis等存儲一些全局性的統(tǒng)計和中間態(tài)數(shù)據(jù)。
網(wǎng)絡應用中會大量使用redis、kv、高吞吐的mq,用來快速響應用戶請求。總之,盡量保持通訊層的清爽,你會省去很多憂慮。
單機支持100萬連接是可行的,但帶寬問題會成為顯著的瓶頸。啟用壓縮的二進制協(xié)議會節(jié)省部分帶寬,但開發(fā)難度增加。
和《LWP進程資源耗盡,Resource temporarily unavailable》中提到的ES配置一樣,優(yōu)化都有類似的思路。這份配置,可以節(jié)省你幾天的時間,請收下!
操作系統(tǒng)優(yōu)化更改進程最大文件句柄數(shù)
ulimit -n 1048576
修改單個進程可分配的最大文件數(shù)
echo 2097152 > /proc/sys/fs/nr_open
修改/etc/security/limits.conf文件
* soft nofile 1048576 * hard nofile 1048576 * soft nproc unlimited root soft nproc unlimited
記得清理掉/etc/security/limits.d/*下的配置
網(wǎng)絡優(yōu)化打開/etc/sysctl.conf,添加配置
然后執(zhí)行,使用sysctl生效
#單個進程可分配的最大文件數(shù) fs.nr_open=2097152 #系統(tǒng)最大文件句柄數(shù) fs.file-max = 1048576 #backlog 設置 net.core.somaxconn=32768 net.ipv4.tcp_max_syn_backlog=16384 net.core.netdev_max_backlog=16384 #可用知名端口范圍配置 net.ipv4.ip_local_port_range="1000 65535" #TCP Socket 讀寫 Buffer 設置 net.core.rmem_default=262144 net.core.wmem_default=262144 net.core.rmem_max=16777216 net.core.wmem_max=16777216 net.core.optmem_max=16777216 net.ipv4.tcp_rmem="1024 4096 16777216" net.ipv4.tcp_wmem="1024 4096 16777216" #TCP 連接追蹤設置 net.nf_conntrack_max=1000000 net.netfilter.nf_conntrack_max=1000000 net.netfilter.nf_conntrack_tcp_timeout_time_wait=30 #TIME-WAIT Socket 最大數(shù)量、回收與重用設置 net.ipv4.tcp_max_tw_buckets=1048576 # FIN-WAIT-2 Socket 超時設置 net.ipv4.tcp_fin_timeout = 15總結
netty的開發(fā)工作并不集中在netty本身,更多體現(xiàn)在保證服務的高可靠性和穩(wěn)定性上。同時有大量的工作集中在監(jiān)控和調(diào)試,減少bug修復的成本。
深入了解netty是在系統(tǒng)遇到疑難問題時能夠深入挖掘進行排查,或者對苛刻的性能進行提升。但對于廣大應用開發(fā)者來說,netty的上手成本小,死挖底層并不會產(chǎn)生太多收益。
它只是個工具,你還能讓它怎樣啊。
0.jpeg
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/11984.html
摘要:比如面向連接的功能包發(fā)送接收數(shù)量包發(fā)送接收速率錯誤計數(shù)連接重連次數(shù)調(diào)用延遲連接狀態(tài)等。你要處理的,就是心跳超時的邏輯,比如延遲重連。發(fā)生異常后,可以根據(jù)不同的類型選擇斷線重連比如一些二進制協(xié)議的編解碼紊亂問題,或者調(diào)度到其他節(jié)點。 在java界,netty無疑是開發(fā)網(wǎng)絡應用的拿手菜。你不需要太多關注復雜的nio模型和底層網(wǎng)絡的細節(jié),使用其豐富的接口,可以很容易的實現(xiàn)復雜的通訊功能。 和...
摘要:是個不太干凈協(xié)議。目前此協(xié)議的受眾的也不僅僅是開發(fā)者。借助協(xié)議進行握手,握手成功后,就會變身為通道,從此與不再相見。如此操作,可以盡量避免普通請求被誤認為協(xié)議。它包含四個事件和兩個動作發(fā)送和關閉。有類似協(xié)議的幀格式,在此不做過多解釋。 WebSocket是一種比較新的協(xié)議,它是伴隨著html5規(guī)范而生的,雖然還比較年輕,但大多主流瀏覽器都已經(jīng)支持。它使用方面、應用廣泛,已經(jīng)滲透到前后端...
摘要:我覺得了解簡歷和面試的技巧可以幫助你更好的去學習重要的知識點以及更好地去準備面試以及面試,說實話,我個人覺得這些東西還挺重要的。在本文里,我將介紹我這段時間里更新簡歷和面試的相關經(jīng)歷。 分享一篇很不錯的文章!本文作者曾經(jīng)寫過《Java Web輕量級開發(fā)面試教程》和 《Java核心技術及面試指南》這兩本書。我覺得了解簡歷和面試的技巧可以幫助你更好的去學習重要的知識點以及更好地去準備面試以...
閱讀 1985·2021-11-22 14:45
閱讀 2592·2021-10-12 10:11
閱讀 767·2021-09-22 10:02
閱讀 1196·2019-08-30 15:55
閱讀 1141·2019-08-30 15:54
閱讀 3247·2019-08-30 15:54
閱讀 1180·2019-08-29 17:16
閱讀 3080·2019-08-28 17:55