首页 > 代码库 > Jetty 9 Connector及Server类的一些源码分析 #1

Jetty 9 Connector及Server类的一些源码分析 #1

本文的源码基于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的数量。