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
相关推荐
在websphere8.5 下部署含有CXFwebservice的war包无法正常启动,而相应的war包在tomcat上是可以正常启动的,通过后台的日志分析大致可以定位为相关的cxf类无法找到,其实这些类在项目的lib目录下都是存在的,莫名其妙...
包含最新的包,connector加载不了的问题,包是最新的,开发环境,eclipse导入既可以用
Jetty Jetty 是一个开源的servlet容器,它为基于Java的web内容,例如JSP和servlet提供运行环境。Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布。... 配置connector 配置handler 配置servlet
C5Connector.Java * 已弃用 * Java 后端。... 目前只有jetty 8 和jetty 9 被作者成功测试。 如果您在其他 servlet 环境中成功测试了 C5Container.Java,请毫不犹豫地通知作者。 可以在找到更改日志。
安装agent是无侵入式的对性能的影响最小(只增加约3%资源利用率)支持的模块:JDK 6 Tomcat 6/7/8, Jetty 8/9Spring, Spring BootApache HTTP Client 3.x/4.x, JDK HttpConnector, GoogleHttpClient, OkHttpClient,...
Camel侦听器通过Camel Jetty组件接收信息,并将信息转换为SysAid创建服务请求所需的JSON格式。 用于SysAid的Rest API用于在SysAid中连接并创建服务请求。 要构建此项目,请使用 mvn install 要从Maven内部运行此...
7:mysql-connector-java-5.1.20-bin.jar 支持 mysql 数据库。 8:c3p0-0.9.1.2.jar 数据库连接池。 9:ehcache-core-2.5.2.jar、slf4j-api-1.6.1.jar、slf4j-log4j12-1.6.1.jar 支持 EhCache。 在使用EhCache时...
* AJP server connector available to let you plug behind an Apache HTTP server or Microsoft IIS. It is based on Jetty's connector. * Multiple client HTTP connectors available, based on either the JDK...
[INFO] Started ServerConnector@f1a45f8{HTTP/1.1}{0.0.0.0:8080} [INFO] Started @5133ms [INFO] Started Jetty Server [INFO] Starting scanner at interval of 10 seconds. 5. 访问 sample ...
如何作为独立的 Web 应用程序运行 mvn clean install jetty:run -P war然后访问网页界面 http://localhost:9092/或访问服务器的状态页面 http://localhost:9092/xdi或者使用 XDI 客户端将 XDI 消息发送到 ...
安装agent是无侵入式的对性能的影响最小(只增加约3%资源利用率)支持的模块:JDK 6+Tomcat 6/7/8,Jetty 8/9Spring,Spring BootApache HTTP Client 3.x/4.x,JDK HttpConnector,GoogleHttpClient,OkHttpClient...
NRE包括若干HTTP服务器连接器(HTTP server connector),它们都是基于Mortbay的Jetty、Codehaus的AsyncWeb,以及Simple框架这些流行的HTTP Java开源项目的。它甚至提供一个适配器(adapter),使你可以在标准...
5、Jersey(JAX-RS)、Tomcat、Jetty、DB Connector 等等。 Spring MVC 允许使用 MVC(模型、视图、控制器)设计模式开发 Web 应用程序。 为了熟悉 Spring MVC 应用程序,以下 Spring 注释很有用。 @Controller - 该...
依赖关系Javax Servlet (javax.servlet-3.0.0.v201112011016.jar) Jetty All (jetty-all-9.0.4.v20130625.jar) JSON-Java (jsonjava.jar) 从构建MySQL 连接器 (mysql-connector-java-5.1.28-bin.jar) jBCrypt ...
2014-12-11 13:44:22.880:INFO:oejs.Server:main: jetty-9.2.5.v20141112 2014-12-11 13:44:22.904:INFO:oejs.ServerConnector:main: Started ServerConnector@4a59d584{HTTP/1.1}{0.0.0.0:5050} 2014-12-11 13:44:...
NRE包括若干HTTP服务器连接器(HTTP server connector),它们都是基于Mortbay的Jetty、Codehaus的AsyncWeb,以及Simple框架这些流行的HTTP Java开源项目的。它甚至提供一个适配器(adapter),使你可以在标准...
只需运行Connector_Setup.exe ,就可以完成。 如果您需要编写部署脚本,则可以像调用命令行一样轻松实现。 差异与优势 这是连接IIS和Apache Tomcat的现代方法。 最有可能使用Railo,Lucee或JSP驱动的后端。 ...
jarjar-aether-connector-wagon-1.13.1.jar jarjar-aether-impl-1.13.1.jar jarjar-aether-spi-1.13.1.jar jarjar-aether-util-1.13.1.jar jarjar-maven-aether-provider-3.0.4.jar jarjar-maven-artifact-...
员工管理系统 作为基于Web的动态项目的一部分,使用J2EE,Servlet,MySQL和Java设计和开发了员工...选择项目-> RunOnServer->选择现有服务器(Jetty / Pivotal)->选择EMS jar文件->单击完成 项目在端口8080上运行。
832,960 mysql-connector-java-5.1.22-bin.jar 536,609 mysql-jdbc.jar 125,150 nekohtml-1.9.21.jar 1,106,629 netty-3.5.7.Final.jar 4,063,471 operadriver-1.5.jar 10,642 phantomjsdriver-1.1.0.jar 2,...