Jetty 的启动过程
Jetty 的入口是 Server类,Server 类启动完成了,就代表 Jetty 能为你提供服务了。它到底能提供哪些服务,就要看 Server 类启动时都调用了其它组件的 start方法。从 Jetty 的配置文件我们可以发现,配置 Jetty 的过程就是将那些类配置到 Server 的过程。下面是 Jetty 的启动时序图:
图 4. Jetty 的启动流程
因为 Jetty 中所有的组件都会继承LifeCycle,所以 Server 的 start 方法调用就会调用所有已经注册到 Server 的组件,Server启动其它组件的顺序是:首先启动设置到 Server 的 Handler,通常这个 Handler 会有很多子 Handler,这些 Handler 将组成一个Handler 链。Server 会依次启动这个链上的所有
Handler。接着会启动注册在 Server 上 JMX 的 Mbean,让 Mbean也一起工作起来,最后会启动 Connector,打开端口,接受客户端请求,启动逻辑非常简单。
接受请求
Jetty 作为一个独立的Servlet 引擎可以独立提供 Web 服务,但是它也可以与其他 Web 应用服务器集成,所以它可以提供基于两种协议工作,一个是 HTTP,一个是 AJP协议。如果将 Jetty 集成到 Jboss 或者 Apache,那么就可以让 Jetty 基于 AJP 模式工作。下面分别介绍 Jetty如何基于这两种协议工作,并且它们如何建立连接和接受请求的。
基于 HTTP 协议工作
如果前端没有其它 web 服务器,那么Jetty 应该是基于 HTTP 协议工作。也就是当 Jetty 接收到一个请求时,必须要按照 HTTP 协议解析请求和封装返回的数据。那么 Jetty是如何接受一个连接又如何处理这个连接呢?
我们设置 Jetty 的Connector 实现类为 org.eclipse.jetty.server.bi.SocketConnector 让 Jetty 以 BIO的方式工作,Jetty 在启动时将会创建 BIO 的工作环境,它会创建 HttpConnection 类用来解析和封装 HTTP1.1的协议,ConnectorEndPoint 类是以 BIO 的处理方式处理连接请求,ServerSocket
是建立 socket连接接受和传送数据,Executor 是处理连接的线程池,它负责处理每一个请求队列中任务。acceptorThread 是监听连接请求,一有 socket连接,它将进入下面的处理流程。
当 socket被真正执行时,HttpConnection 将被调用,这里定义了如何将请求传递到 servlet 容器里,有如何将请求最终路由到目的servlet,关于这个细节可以参考《 servlet 工作原理解析》一文。
下图是 Jetty启动创建建立连接的时序图:
图 5. 建立连接的时序图
Jetty创建接受连接环境需要三个步骤:
- 创建一个队列线程池,用于处理每个建立连接产生的任务,这个线程池可以由用户来指定,这个和 Tomcat是类似的。
- 创建 ServerSocket,用于准备接受客户端的 socket
请求,以及客户端用来包装这个 socket的一些辅助类。 - 创建一个或多个监听线程,用来监听访问端口是否有连接进来。
相比 Tomcat创建建立连接的环境,Jetty 的逻辑更加简单,牵涉到的类更少,执行的代码量也更少了。
当建立连接的环境已经准备好了,就可以接受HTTP 请求了,当 Acceptor 接受到 socket 连接后将转入下图所示流程执行:
图 6. 处理连接时序图
Accetptor线程将会为这个请求创建 ConnectorEndPoint。HttpConnection 用来表示这个连接是一个 HTTP 协议的连接,它会创建HttpParse 类解析 HTTP 协议,并且会创建符合 HTTP 协议的 Request 和 Response对象。接下去就是将这个线程交给队列线程池去执行了。
参考:http://www.ibm.com/developerworks/cn/java/j-lo-jetty/