Jetty9原始碼剖析 - Connector元件 - SelectorManager
轉載自ph0ly:http://www.ph0ly.com
一、概念
SelectorManager是選擇器管理器,它主要完成連線接入時的Selector選擇,以及控制ManagedSelector完成一系列的操作(例如EndPoint和Connection的建立,以及讀寫事件的註冊)
二、繼承體系
通常我們用的是ServerConnectorManager,ServerConnectorManager會完成一些簡單的操作,大部分核心邏輯還是在SelectorManager。可以看到SelectorManager是具有生命週期的
三、總體架構
四、原始碼剖析
1. 建構函式
可以看到SelectorManager第一個建構函式會用當前JVM可用處理器數/2,+1的目的是防止為0,也就是最少保證1個,正常是可用處理器數/2,作為selector的數量
Executor、Scheduler使用的是ServerConnector傳入的(ServerConnector文章有講解)
2. 啟動
按照之前分配的selector數量,建立ManagedSelector,並將其他們放到容器託管,並啟動容器中的所有物件(super.doStart),包括ManagedSelector
newSelector會直接建立ManagedSelector,並將當前執行任務策略工廠傳入(稍後EPC會專門講解這部分知識)
3. 接受連線
首選選擇一個Selector,然後在新的執行緒執行連線接受,接受邏輯將會在ManagedSelector文章中介紹
4. 選擇Selector
這個方法是SelectorManager選擇ManagedSelector核心的方法
預設情況,SocketChannel不是null,因此會根據當前ip地址的最後一個值來對選擇器數量取模,選出一個candidate1,作為預選擇的ManagedSelector,而candidate2則是直接輪詢選一個
通常我們希望同一個客戶端的連線儘量就在同一個selector上面,防止多核資料汙染(這裡大家可以思考下為什麼?)
但是有些客戶端是一個代理,可能會將很多客戶端的請求轉發過來,那其實拿到的ip地址是同一個,這個時候我們還將同一個ip的落到同一個Selector上面,那這個Selector壓力就很大了,所以這裡會看這個candidate1選出來的ManagedSelector是否註冊過過多的Channel(超過candidate2的兩倍),那就會使用輪詢選擇出來的candidate2作為選擇器,這其實是一種優化
另外值得注意的是,當candidate1為null的時候,直接返回candidate2,這種情況是使用Selector來接受連線的場景,使用者使用ServerConnector的時候配置的
4. 建立EndPoint、Connection
建立accepted其實就是上面實際呼叫的連線接受,最終調到了ServerConnector,由ServerConnector配置完成後觸發SelectorManager分發邏輯
newEndPoint建立一個SelectChannelEndPoint
newConnection會使用當前容器中的工廠來建立連線,預設是HttpConnectionFactory,將會建立一個HttpConnection
endPointOpened會觸發SelectChannelEndPoint.onOpen
onEndPointOpened會將當前建立的EndPoint加入到ServerConnector的_endpoints列表中
endPointClosed邏輯相似,這裡不在贅述
五、總結
SelectorManager是一個管理器,邏輯相對還是比較簡單,不過對於實現來說,還是有點小繞,讀者如果還想更加細節的理解,還是需要下來追下程式碼,這裡只是把總體核心的思路理清楚了。後面的文章會帶領大家來看下ManagedSelector如何實現資料的讀寫,以及EPC在這裡發揮的作用,請持續關注~