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的数量。
Jetty 9 源码分析 Connector及Server类(一)的更多相关文章
- Jetty - Container源码分析
1. 描述 Container提供管理bean的能力. 基于Jetty-9.4.8.v20171121. 1.1 API public interface Container { // 增加一个bea ...
- tomcat8源码分析-Connector初始化
谈起Tomcat的诞生,最早可以追溯到1995年.近20年来,Tomcat始终是使用最广泛的Web服务器,由于其使用Java语言开发,所以广为Java程序员所熟悉.很多人早期的J2EE项目,由程序员自 ...
- 【Canal源码分析】Canal Server的启动和停止过程
本文主要解析下canal server的启动过程,希望能有所收获. 一.序列图 1.1 启动 1.2 停止 二.源码分析 整个server启动的过程比较复杂,看图难以理解,需要辅以文字说明. 首先程序 ...
- Eureka 源码分析之 Eureka Server
文章首发于公众号<程序员果果> 地址 : https://mp.weixin.qq.com/s/FfJrAGQuHyVrsedtbr0Ihw 简介 上一篇文章<Eureka 源码分析 ...
- Spring Developer Tools 源码分析:二、类路径监控
在 Spring Developer Tools 源码分析一中介绍了 devtools 提供的文件监控实现,在第二部分中,我们将会使用第一部分提供的目录监控功能,实现对开发环境中 classpath ...
- Jetty - LifeCycle源码分析
1. 描述 基于Jetty-9.4.8.v20171121. LifeCycle主要管理Jetty里面通用组件的生命周期,比如组件启动中.启动.运行.停止中.停止等,实现该接口就可以定义一套生命周期. ...
- nova-api源码分析(WSGI server的创建及启动)
源码版本:H版 一.前奏 nova api本身作为一个WSGI服务器,对外提供HTTP请求服务,对内调用nova的其他模块响应相应的HTTP请求.分为两大部分,一是服务器本身的启动与运行,一是加载的a ...
- [编织消息框架][netty源码分析]6 ChannelPipeline 实现类DefaultChannelPipeline职责与实现
ChannelPipeline 负责channel数据进出处理,如数据编解码等.采用拦截思想设计,经过A handler处理后接着交给next handler ChannelPipeline 并不是直 ...
- tp5底层源码分析之------tp5.1类的自动加载机制
tp框架作为国内主流框架,目前已经发布了6.0版本,相当于3.*版本是进行了重构,今天我们从源码的角度来研究下tp5.1自动加载的实现 作为单入口框架,从入口文件看起,入口文件在public/下,那么 ...
随机推荐
- LinuxMM--Memory Pressure
Memory pressure定义在操作系统中,用户分配.文件缓存.网卡包缓冲区等等都会消耗内存.一旦出现内存紧张就会导致memory pressure.引发当某个任务需要请求内存时就有可能引发mem ...
- 性能测试之--Apache JMeter安装
Hi,今天给大家分享一下安装JMeter的相关内容~ Apache JMeter 是Apache组织的开源项目,是一个100%纯Java桌面应用,用于压力测试和性能测试. 它能够对HTTP.FTP服务 ...
- linux权限管理
安全上下文:在linux系统中每个进程均以某个用户的身份运行,进程访问资源的权限取决于发起此进程的那个用户的权限 权限应用模型: 1)判断运行此进程的用户是否与被访问的资源的属主相同,如果相同,则运用 ...
- flask_单元测试
我们现在可以试着在控制台向数据库添加一个用户: In[2]: import model; In[3]: from microblog import db; In[4]: u=model.User(ni ...
- ArcGIS Js/Flex等前端API(Query(StatisticDefinition)时)针对SDE的SHAPE.AREA/SHAPE.LEN知道查询无效,而对GDB的SHAPE_Area/SHAPE_Length有效探索。
FIeld 'SHAPE.AREA' and 'SHAPE.LEN' of SDE For Oracle,Field 'SHAPE_Area' and 'SHAPE_Length' of gdb(ge ...
- hdu 5543 Pick The Sticks(动态规划)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5543 题意:给你一根长为m的长木板和一些小木棒,每一根小木棒有它的长度和价值,这些小木棒要放在长木板上 ...
- 在JAVA中把JSON数据格式化输出到控制台
public class ForMatJSONStr { public static void main(String[] args) { String jsonStr = "{\" ...
- 初学python第一天
在学习了c++,java后自己又找到一门面向对象的技术.没错,它就是python.首先介绍一下自己所用的python版本,自己在Python官网http://www.python.org下载了IDLE ...
- 查询Oracle锁表和解决方法
Oracle数据库操作中,我们有时会用到锁表查询以及解锁和kill进程等操作,那么这些操作是怎么实现的呢?本文我们主要就介绍一下这部分内容.(1)锁表查询的代码有以下的形式:select count( ...
- Hibernate快照
l当session加载了某个对象后,会为该对象的值类型的属性复制一份快照.当刷出缓存时,通过比较对象的当前属性和快照,来判断对象的哪些属性发生了变化. 代码如下: /** * 修改学生信息 */ @T ...