本文的源碼基於Jetty9,主要分析了Jetty 的Connector與Server類間在Jetty啟動過程中的一些細節。
Jetty9 對以前的Connector體系進行了重構, 結構與6和7都不同,原有的一些BIO類已經被拋棄。
先看Server 構造函數
public Server(@Name("port")int port) { this((ThreadPool)null); ServerConnector connector=new ServerConnector(this); connector.setPort(port); setConnectors(new Connector[]{connector}); }
將本身傳入ServerConnector構造, 設置connector的port, 並將ServerConnector傳入自身的
Connector數組,保持引用。
Server自身的Connectors數組變量,采用CopyOnWriteArrayList,保證可能的線程操作的安全。
private final List<Connector> _connectors = new CopyOnWriteArrayList<>();
Server啟動類在Jetty.xml中定義,並設置線程池,Handler
<Configure id="Server" class="org.eclipse.jetty.server.Server">
ThreadPool是共享的, Connector與dispatch類都會用到。
Server繼承自HandlerWrapper, HandlerWrapper將handle代理給其裝飾的類,即實際的Handler類,實現Decorator模式。
繼承關系如下:
AbstractHandler
|-AbstractHandlerContainer
|-HandlerWrapper
|-Server
Server的啟動方法是doStart(),該方法先調用上層doStart()方法,然后調用自身Connector數組的中的Connector類的start()方法。
try { super.doStart(); } for (Connector _connector : _connectors) { try { _connector.start(); } catch (Throwable e) { mex.add(e); } }
ServerConnector是Jetty9中主要的Connector實現,負責主要接入處理,此類主要的操作還有Java對接入連接的抽象Connection,
Connection由Connector中設置的工廠類產生,如果沒設置過,默認的工廠類是HttpConnectionFactory。
Connector中還會與另一抽象Selector交互。
描述了ServerConnector繼承關系的類圖:
ServerConnector的繼承層次如下:
下面看一些具體點的代碼:
AbstractLifeCycle start() -> doStart(); 預留了doStart()方法供子類重寫。
|-ContainerLifeCycle doStart()
|-AbstractConnector
|-AbstractNetworkConnector doStart() ->open(); 設置了一個open方法供子類重寫
|-ServerConnector open(); 實現了open方法,打開ServerSocketChannel
AbstractLifeCycle中start()的內容:
try { if (_state == __STARTED || _state == __STARTING) return; setStarting(); doStart(); setStarted(); }
可看到此方法作為一個模板方法,將doStart()的實現留給子類重寫,其自身的doStart()是一個空方法,這種用法在Jetty跟生命周期有關的類很多。
Open方法的內容,隱藏部分不太重要的細節:
if (serverChannel == null) { serverChannel = ServerSocketChannel.open(); InetSocketAddress bindAddress = getHost() == null ? new InetSocketAddress(getPort()) : new InetSocketAddress(getHost(), getPort()); serverChannel.socket().bind(bindAddress, getAcceptQueueSize()); serverChannel.socket().setReuseAddress(getReuseAddress()); _localPort = serverChannel.socket().getLocalPort(); if (_localPort <= 0) throw new IOException("Server channel not bound"); addBean(serverChannel); } serverChannel.configureBlocking(true); addBean(serverChannel); _acceptChannel = serverChannel;
這里的ServerSocketChannel使用的是阻塞模式,
回到 AbstractNetworkConnector 的doStart中:
protected void doStart() throws Exception { open(); super.doStart(); }
方法繼續調用了父類的doStart(), 那么再看父類AbstractConnector的doStart():
protected void doStart() throws Exception { _defaultConnectionFactory = getConnectionFactory(_defaultProtocol); super.doStart(); _stopping=new CountDownLatch(_acceptors.length); for (int i = 0; i < _acceptors.length; i++) getExecutor().execute(new Acceptor(i)); }
此方法設置的默認的ConnectionFactory, 另一個重要概念Acceptor類也是這里出現的。
Acceptor是AbstractConnector的私有內部類,這里用的CountDownLatch是給doStop用的, stop中會計算這個CountDownLatch是否為空,
不為空則會調用CountDownLatch.await等待, 知道Acceptor的線程都停掉才繼續做stop的其他事情。
Acceptor的數量在該類的構造方法中進行初始化,下面是片段:
if (acceptors<=0) acceptors=Math.max(1,(Runtime.getRuntime().availableProcessors()) / 2);
主要計算方式就是最少是1個,是否大於一個要根據CPU數量來,按CPU核心數量/2來計算Acceptor的數量。