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的数量。

时间: 2024-09-20 00:11:34

Jetty 9 源码分析 Connector及Server类(一)的相关文章

Hive源码分析:CLI入口类

说明: 本文的源码分析基于hive-0.10.0-cdh4.3.0. 启动脚本 从shell脚本/usr/lib/hive/bin/ext/cli.sh可以看到hive cli的入口类为org.apache.hadoop.hive.cli.CliDriver cli () { CLASS=org.apache.hadoop.hive.cli.CliDriver execHiveCmd $CLASS "$@" } cli_help () { CLASS=org.apache.hadoop

远哥Amoeba源码分析之:核心类说明

同事喜欢叫我远哥,所以我把这个笔记称为远哥系列,今天有兴趣分析一下Amoeba的源码,并且在此记录一下,并且随时更新.   Amoeba目前一共有三个项目产品,分别是:   Amoeba for MySQL: 为MySQL提供了一种数据库代理的解决方案,可以实现多台MySQL之间的读写分离,具有负载均衡.高可用性.Query过滤.读写分离.可路由相关的query到目标数据库.可并发请求多台数据库合并结果. 在Amoeba上面你能够完成多数据源的高可用.负载均衡.数据切片的功能.   Amoeba

springboot源码分析6-springboot之PropertySource类初探

摘要:本小节重点梳理一下PropertySource类的相关结构以及职责,本文的学习前提是学习了springboot源码分析5-springboot之命令行参数以及原理一文. 在springboot源码分析5-springboot之命令行参数以及原理一文中,我们看到了实例化Source类的时候,会去先实例化其父类SimpleCommandLinePropertySource.SimpleCommandLinePropertySource类的构造函数中直接解析了命令行参数以及值,然后返回封装好的C

springboot源码分析3-springboot之banner类架构以及原理

继续上文的<<springboot源码分析2-springboot 之banner定制以及原理章节>>进行讲解,上一节我们详细详解了banner的三种输出模式.banner的输出模式设置.banner类的架构.SpringApplicationBannerPrinter类.ImageBanner以及TextBanner的处理方式.本小节我们来重点讲解一下各种banner处理类的相关实现逻辑以及设计意图和职责. 1.1 SpringBootBanner类 SpringBootBann

tomcat源码分析-Connector初始化与启动

   一个应用应用服务器的性能很大程度上取决于网络通信模块的实现,因而Connector模块对于tomcat来说是重中之重.从tomcat5开始,默认的连接器实现为Coyote实现(orag.apache.tomcat:tomcat-coyote:7.0.57),本文基于coyote实现会回答如下两个问题:     一个http请求是怎么被tomcat监听到的,会有那些处理:     ajp协议干什么用的. 一.Connector配置     通过对Container的初始化分析,我们很自然的会

Tomcat源码分析----Connector初始化与加载

一个应用服务器的性能很大程度上取决于网络通信模块的实现,因此Connector对于tomcat而言是重中之重.在本章节中以下两个问题会被回答: 一个http请求是怎么被tomcat监听到的,会有哪些处理: 为什么请求可以有需要通过nginx的,也可以不需要nginx的直接请求到tomcat上? 1 Connector配置 通过对Container的初始化分析,我们很自然的会回过头看conf/server.xml中的connector配置.在xml中配置了2个connector. <Connect

springboot源码分析7-环境属性构造过程(上)

使用springboot的目的就是在项目开发中,快速出东西,因此springboot对于配置文件的格式支持是非常丰富的,最常见的配置文件后缀有如下四种:properties.xml.yml.yaml,比如我们在springboot项目根目录中配置了一个application.properties文件,则springboot项目启动的时候就会自动将该文件的内容解析并设置到环境中,这样后续需要使用该文件中配置的属性的时候,只需要使用@value即可.同理application.xml.applica

Tomcat源码分析——server.xml文件的解析

前言 在<Tomcat源码分析--server.xml文件的加载>一文中我们介绍了server.xml的加载,本文基于Tomcat7.0的Java源码,接着对server.xml文件是如何解析的进行分析. 概要 规则 Tomcat将server.xml文件中的所有元素上的属性都抽象为Rule,以Server元素为例,在内存中对应Server实例,Server实例的属性值就来自于Server元素的属性值.通过对规则(Rule)的应用,最终改变Server实例的属性值. Rule是一个抽象类,其中

Apache Kafka源码分析 – Broker Server

1. Kafka.scala 在Kafka的main入口中startup KafkaServerStartable, 而KafkaServerStartable这是对KafkaServer的封装 1: val kafkaServerStartble = new KafkaServerStartable(serverConfig) 2: kafkaServerStartble.startup   1: package kafka.server 2: class KafkaServerStartab