1.Connector的继承体系
jetty的connector继承体系如下图:
我们可以看到,首先AbstractConnector实现了lifecycle的接口和connector接口,事实上,connector的生命周期应该和容器是差不多的,会一直存在。然后看到AbstractConnector持有了到server,ThreadPool等的引用,基本上,持有了Server的引用,就可以触及Threadpool和Handler,整个关联关系就打通了。
然后可以看到每个具体的Connector,首先都有一个ServerSocketChannel(或者ServerSocket),对于SocketConnector和BlockingChannelConnector这样block的连接模式都有一个Endpoint的Set来存放目前所有的连接。对于Select型的,则委托给SelectorManager来管理。
HttpBuffers是读取请求头和body的缓冲区,估计是出于减少内存分配的考虑,使用了ThreadLocal的变量,具体有requsetBuffer和responseBuffer,他们被具体connection的parser和generator引用。当然这样也增加了复杂度,特别是在continuation的情况下。
endpoint这边是每次请求新创建的对象,生命周期同请求的生命周期,而且和connector一一对应。根据是否nio,使用了stream和channel两种方式,对于channel又分为阻塞和非阻塞。每个endpoint都会持有一个httpconnection,在接收请求的时候,会调用httpconnection的handle,这样后面的处理所有connector就一样了。connection会把读取的工作委托给httpPaser,在具体的fill数据的过程还是有区别的,但都是统一接口不同实现。下面针对各个connector逐一分析。
2.SocketConnector
block模式的connector代码比较简单,基本上就是获取一个socket,丢到线程池让一个worker来处理就好了。
初始化过程大致如下:
- SocketConnector的doStart方法直接调用父类,也就是AbstractConnector的doStart方法。
- AbstractConnector先调用open()方法,实际委托到具体的实现类,对于SocketConnector,就是调用_serverSocket= newServerSocket(getHost(),getPort(),getAcceptQueueSize());
- 然后初始化connector的ThreadPool,如未特别设置,就是取server的ThreadPool。
- 根据getAcceptors()个数初始化Acceptor并放入线程池,线程池内会启动acceptor并调用run方法,这个run方法最核心的就是调用一个抽象方法accept(_acceptor),委托给子类实现,对于SocketConnector,就是 Socket socket = _serverSocket.accept().
至此,初始化基本完成,会有getAcceptors()个Thread处于accept状态,但使用的是同一个connector,因此对于bio来说,大于一个acceptor没有意义。
接收请求过程大致如下:
- serverSocket.accept(),取得一个socket之后,用这个socket new出一个ConnectorEndPoint
- 在ConnectorEndPoint的构造函数中new出一个HttpConnection(传入ConnectorEndPoint本身和server的引用)并赋值给ConnectorEndPoint
- 然后调用ConnectorEndPoint的dispatch,把ConnectorEndPoint本身放入线程池。
- 最后ConnectorEndPoint的run方法被调用,run方法中调用其持有的HttpConnection的handle函数即可。
- HttpConnection的handle函数及其后面,所有的connector都是同一套代码了,主要完成http请求数据解析,request等构造,以及具体的handler处理。
3.SelectChannelConnector
这个比较复杂,先上一个类图
其中蓝色对象的生命周期是一个请求的生命周期,黄色的生命周期是server的生命周期。该类图和文章前面的图有些重合,但侧重点在selectchannelConnector。其中selectchannelConnector的SelectorManager以及多个selectSet主要完成selectKey的注册,轮询等操作,selectChannelEndPoint主要持有一个connection对象以及manager对象。connection持有server的引用,以及4个重要的成员,request,respoonse,parser和generator,很对称。parser和generator又持有对buffer的引用。这些对象都是在accept后new出来的,在请求结束之后销毁。
初始化过程大致如下:
- doStart()方法先初始化 SelectorManager,设置SelectSet个数等参数,_manager.setSelectSets(getAcceptors());一个SelectorManager有多个SelectSet,放在一个数组中,SelectorManager$SelectSet是去做doselect,完成读取等工作的地方。
- 调用super.doStart()方法,即AbstractConnector的doStart。AbstractConnector调用open()方法,实际委托到具体的实现类,对于SelectChannelConnector,工作就是调用_acceptChannel = ServerSocketChannel.open();和bind();
- 初始化getAcceptors()个Acceptor并放入线程池,线程池内会启动acceptor并调用run方法。
- 这个run方法最核心的就是调用一个抽象方法accept(_acceptor),委托给子类实现
- 在Acceptor的run方法中,会调用accept(_acceptor),将具体的accept实现委托给子类完成。对于SelectChannelConnector,其accept(_acceptor)方法就是调用_manager.doSelect(acceptorID);
- _manager.doSelect(acceptorID)会根据acceptorID,调用一个具体的SelectSet的doSelect方法。一个SelectorManager有多个SelectSet,放在一个数组中,SelectSet的个数就是Acceptor的个数。
- 然后SelectChannelConnector的doStart方法会启动一个线程(委托给SelectorManager,最终使用的是ServerSocketChannel的ThreadPool,如果没有特别设置,就是server的ThreadPool),在这个线程中使用ServerSocketChannel.accept来accept请求,
接收请求过程大致如下:
- _ServerSocketChannel.accept接收到请求,调用manager.register(channel);将得到的SocketChannel以轮询的方式,放入多个SelectSet的一个的队列中
- 让SelectSet的doSelect会消费它队列中的消息,发现如果是一个SocketChannel,就为这个channel注册一个READ事件,并createEndPoint创建一个EndPoint(在创建EndPoint的过程中会创建HttpConnection),将endPoint绑定到key的attachment,调用EndPoint的schedule().
- doSelect方法开始调用SelectionKey key: selector.selectedKeys()。对于每个取得的key,如果是SelectChannelEndPoint,就调用SelectChannelEndPoint的schedule()方法。
- 还会新起一个线程来判断所有SendPoint的idle超时状态。在createEndPoint()时会将创建的endPoint放到一个map中。这里是每个SelectSet都有这个map。
对于createEndPoint的过程,本质和socketConnector没有区别,就是将EndPoint和HttpConnection创建出来,并维护上面类图所示关系,大致时序如下图:(这里绕一圈的原因就是httpconnection需要持有connector的引用,然后普通的encpoint都是connector的内部类,比较好处理,select是单独的,要通过manager绕一圈,当然也可以直接把connector传入。)
SelectChannelEndPoint的schedule()方法会处理一些nio的操作,然后将自己的handler通过dispatch丢入线程池,让别的线程来处理后续流程,包括http请求数据解析,request等构造,以及具体的handler处理等,具体过程见下图:
再重复一下,这里其实从HttpConnection开始,各种connector的处理就一样了。
总结一下,jetty的selectchannel处理模型是这样的:
4.jetty的nio
1.jetty目前是通过一个线程来accept,然后将取得的socketChannel丢入由2个或者多个(根据acceptor个数配置)处理器中的一个的待处理队列(SelectorManager$selectSet._changes),来处理。这几个处理线程的逻辑是,先看待处理队列有木有要处理的事情,主要有两件:
1.处理连接,新建endpoint,注册读事件
2.updatekey,处理selectkey的更新操作,把关注事件添加到selectKey。
这个事情干完后,再调用selector做select,这里主要针对的是读事件的到达,有读事件到达后,将对应的attachment取出来(一般是一个SelectsocketChannel,然后调用它的schedule,将其handler丢入线程池去等待处理)。如果在http头处理中,一次读取没有全部度出来,线程将释放,等待下次读事件的到达
对于写操作,具体的写操作一般再endpoint的flush方法,但是在write的时候,一般是先注册写事件然后wait,然后等写事件就绪的时候(也在selectSet的doselect方法中)再notifyAll,然后开始写。
一些配置:
maxIdletime,最大空闲时间,主要有3钟作用(类似于apche的timeout+keepalivetimeout)
1.连接空闲的最大时间,后台有一个线程,会定时轮询所有的连接(endpoint)是否超过了最大时间,如果超过则关闭.在接收到请求等时候会更新endpoint的对应属性。
2.阻塞读取请求头或者体的最大阻塞时间。
3.阻塞写时的最大阻塞时间。
在非nio的情况下,直接设置为socekt.setSoTimeout
相关推荐
在构架方面,作者深入讲解了Jetty的架构,包括Connector(连接器)、Handler(处理器)、Server和ThreadPool(线程池)等核心组件,让读者了解Jetty如何处理网络请求和应用服务。 配置文件是Jetty管理的关键,书中...
#### 八、Jetty Connector SSL的配置 - **SSL/TLS支持**: 如何配置Jetty以支持HTTPS连接。 - **Apache mod_proxy**: 如何将Apache服务器与Jetty配合使用。 - **AJP部署**: 介绍AJP协议及其在Jetty中的应用。 #### ...
配置Jetty9服务器使用HTTPS证书的过程涉及多个步骤,包括申请证书、转换证书格式、以及配置Jetty服务器本身。以下详细描述这些步骤。 首先,申请证书部分通常需要借助第三方服务商,如阿里云、腾讯云等,这些服务商...
《深入解析i_jetty安卓端源码》 i_jetty是一款专门为Android平台设计的轻量级Web服务器组件,它基于著名的Java Web服务器Jetty进行优化和定制,为Android应用提供了强大的HTTP服务支持。本文将围绕i_jetty安卓端...
Jetty-all.jar是一个集合了众多Jetty组件的综合性JAR文件,它的主要目的是为了方便开发者在项目中快速引入和使用Jetty服务器。Jetty是一个开源的HTTP服务器和Servlet容器,它以其轻量级、高性能和易用性而受到广泛...
1. 接受请求:Jetty 通过 connector 接受来自客户端的请求。 2. 处理请求:Jetty 通过 handler 处理请求,包括解析请求、执行业务逻辑等。 3. 响应请求:Jetty 通过响应客户端的请求。 请求处理下篇 Jetty 的请求...
它提供了Server、Connector和Handler等关键接口和实现。 2. **jetty-http.jar**:这个库提供了HTTP协议的实现,包括请求和响应的解析与构建。 3. **jetty-servlet.jar**:Servlet是Java Web开发的标准接口,这个...
7. **类加载器**、**Jetty Connector的SSL配置**、**虚拟主机**、**管理服务器**、**JNDI配置**、**会话与集群**、**性能优化**、**异步Servlet、Ajax和Comet**以及**嵌入Jetty**等内容,都是指南中详细阐述的主题,...
- **构架概述**:解释Jetty的核心组件,如Connector(连接器)、Handler(处理器)和Server。 - **Connector**:负责网络通信,如HTTP和HTTPS连接的建立。 - **Handler**:处理不同的HTTP请求,如Request Handler...
<connector implementation="org.eclipse.jetty.server.ssl.SslSelectChannelConnector"> <port>443 <keystore>C:\Program Files\Java\jdk1.6.0_43\bin\dotuian.keystore <keyPassword>123456 <password>123456 ...
#### 八、Jetty Connector SSL的配置 **8.1 SSL配置** Jetty支持通过HTTPS协议提供安全的Web服务。配置SSL涉及创建密钥库、配置证书等步骤。 **8.2 Apache mod_proxy/AJP部署** 除了作为独立的Web服务器,Jetty...
<New id="httpConnector" class="org.eclipse.jetty.server.nio.SelectChannelConnector"> <Set name="host">localhost <Set name="port">8080 ``` **4.3 org.mortbay.xml.XmlConfiguration** `org....
对于需要在多个端口上提供服务的情况,Jetty提供了`ServerConnector`接口。你可以创建多个`ServerConnector`实例,分别绑定到不同的端口,实现同一服务器同时监听多个端口的功能。 6. **连接器与协议**: Jetty...
4. **连接器(Connector)**:Jetty通过`Connector`组件与网络通信,如`SelectChannelConnector`使用NIO(非阻塞I/O)处理网络连接。这部分源码可以帮助理解Jetty如何处理网络I/O事件。 5. **生命周期管理**:Jetty...
2. **内嵌Jetty的实现**:学习如何通过Java代码创建并启动一个内嵌的Jetty服务器,这通常涉及导入相关的Jetty库,创建Server对象,配置Connector(如HTTP或HTTPS)和Handler(如WebAppContext)。 3. **Servlet容器...
`ServerConnector`是Jetty中用于接收客户端连接并将其传递给适当的Handler进行处理的关键组件。 **初始化代码示例:** ```java public Server(@Name("port") int port) { this((ThreadPool) null); Server...
Jetty的核心组件包括Server、Connector和Handler。Server是整个Jetty服务器的入口点,Connector负责处理网络连接,而Handler则处理HTTP请求和响应。在指定端口创建TCP服务时,我们需要配置一个Connector,并设置监听...
3. **连接器(Connector)**:理解Jetty的不同连接器类型,如HTTP/1.1和HTTP/2,以及如何选择和配置。 4. **安全性**:介绍Jetty的安全机制,包括角色认证、SSL/TLS配置和过滤器链。 四、实战与最佳实践 1. **...
2. **Connector**:理解`Connector`接口及其实现,如`SelectChannelConnector`,它们负责网络连接的建立和管理。 3. **Handler**:查看`Handler`接口和其实现,如`ContextHandler`和`ServletHandler`,它们处理HTTP...
使用Jetty Server API是最基础的嵌入方式,通过创建Server对象,配置Connector(连接器)来监听端口,然后添加Handler(处理器)来处理请求。例如,可以创建一个简单的HTTP服务器,监听8080端口: ```java ...