幾個重要的概念
- Connector: jetty網絡接口的封裝,用于監聽網絡連接配接
- SelectorManager:底層selector封裝,管理網絡事件,主要是向底層selector注冊感興趣的網絡事件,并從selector中輪詢出準備好的事件
- EndPoint:socket的封裝,用于底層網絡的讀寫,一旦網絡讀寫準備好,會調用相應的connection的handle方法
- Connection:請求的抽象,比如解析請求的http協定,并調用servlet 容器,依賴EndPoint
見圖

幾個重要的線程
1) Acceptor線程
- task:org.eclipse.jetty.server.AbstractConnector.Acceptor
- 數量設定:setAcceptors(Math.max(1,(Runtime.getRuntime().availableProcessors()+3)/4));見SelectChannelConnector構造函數
- 觸發時機:見SelectChannelConnector(AbstractConnector).doStart()
- 執行線程:QueuedThreadPool中的線程
- 執行邏輯
-
- 輪詢SelectChannelConnector.accept(int acceptorID)
- 以阻塞的方式擷取連接配接請求
- 一旦獲得連接配接,調用ConnectorSelectorManager.register(SocketChannel channel)
-
- 向SelectorManager$SelectSet 内部的_changes隊列中添加該事件(有新的連接配接)
- 喚醒selector
2)Selector 線程
- task:匿名内部類(new Runnable(){......})
- 數量設定:在jetty.xml中配置
- 觸發時機:見SelectChannelConnector$ConnectorSelectorManager(SelectorManager).doStart()
- 執行線程:QueuedThreadPool中的線程
- 執行邏輯
-
- 輪詢SelectorManager$SelectSet.doSelect()
- 從_changes隊列擷取感興趣的事件
-
- 如果是EndPoint類型(讀寫事件)
-
- 如果已在selector中注冊過,則更新selection key, 否則向selector注冊
- 如果是ChannelAndAttachment類型
-
- 如果關聯的SocketChannel已連接配接,則向selector注冊讀事件
- 否則注冊連接配接事件
- 如果是SocketChannel類型(連接配接事件)
-
- 則向selector注冊讀事件//key = channel.register(selector,SelectionKey.OP_READ,null);
- 執行個體化SelectChannelEndPoint //createEndPoint(channel,key);
- 調用SelectChannelEndPoint.schedule()
-
- 調用SelectChannelConnector$ConnectorSelectorManager.dispatch(Runnable task)将請求扔給QueuedThreadPool(存放在内部jobs隊列)
- 如果是ChangeTask類型
-
- 直接執行
- 如果是Runnable
-
- 直接丢給QueuedThreadPool
- 運作selector.select擷取準備好的SelectionKey,周遊SelectionKey
-
- 如果key無效則去更新
- 如果有事件發生則調用SelectChannelEndPoint.schedule()
- 調用selector.selectedKeys().clear()
3)Worker線程
- task:匿名内部類(new Runnable(){......})
- 數量設定:在jetty.xml中配置
- 觸發時機:QueuedThreadPool.startThread
- 執行線程:QueuedThreadPool中的線程
- 執行邏輯:
-
- 輪詢從jobs隊列取job(通常是SelectChannelEndPoint的匿名内部類(new Runnable(){......}))
- 然後執行job.run(通常是SelectChannelEndPoint.handle())
-
- 調用SelectChannelConnector$SelectChannelHttpConnection(AsyncHttpConnection).handle()
-
- HttpParser.parseAvailable()(不斷調用parseNext讀取請求的内容)處理請求
- flush内容
- 如果過程中存在寫阻塞,會調用SelectChannelEndPoint.scheduleWrite()或者直接調用updateKey()往_changes隊列中添加寫事件
線程關系見圖
小結(請求處理流程)
- Acceptor線程負責監聽連接配接,一但有連接配接過來,寫入changes隊列
- Selector輪詢changes隊列,将隊列中的感興趣事件往selector中注冊,并從selector中查出準備好的網絡事件,一旦有準備好的網絡事件,通過調用endpoint.schedule()将task丢入線程池的jobs隊列
- Work線程會從jobs隊列取出任務,然後執行
- 上面的3組線程全來自QueuedThreadPool中的線程