Jetty 9 源碼分析 Connector及Server類(一)


本文的源碼基於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的數量。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM