當前位置:首頁 » 操作系統 » netty40源碼

netty40源碼

發布時間: 2022-11-01 18:10:08

A. Netty 源碼解析 ——— ChannelConfig 和 Attribute

嗯,本文與其說是ChannelConfig、Attribute源碼解析,不如說是對ChannelConfig以及Attribute結構層次的分析。因為這才是它們在Netty中使用到的重要之處。

在 Netty 源碼解析 ——— 服務端啟動流程 (下) 中說過,當我們在構建NioServerSocketChannel的時候同時會構建一個NioServerSocketChannelConfig對象賦值給NioServerSocketChannel的成員變數config。

而這一個NioServerSocketChannelConfig是當前NioServerSocketChannel配置屬性的集合。NioServerSocketChannelConfig主要用於對NioServerSocketChannel相關配置的設置(如,網路的相關參數配置),比如,配置Channel是否為非阻塞、配置連接超時時間等等。

NioServerSocketChannelConfig其實是一個ChannelConfig實例。ChannelConfig表示為一個Channel相關的配置屬性的集合。所以NioServerSocketChannelConfig就是針對於NioServerSocketChannel的配置屬性的集合。

ChannelConfig是Channel所需的公共配置屬性的集合,如,setAllocator(設置用於channel分配buffer的分配器)。而不同類型的網路傳輸對應的Channel有它們自己特有的配置,因此可以通過擴展ChannelConfig來補充特有的配置,如,ServerSocketChannelConfig是針對基於TCP連接的服務端ServerSocketChannel相關配置屬性的集合,它補充了針對TCP服務端所需的特有配置的設置setBacklog、setReuseAddress、setReceiveBufferSize。

DefaultChannelConfig作為ChannelConfig的默認實現,對ChannelConfig中的配置提供了默認值。

接下來,我們來看一個設置ChannelConfig的流程:
serverBootstrap.option(ChannelOption.SO_REUSEADDR, true);
我們可以在啟動服務端前通過ServerBootstrap來進行相關配置的設置,該選項配置會在Channel初始化時被獲取並設置到Channel中,最終會調用底層ServerSocket.setReuseAddress方法來完成配置的設置。
ServerBootstrap的init()方法:

首先對option和value進行校驗,其實就是進行非空校驗。
然後判斷對應的是哪個常量屬性,並進行相應屬性的設置。如果傳進來的ChannelOption不是已經設定好的常量屬性,則會列印一條警告級別的日誌,告知這是未知的channel option。
Netty提供ChannelOption的一個主要的功能就是讓特定的變數的值給類型化。因為從』ChannelOption<T> option』和』T value』可以看出,我們屬性的值類型T,是取決於ChannelOption的泛型的,也就屬性值類型是由屬性來決定的。

這里,我們可以看到有個ChannelOption類,它允許以類型安全的方式去配置一個ChannelConfig。支持哪一種ChannelOption取決於ChannelConfig的實際的實現並且也可能取決於它所屬的傳輸層的本質。

可見ChannelOption是一個Consant擴展類,Consant是Netty提供的一個單例類,它能安全去通過』==』來進行比較操作。通過ConstantPool進行管理和創建。
常量由一個id和name組成。id:表示分配給常量的唯一數字;name:表示常量的名字。

如上所說,Constant是由ConstantPool來進行管理和創建的,那麼ConstantPool又是個什麼樣的類了?

首先從constants中get這個name對應的常量,如果不存在則調用newConstant()來構建這個常量tempConstant,然後在調用constants.putIfAbsent方法來實現「如果該name沒有存在對應的常量,則插入,否則返回該name所對應的常量。(這整個的過程都是原子性的)」,因此我們是根據putIfAbsent方法的返回來判斷該name對應的常量是否已經存在於constants中的。如果返回為null,則說明當前創建的tempConstant就為name所對應的常量;否則,將putIfAbsent返回的name已經對應的常量值返回。(注意,因為ConcurrentHashMap不會允許value為null的情況,所以我們可以根據putIfAbsent返回為null則代表該name在此之前並未有對應的常量值)

正如我們前面所說的,這個ConstantPool<ChannelOption<Object>> pool(即,ChannelOption常量池)是ChannelOption的一個私有靜態成員屬性,用於管理和創建ChannelOption。

這些定義好的ChannelOption常量都已經存儲數到ChannelOption的常量池(ConstantPool)中了。

注意,ChannelOption本身並不維護選項值的信息,它只是維護選項名字本身。比如,「public static final ChannelOption<Integer> SO_RCVBUF = valueOf("SO_RCVBUF");」👈這只是維護了「SO_RCVBUF」這個選項名字的信息,同時泛型表示選擇值類型,即「SO_RCVBUF」選項值為Integer。

好了,到目前為止,我們對Netty的ChannelOption的設置以及底層的實現已經分析完了,簡單的來說:Netty在初始化Channel時會構建一個ChannelConfig對象,而ChannelConfig是Channel配置屬性的集合。比如,Netty在初始化NioServerSocketChannel的時候同時會構建一個NioServerSocketChannelConfig對象,並將其賦值給NioServerSocketChannel的成員變數config,而這個config(NioServerSocketChannelConfig)維護了NioServerSocketChannel的所有配置屬性。比如,NioServerSocketChannelConfig提供了setConnectTimeoutMillis方法來設置NioServerSocketChannel連接超時的時間。
同時,程序可以通過ServerBootstrap或Boostrap的option(ChannelOption<T> option, T value)方法來實現配置的設置。這里,我們通過ChannelOption來實現配置的設置,ChannelOption中已經將常用的配置項預定義為了常量供我們直接使用,同時ChannelOption的一個主要的功能就是讓特定的變數的值給類型化。因為從』ChannelOption<T> option』和』T value』可以看出,我們屬性的值類型T,是取決於ChannelOption的泛型的,也就屬性值類型是由屬性來決定的。

一個attribute允許存儲一個值的引用。它可以被自動的更新並且是線程安全的。
其實Attribute就是一個屬性對象,這個屬性的名稱為AttributeKey<T> key,而屬性的值為T value。

我們可以通過程序ServerBootstrap或Boostrap的attr方法來設置一個Channel的屬性,如:
serverBootstrap.attr(AttributeKey.valueOf("userID"), UUID.randomUUID().toString());
當Netty底層初始化Channel的時候,就會將我們設置的attribute給設置到Channel中:

如上面所說,Attribute就是一個屬性對象,這個屬性的名稱為AttributeKey<T> key,而屬性的值為T value。
而AttributeKey也是Constant的一個擴展,因此也有一個ConstantPool來管理和創建,這和ChannelOption是類似的。

Channel類本身繼承了AttributeMap類,而AttributeMap它持有多個Attribute,這些Attribute可以通過AttributeKey來訪問的。所以,才可以通過channel.attr(key).set(value)的方式將屬性設置到channel中了(即,這里的attr方法實際上是AttributeMap介面中的方法)。

AttributeKey、Attribute、AttributeMap間的關系:
AttributeMap相對於一個map,AttributeKey相當於map的key,Attribute是一個持有key(AttributeKey)和value的對象。因此在map中我們可以通過AttributeKey key獲取Attribute,從而獲取Attribute中的value(即,屬性值)。

Q:ChannelHandlerContext和Channel都提供了attr方法,那麼它們設置的屬性作用域有什麼不同了?
A:在Netty 4.1版本之前,它們兩設置的屬性作用域確實存在著不同,但從Netty 4.1版本開始,它們兩設置的屬性的作用域已經完全相同了。

若文章有任何錯誤,望大家不吝指教:)

聖思園《精通並發與Netty》

B. netty 一個server有可以建多少個連接

1. 應用在netty建連接的過程中做了耗時的事;
因此我先mp了應用的線程,看到一切正常,boss線程看起來非常空閑;
2. backlog太小;
首先問了下開發代碼里有沒有設置過backlog,開發告訴我沒設置過,於是我翻了下netty的源碼確認下默認值,看到backlog的默認值為讀取自系統的/proc/sys/net/core/somaxconn,於是查了下系統的這個值,確認系統的這個值已經是調整過的,設置為了2048,然後確認了系統上的tcp_max_syn_backlog是4096,也就是最後work的會是2048(為什麼是這樣具體可見 這篇文章 ),也就是說應該是夠的。
用ss -s觀察連接的狀況,看到的是synrecv是0,也印證了上面的不是backlog的問題。
到這一步就徹底傻眼了,不知道該用什麼方法排查了,於是開始一堆的google,看到的各種說解決新建連接並發低的解決辦法,除了調整backlog外,主要是以下兩種:
1 關閉tcp_tw_recycle,嘗試了(話說這里充分體現了」病急亂投醫「的心態,其實我自己都不相信改這參數有用,但想著只是改下參數這種小代價的事,還是試試吧),沒任何作用;
2 關閉window scaling ,也嘗試了,一樣沒任何作用;
查到這個階段覺得自己已經無法理解了,於是求助了廠內內核團隊對網路這塊比較精通的同學,然後又求助了「神」,「神「幫忙看了會後,說主要的問題是現在是每epollWait喚醒一次,只建了一個連接,這導致在大量新建連接請求並發的時候,效率不夠高,因此我翻了下代碼,發現我本機上看到的代碼不是這樣的,我本機上看到的netty代碼在epollWait喚醒後,是會嘗試一直去accept的,但這個應用使用的netty確實不是這樣,於是查了下應用的jar包庫,發現裡面有兩個版本的netty(一個是3.2.1.Final,一個是3.6.3.Final),3.2.1確實是每次epollWait後就處理一個,於是通知開發同學把3.2.1去掉,滿心期待的認為應該是好了,等開發更新好了後,自己也確認了一次epollWait喚醒後會連續處理很多個建立連接的請求,但悲催的還是沒解決問題,具體的netty在這塊的改造感興趣的同學可以看看NioServerSocketPipelineSink這個類(重點看select喚醒後)…
到這步,就徹底郁悶了,話說其實到這步的時候我已經被這個問題困擾了2天多了,於是只好繼續google,發現又有提到打開syn cookies的建議,於是嘗試了下,竟然真的work了,打開了這個參數後新建連接的並發請求輕松超過100+了。
到此以為已經解決了,但很快開發給我反饋,整個集群開啟了這個參數後,連接確實是能建上了,但客戶端出現了發了請求後,等不到任何響應的現象,當時還不確定伺服器端到底有沒有收到請求,於是只好又先關閉了這個參數(話說這個我到現在都不明白為什麼這個參數打開後,會出現發請求沒響應的現象,求高人解答)。
盡管還是沒解決,但畢竟有進展,有的進展就是打開了syn cookies後連接就能建上,而syn cookies只有在backlog滿了後才會生效,那也就是說還是backlog滿了,從kern的日誌也能確認syn cookies確實是work了,到這步就覺得詭異了,明明netty用的默認值就是somaxconn,而每秒新建40多個連接,且boss線程還很空閑的情況下顯然不應該出現backlog滿的現象,這個時候仔細看了下本機查看的netty代碼,才發現我看的是netty 4的代碼,而應用用的是netty 3.6.3,悲催,趕緊把netty 3.6.3的代碼撈下來看了,才發現在3.6.3里backlog的默認值處理時不一樣的,在3.6.3里默認值是50,不是netty寫的默認值,是java本身,50那估計真的不一定夠,於是就通知開發在代碼里先強制設置下backlog為1000。
在開發改代碼的過程中,還有一個懷疑點想確認,就是既然是backlog滿了,為什麼看到的synrecv會是0呢,於是再用netstat -na | grep [port] | grep SYN_RECV -c統計了下,結果發現值基本一直是64,java層面默認設置的是50,linux會將這個值調整為大於這個值的2的n次冪的值,那也就是64,好吧,看到這就徹底可以確定真的是因為backlog太小了造成的(只是話說我不明白為什麼ss -s統計出來的synrecv會是0呢,求高人解答)。
等開發改完代碼重新發布後,稍微增加了點引流測試了下,輕松支撐每秒200+,客戶端建立連接後發請求獲取響應也完全ok,問題到此宣告解決。
題外話: 這應用之所以會比較容易出現較多的synrecv,主要是因為手機網路通常是不太穩定的,另外一個原因是這種對外的都很容易帶來攻擊,而當時剛好這個應用前面的一個用來防syn flood的由於有bug臨時關閉了,所以問題暴露的比較明顯。
從這個折騰了4天的case的排查過程,大家可以看到其實如果一開始我仔細確認過應用用的netty版本和我本機看的代碼是不一致的話,估計很快就會排查出原因就是backlog值太小造成的,所以說折騰了這么多天其實也是自己造成的,這個告訴自己,以後排查問題的時候一定要對出現問題的應用所在的環境更加清楚的確認。
ps: 最後再多啰嗦幾句,從這個case還能看到的是netty的版本其實在細節上是一直在改進的,就像這個case里的不同版本的netty在處理連接事件喚醒上,還有backlog的默認值上,所以我一直很強調,對於需要存活很多年的軟體而言,選擇一個使用范圍較廣的開源軟體是非常重要的,如果自己開發,也許短期能超越,但放到三年、五年這樣的范圍來看,通常是很難和開源軟體去抗衡的(原因是商業公司沒多少人會專注在一個領域做三五年的,而開源界這樣的人實在是多,說實話,這種case看過太多),所以如果覺得你能做的比開源軟體好,還不如去幫助已有的(當然,如果這個領域目前完全沒有什麼使用面較廣的、靠譜的,那自己做一個開源是挺好的),軟體的可持續發展能力(除非是一次性軟體、做的玩的或就玩個一兩年的)是非常非常重要的。

C. netty 如何阻塞主線程

1 netty本身的 worker線程的個數是根據CPU來的,直接在 worker線程里做業務邏輯處理不好么?
2 如果不想並發,修改源碼,讓worker線程個數為1,就沒有並發了,這一點跟redis一樣的,redis單線程的處理能力貌似也夠用了,redis的作者是這么說的。
3 為啥要自定義多個業務邏輯線程?netty本身的worker線程拿到消息後就可以處理了啊

D. Netty核心組件之NioEventLoop(一)

在接下來幾篇文章,我會通過Netty的源碼深入講解NioEventLoop的實現機制。
特別說明:基於4.1.52版本的源碼

先來看下NioEventLoop的類關系圖和重要的屬性,對其有一個整體的感知,便於後面詳細分析。

首先來看NioEventLoop的構造函數

默認情況下,會創建MPSC,即多生產者單消費者的隊列,這里最終會用到JCTools庫,這里不過多介紹,感興趣的可以自己去了解。

如果設置了優化開關(默認優化選項是開啟的),則通過反射的方式從Selector中獲取selectedKeys和publicSelectedKeys,將這兩個成員設置為可寫,通過反射,使用Netty構造的selectedKeySet將原生JDK的selectedKeys替換掉。
我們知道使用Java原生NIO介面時,需要先調Selector的select方法,再調selectedKeys方法才可以獲得有IO事件准備好的SelectionKey集合。這里優化過後,只通過一步select調用,就可以從selectedKeySet獲得需要的SelectionKey集合。
另外,原生Java的SelectionKey集合是一個HashSet,這里優化過後的SelectedSelectionKeySet底層是一個數組,效率更高。

EventLoop的職責可以用下面這張圖形象的表示

下面詳細解析:

每次循環,都會檢測任務隊列和IO事件,如果任務隊列中沒有任務,則直接返回SelectStrategy.SELECT;如果任務隊列中有任務,則會調用非阻塞的 selectNow 檢測有IO事件准備好的Channel數。

nextScheledTaskDeadlineNanos 方法返回下一個將要被執行的定時任務的截止時間

NioEventLoop的定時任務隊列是一個優先順序隊列,隊列中存儲的是ScheledFutureTask對象

通過ScheledFutureTask的 compareTo 方法可以看出,優先順序隊列中的元素是以任務的截止時間來排序的,隊首元素的截止時間最小,當截止時間相同時,以任務ID排序,ID小的排在前面。

當定時任務ScheledFutureTask執行後,會根據 periodNanos 的取值決定是否要將任務重新放回隊列。從netty的注釋可以清晰看到:

看下ScheledFutureTask的 run 方法

當任務的執行時間還未到,則判斷任務是否已經取消,如果已取消則移除任務,否則重新加入隊列。對於只執行一次的任務,執行完了不會再放回隊列。其他的任務,則根據 periodNanos 的類型,重新計算截止時間,重新放回隊列,等待下次調度。
定時任務的優先順序隊列到此介紹完畢,接著看NioEventLoop的 run 方法

在調用 select 之前,再次調用 hasTasks() 判斷從上次調用該方法到目前為止是否有任務加入,多做了一層防護,因為調用 select 時,可能會阻塞,這時,如果任務隊列中有任務就會長時間得不到執行,所以須小心謹慎。
如果任務隊列中還是沒有任務,則會調用 select 方法。在這個方法中會根據入參 deadlineNanos 來選擇調用NIO的哪個select方法:

到這里,可能有人要問了: 在上面的方法中,如果調用了Java NIO的無參的 select 方法,就會進入阻塞,除非檢測到Channel的IO事件,那麼在檢測到IO事件之前,加入到任務隊列中的任務怎麼得到執行呢?

好,你想,在檢測到IO事件之前,可以退出阻塞的方法是什麼?對,調用 wakeup 方法。那麼我們來搜一下NioEventLoop中有調用Selector的 wakeup 方法的地方嗎:

還真搜到了,再看一下這個方法被調用的地方

看到SingleThreadEventExecutor的 execute 方法了嗎,就是說在調 execute 方法,向EventLoop提交任務時,會將EventLoop線程從Java NIO的select阻塞中喚醒。

到這里,NioEventLoop的run方法的職責之一:檢測Channel的IO事件就講解完畢。

至於IO事件的處理以及任務隊列中任務的處理會在後面的文章中解析,敬請期待。

在本文中,對Netty的NioEventLoop進行了深入的解讀,並且詳細講解了它的三大職責之一:檢測Channel的IO事件的機制。
NioEventLoop是Netty最核心的概念,內部運行機制很復雜,在接下來的兩篇文章中會繼續分析。

E. 《Netty實戰NettyINACTION》epub下載在線閱讀,求百度網盤雲資源

《Netty實戰》(諾曼·毛瑞爾(Norman Maurer))電子書網盤下載免費在線閱讀

資源鏈接:

鏈接:

提取碼: pyuk

書名:Netty實戰

作者:諾曼·毛瑞爾(Norman Maurer)

譯者:何品

豆瓣評分:7.5

出版社:人民郵電出版社

出版年份:2017-5-1

頁數:276

內容簡介:

編輯推薦


- Netty之父」Trustin Lee作序推薦

- 阿里巴巴中間件高級技術專家為本書中文版作序推薦

- 系統而詳細地介紹了Netty的各個方面並附帶了即用型的優質示例

- 附帶行業一線公司的案例研究

- 極實用的Netty技術書

無論是構建高性能的Web、游戲伺服器、推送系統、RPC框架、消息中間件還是分布式大數據處理引擎,都離不開Netty,在整個行業中,Netty廣泛而成功的應用,使其成為了Java高性能網路編程的卓絕框架。

Netty的現Tech Lead Norman在本書中循序漸進地講解了Netty的各個關鍵部分,在看完本書後,你不但可以熟練地使用Netty來構建以上系統,並且還可以避免很多常見的陷阱。

無論是想要學習Spring 5 、Spark、Cassandra等這樣的系統,還是通過學習Netty來構建自己的基於Java的高性能網路框架,或者是更加具體的高性能Web或者游戲伺服器等,本書都將是你的超強拍檔。

本書中文版基於Netty4.1.9做了修訂,希望本書能夠給你帶來一個接近完美的閱讀體驗,並能幫到你。

內容提要

本書是為想要或者正在使用Java從事高性能網路編程的人而寫的,循序漸進地介紹了Netty各個方面的內容。

本書共分為4個部分:第一部分詳細地介紹Netty的相關概念以及核心組件,第二部分介紹自定義協議經常用到的編解碼器,第三部分介紹Netty對於應用層高級協議的支持,會覆蓋常見的協議及其在實踐中的應用,第四部分是幾個案例研究。此外,附錄部分還會簡單地介紹Maven,以及如何通過使用Maven編譯和運行本書中的示例。

閱讀本書不需要讀者精通Java網路和並發編程。如果想要更加深入地理解本書背後的理念以及Netty源碼本身,可以系統地學習一下Java網路編程、NIO、並發和非同步編程以及相關的設計模式。

本文僅用於學習和交流目的,不代表非同步社區觀點。非商業轉載請註明作譯者、出處,並保留本文的原始鏈接。

作者簡介:

Norman Maurer,是蘋果公司的資深軟體工程師,同時也是Netty的核心開發人員。

Marvin Allen Wolfthal,是Dell Services的顧問,他使用Netty實現了多個任務關鍵型的企業系統。

何品,目前是淘寶的一名資深軟體工程師,熱愛網路、並發、非同步相關的主題以及函數式編程,同時也是Netty、Akka等項目的貢獻者,活躍於Scala社區,目前也在從事GraphQL相關的開發工作。

F. 為什麼學習集合關系

集合可以說是學習 Java 中最重要的一塊知識點了,無論做任何業務系統,集合總是最為基礎的那塊 API。我第一次接觸集合,是在我大三的時候,那時候去面試,面試官問我:你了解過集合嗎?可惜那時候沒什麼項目經驗,所以基本沒有了解過,因此也錯失了機會。

到了現在,我已經工作了5年了,也做過了大大小小十幾個項目。這些項目中有簡單的 SSH 項目,也有分布式高並發的復雜項目。無論在哪個項目中,關於集合的時候是必不可少的。但我現在慢慢回顧過去做的項目,我發現自己使用到的集合還是比較少,基本上只有:ArrayList、HashSet、HashMap 這幾個。

但當我開始深入去了解 JDK 集合的整個體系時,我發現之前的我了解得確實非常淺顯。例如關於 List 的實現有 ArrayList、LinkedList、Vector、Stack 這四種實現,但我們很多時候只是直接使用 ArrayList,而不是根據場景去選擇。

1.學習集合源碼,能夠讓我們使用得更加准確。

當我們深入學習了源碼之後,我們就能夠了解其特性,從而能夠根據我們的使用場景去做出更好的選擇,從而讓我們的代碼運行效率更高。

我們舉一個最簡單的例子 —— ArrayList 和 LinkedList。它們兩者底層採用了完全不同的實現方式,ArrayList 使用數組實現,而 LinkedList 則使用鏈表實現。這使得 ArrayList 的讀取效率高,而 LinkedList 的讀取效率低。但因為 LinkedList 採用鏈表實現,所以其增加和刪除比較方便,而 ArrayList 則比較麻煩。所以 ArrayList 比較適合用於讀場合較多的情況,而 LinkedList 比較適合用於增加、刪除較多的場景。

我們來看另外一個例子 —— HashMap 和 TreeMap。乍看之下,他們都是 Map 集合的實現,但是它們內部有著截然不同的實現。HashMap 是 Map 介面的哈希實現,其內部使用了鏈表和紅黑樹實現。而 TreeMap 是 Map 介面的有序實現,其內部使用了紅黑樹實現。所以 HashMap 一般用來存儲 key、value 的實現,而 TreeMap 常用存儲需要排序的元素。

除了我們舉的這兩個例子之外,還有許多這樣的例子,比如:HashMap 與 LinkedHashMap 的區別,HashMap 與 WeakHashMap 的區別,LinkedList 與 ArrayDeque 的區別。

2.學習集合源碼,讓我們學習經典的設計方式。

在集合的整個架構設計中,其類繼承體系非常簡單,但是卻很經典。例如:Collection 介面設計了集合通用的操作,每個集合類型都有對應的介面(List、Set、Map),每個集合類型都有對應的抽象實現(AbstractList、AbstractSet、AbstractMap)等。
當我們閱讀這些源碼的時候,這種設計方式都會潛移默化地影響我們。當我們之後自己設計一個框架的時候,我們就會不知不覺地用上去。所有的創新都是從模仿開始的,所以閱讀優秀的集合源碼很重要。

3.幫助通過面試,獲得更高的薪酬。

現在關於集合的原理是 Java 工程師面試的家常菜,幾乎每一個企業的面試都會問到。如果你連這塊東西都沒搞清楚,那麼你就不需要聊其他了,直接被幹掉。而如果你能將整個 Java 集合體系清晰地說出去,並且舉一反三地對比,那麼你就比其他人優秀了。

4.學習經典的數據結構。

還記得大學在學習數據結構的時候,我們都是從理論上去記憶。但是當我看完集合源碼之後,我忽然發現——JDK集合源碼簡直就是數據結構的最佳實踐呀!

數據結構中最為基礎的幾個結構為:順序表、單鏈表、雙向鏈表、隊列、棧、二叉堆、紅黑樹、哈希表。這些所有的實現都能在 JDK 集合的實現中找到。例如:ArrayList 就是順序表的實現,LinkedList 就是雙向鏈表的實現,Stack 就是棧的實現,HashMap 就是哈希表的實現,TreeMap 就是紅黑樹的實現,PriorityQueue 就是二叉堆的實現。

5.所有技術的基礎

集合源碼可以說是 JDK 所有源碼中最為簡單的一塊了,而且也是其他所有源碼的基礎。例如線程池的源碼中也大量使用了阻塞隊列,如果你連集合源碼都搞不懂,那麼線程池的源碼你也肯定看不懂的。而如果線程池源碼看不懂,那麼你 netty 的源碼也看不懂的。netty 源碼看不懂,那麼 bbo 的源碼也是看不懂的。
看明白了么?這些技術都是一換扣著一換的。如果你想要後續學習更加快速,那麼你就必須把最基礎的東西學明白了。如果連最基礎的東西都沒學明白,就直接去學其他更復雜的東西,最後只會越來越難,最終逃脫不了放棄的命運。

讀到了這里,我相信你也對集合的重要性有了不一樣的認識。那麼接下來一段時間,就讓我和你一起來深入學學集合源碼吧。如果覺得讀了有用,那麼請給我一個贊吧。你們的贊是我繼續寫下去的動力!

G. 這幾個大數據GitHub項目,太強了吧

大家好,我是 夢想家 Alex 。我們都知道 github 對於程序員們而言,就是一個巨大的「聚寶盆」,上面不僅有很多優質的開源項目,還有很多熱愛開源分享的開發者。但如何從浩如煙海的寶藏中,篩選出適合自己的優質項目呢?本期內容,我就為大家推薦幾個我認為還不錯的大數據學習必備的 牛 X 項目,希望大家看完有所收獲。

首推 heiying 的 BigData-Notes,該項目目前已經有高達 10.2K 的star,正如該倉庫的介紹上簡短幾個字:大數據入門指南。這個項目也是我認為目前 最適合初學者學習和參考的項目

為什麼說這個項目適合大數據初學者呢,可以通過觀察項目的介紹文檔,該項目包含了大數據學習必須要掌握的幾種組件,包括 Hadoop,Hive,Spark,Flink,Kafka,Zookeeper,Flume,Sqoop,Azkaban,以及 Scala 函數式編程語言的教程 ,可謂是非常的系統全面

我們再藉助谷歌插件 Octotree 觀察項目的結構,可以看到該項目主要分為 code,notes,pictures,resources 四個目錄

其中 code 目錄主要用來存放各個組件使用相關的代碼,正如統計的結果一樣,這個項目中 Java 代碼佔了 94.8%,Scala 佔了 5.2%,所以對於喜歡用 Java 編寫代碼的小夥伴們來說,這是一個不容錯過的寶藏學習機會。

notes 部分主要存放相關組件的介紹和使用文檔,其中 installation 子目錄主要存放了相關組件編譯,以及在Linux環境下各個組件的安裝,單機/集群環境搭建的教程,我看過了內容,介紹的非常清晰詳細。

另外兩個目錄 pictures resources 就不做過多介紹了,一個是存放相關的圖片教程,另一個是存放編寫的代碼中所需要用到的文本文件。

這個項目同樣給力,是由 BAT 高級大數據架構師 王知無 創建的,該項目目前也已經斬獲高達 5.2k star,是為數不多, 集基礎學習和進階實戰 於一體的優質項目。

該項目按照大數據不同階段的學習,所列舉不同的文章干貨

大數據開發基礎篇

大數據框架學習篇

大數據開發實戰進階篇

大數據開發面試篇

從不同的分類足以見 王老師 的用心。同時,王知無前輩也是 51CTO 上的認證講師,來看看官方的介紹 。

相信很多同學在學習大數據的過程中,不清楚 Java 需要學習哪些內容,掌握到什麼程度,這個時候完全可以借鑒王老師的這個倉庫內容。

同時,學習這個倉庫的內容,可以學習到作者作為架構師本身對於 JVM,分布式理論和基礎,大數據框架基石之網路通信Netty,以及各個框架的源碼學習,可謂「 真.寶藏倉庫

除了基礎的理論學習以外,還有大量實戰性的內容可以借鑒參考

以及大量的面試題,還有自己從零到大數據專家一路走來的心路歷程,學習路徑指南,和自己對於技術學習的一些深入思考,相信大家拜讀過後一定能收獲滿滿,

這個項目比較特殊,是一個國外開發者開源的項目,英文翻譯過來的意思是「很棒的大數據」,實際上呢~他列舉的是很多很棒的大數據框架、資源和其他很棒的精選列表。靈感來自 awesome-php awesome-python awesome-ruby hadoopecosystemtable big-data 。目前也已經斬獲 10.2K 的 star,非常強勢。

為了方便閱讀,我將其全部翻譯成中文進行展示。

我們跳轉到 分布式編程,可以看到很多我們熟悉的技術,例如 Flink,Spark,Pig,MapRece 等等 ....

亦或者「分布式文件系統」,我們所熟知的 HDFS,Ku,GFS ...

點擊對應的鏈接,可以跳轉到對應的官方介紹頁,方便我們減少搜索成本,快速了解不同領域大數據常用的技術組件,為我們之後做技術調研省了很多的時間。

讓我厚顏無恥的夾帶一下「私貨」。這是我在今年年初的時候,創建的一個倉庫,目前也已經有了快 200 的star 。從資歷和star的數量顯然不能跟前面幾個大佬相比,但卻是我第一次花費了大量精力,將一個項目像孩子一樣進行「培養」。

為了設計一個好看的圖標,還花了不少的精力。設置不同媒體平台的徽標設計,還參考了像 JavaGuide 這樣的頭部項目,也算是在親力親為的這個過程中,學到了不少東西。


可以放點內容給大家show一下

另外,我還開設了「福利」專欄,將自己學習過程中收集到的學習干貨毫無保留地分享給大家,方便大家獲取。


顯而易見,這個是專注於 flink 學習的開源項目,其中的內容包含Flink 入門、概念、原理、實戰、性能調優、源碼解析等等,目前已經斬獲了 10.5k 的 star,非常強勢。

其維護的開發人員也是非常用心負責,一路跟隨 flink 的版本,不停的在維護更新 。

同時,主要維護者 zisheng 還將 flink 的研究做到了極致,不僅有 flink 成體系的博客鏈接,還有對應的源碼系列。

還自己創建了專欄《從1到100深入學習Flink》,並將大家學習過程中有疑惑的地方解決過程統一記錄下來,方便有需要的同學查看。雖然是付費的星球專享,但我覺得是真的值!感興趣的話大家可以自行去了解。

H. 如何實現Netty框架中伺服器端的消息推送

netty框架是用在伺服器端,客戶端是嵌入式編程,通過自定義的tcp通信協議進行連接的,現在需求是這樣的,伺服器端只是用來和客戶端進行通信,現在有第三方如微信端進行支付成功後在資料庫里生成了一條數據,表示要往某個客戶端發送指令,以下兩種方式可供參考:
1、微信端生成通訊指令後調用TCP端的介面(負責通訊程序和資料庫交互的),在介面程序中通過定義Socket連到通訊程序伺服器端,根據通道編號去發送,但是這種會導致伺服器端的tcp客戶端連接變得更多。

2、直接在netty框架中定義了scheleAtF。
當然也可藉助第三方工具來完成推送。例如極光推送,極光推送具有以下功能:
1、多種消息類型
開發者可以輕松地通過極光發送各個移動平台的系統通知,還可以在控制台編輯多種富文本展示模板; 極光還提供自定義消息的透傳,客戶端接到消息內容後根據自己的邏輯自由處理。
2、用戶和推送統計
完整的消息生命周期查詢,並且可以形成「推送報表」與「用戶統計報表」呈現給開發者,用來觀察推送的效果和應用發展趨勢。
3、簡訊補充
通過極光後台推送APP通知消息,對於一些重要又不能遺漏的信息可以調用極光簡訊的後台對未收到的客戶端發送簡訊通知,保證消息的可靠性。
4、A/B 測試
合理的推送能夠激活用戶,提高用戶粘性,使用A/B分組測試的科學方法,根據測試反饋的結果,幫助開發者選擇最優化的推送方案。
5、極光推送安全包
為金融、新聞、政務及其他對推送安全要求極高的客戶提供安全嚴謹、穩定可靠的信息推送解決方案
6、可定製的私有雲
對於安全性要求更高,希望推送數據和系統存儲在自己伺服器的客戶,及個性化需求需要定製開發的,性能更高要求的,或者想擁有自己推送平台的甚至要求源碼授權二次開發的開發者,極光提供全功能的私有雲解決方案。
深圳市和訊華谷信息技術有限公司(極光 Aurora Mobile,納斯達克股票代碼:JG)成立於2011年,是中國領先的開發者服務提供商,專注於為開發者提供穩定高效的消息推送、一鍵認證以及流量變現等服務,助力開發者的運營、增長與變現。同時,極光的行業應用已經拓展至市場洞察、金融風控與商業地理服務,助力各行各業優化決策、提升效率。

熱點內容
app什麼情況下找不到伺服器 發布:2025-05-12 15:46:25 瀏覽:714
php跳過if 發布:2025-05-12 15:34:29 瀏覽:467
不定時演算法 發布:2025-05-12 15:30:16 瀏覽:131
c語言延時1ms程序 發布:2025-05-12 15:01:30 瀏覽:167
動物園靈長類動物配置什麼植物 發布:2025-05-12 14:49:59 瀏覽:738
wifi密碼設置什麼好 發布:2025-05-12 14:49:17 瀏覽:150
三位數乘兩位數速演算法 發布:2025-05-12 13:05:48 瀏覽:399
暴風影音緩存在哪裡 發布:2025-05-12 12:42:03 瀏覽:545
access資料庫exe 發布:2025-05-12 12:39:04 瀏覽:632
五開的配置是什麼 發布:2025-05-12 12:36:37 瀏覽:367