分类: 系统运维
2012-11-11 21:25:48
Jetty目前已经出到第七版了,Jetty6是一个稳定的版本。从Jetty7开始,Jetty已经支持和Eclipse的集成,同时在Jetty的官方网站上面,对于Jetty的介绍也划分成为第六版以及第六版以前的版本和第七版两个Jetty介绍的入口,可见Jetty第7版还是有改变的。
介绍时选用版本6的Jetty,由于空间每篇内容大小限制,因此拆分,此为上篇
Jetty架构
Jetty的设计非常的简介明快,由4个功能模块构成,其中每个功能模块都各司其职,从最宏观的视角来开始介绍Jetty:
图 Jetty的宏观架构
官方网站对于此图的介绍是:从20000英尺的高度来看Jetty。如上图所示,Jetty的4个功能组成模块分别是:Connector,Server,ThreadPool以及Handler。对于Jetty的架构定义也是根据这四个模块的各自的功能来完成的。
Jetty的架构是由一系列负责接收HTTP连接的Connectors,将连接请求交给一系列Handlers用于处理连接请求和产生响应,而所有的这些工作是由一个ThreadPool里面的线程进行完成的。而Server是整个架构的核心,负责衔接以上的所有工作。现在分别描述里面的边缘组件的指责。
1. Connector: 连接器,负责连接客户端发起的HTTP connections。
2. Handler:处理器,接受处理来自HTTP connections的请求,并对其进行内容响应。
3. ThreadPool:线程池,管理和调度多个线程,用来服务与HTTP connections和Handler的运行。
其中请求request和相应response这两个术语的定义继承自JavaEE的Servlet API。因此,熟悉Web变成的同学可以毫不费力的理解其中的含义。当然Jetty也可以由非常简单的Connectors和Handler构成,从而不使用Servlet。
构件Jetty的工作就是构件一个由Connectors和Handlers组成的网络,并对Connectors和Handlers给出相应的配置。由于Jetty是使用简单的POJOs(plain old java object)进行配置构件的,因此整个架构的过程可以由多种方法完成。
·使用代码。
·使用jetty.xml配置文件,利用依赖注入的特性。
·使用专门的依赖注入框架:Spring或者XBean
·部署Deployers:WebAppDeployer(静态方式),ContextDeployer(动态方式)。
Jetty模式(patterns)
Jetty的实现遵从了一些最标准的设计模式。例如Connector、Handler以及Buffer等概念是由Java接口来界定的。而对这些接口最基本的处理实现版本则由Abstract进行冠名,例如AbstractConnector,AbstractHandler以及AbstractBuffer。
图 Jetty设计模式
JSR(Java Specification Requests)77引入了life cycle的概念。绝大多数的Jetty组件是由LifeCycle接口来代表的,LifeCycle的基本实现是由AbstractLifeCycle来实现的。
Jetty在String、字节数组以及NIO buffer之上提供了它自己的IO Buffering抽象,这给Jetty带来了更大的移植性,并且隐藏了NIO buffer等技术背后的复杂性及其高级特性。
Connectors
Connectors和具体的协议相绑定,主要用于接受连接,处理请求,以及产生响应。不同种类的Connectors和不同的连接协议、调度模型以及所使用的IO api相关联。
图 Connector的总体结构
例如:Ajp13SocketConnector是用来与支持AJP协议的服务器(如apache http)做反向代理连接时使用的,Ajp13Connection是集成自HttpConnectioin类,因为AJP协议是一种对HTTP协议的扩展。
除了AJPConnector之外,还有以下常用的Connectors。
·SocketConnector:当NIO不可用时,处理少量的忙碌链接。
·BlockingChannelConnector:当NIO可用时,处理少量的忙碌链接。
·SelectChannelConnector:处理大量闲散的连接或者针对Ajax请求的异步处理。
·SslSocketConnector:不带NIO的SSL链接的处理。
·SslSelectChannelConnector:带NIO支持的SSL链接的处理。
综上所述,Connector具有众多实现类的原因,主要是由于socket编程模型和不同的协议来决定的。Connector在Jetty中扮演重要的角色,职责是接收来自客户端的请求,根据HTTP协议解析请求的内容,指派一个线程去处理请求并响应结果。
Handler
Handler组件用于处理接收到的请求,或者将请求传递给另外一个handler(或者servlet)或者将请求修改并封装之后再进行传递。
而Handler最核心的方法调用为:
public void handle(String target, HttpServlet request, HttpServlet response, int dispatch)
throws IOException,. ServletException;
参数target是指客户端请求的地址,也就是URI;这里我们发现request和response的类型分别是来自Servlet规范里面的HttpServletRequest和HttpServletResponse接口,那么我们可以得知HttpConnection引用的Request和Response类分别就是这两个接口的实现了。
图 Handler的总体架构
handle方法的参数列表和Servlet的service方法非常相似,但是必须澄清的是,虽然handle方法列表中采用了Servlet规范中的HttpServletRequest和HttpServletResponse接口,但是不意味着完全实现了Servlet规范所有的特性。例如:如果没有为Jetty配置ContextHandler处理器,那么request的getContextPath方法会返回null。所以handle方法只是借用了Servlet规范中这两个接口而已,估计这也是为了更方便的实现Servlet规范做好准备吧。
Handler的类型有以下三种:
1. 内容输出Handler(Generating Handler)
该类Handler根据target输出内容。如:ResourceHandler、ServletHandler、DefaultHandler等。这些类都是直接对Handler接口进行实现。
2. 过滤模式Handler(Filtering Handler)
该类Handler可以选择在交给另外一个Handler对象调用前或后来处理Request和Response。这些类都继承自HandlerWrapper类。HandlerWrapper中的setHandler方法便是用来设定被代理Handler对象的,这个方法在以后大家会经常用到。另外装饰器模式还运行将多个Handler串联起来使用。
3. 协作类型Handler (Coordinating Handler)
该类Handler的作用是讲请求分发给其他Handler处理,分发策略由各自实现类决定。常用集合类Handler有 HandlerCollection、HandlerList、ContextHandlerCollection。
Servlets
ServletHandler也是一个Handler,而由于Servlet地位的特殊性,因此这里单独叙述。如下图所示:
图 Servlet的结构图
ServletHandler是一个Handler的实现,它将请求传递给任何已经配置过的过滤器(Filters),然后再从过滤器那里将过滤过的请求传给经过URI模式映射的Servlet。
ServletHandler通常部署在一个Servlet上下文环境(Context)之内,在Jetty中,这个上下文环境的名称是ContextHandler,它为Servlet URI映射提供便捷的方法。
过滤器(Filters)以及Servlets同样可以使用一个RequestDispatcher,来将一个请求重路由给另外一个上下文(Context)或者当前上下文(Context)中的另外一个Servlet。
Context
Context就是JavaEE中的上下文了,它在Jetty中也是作为Handler而进行实现的。它将其他的Handler们聚集在一个特定的URI上下文路径或者一个虚拟主机之下。一个典型的Context具有以下的功能部件:
·上下文路径(Context path):该路径定义了哪些请求被Context进行处理。(/myapps)
·资源数据库(Resource base):资源数据库存储一些静态资源,例如:图片、css等。(docroot)
·类加载器(class loader):用于加载针对当前Context的类(docroot/WEB-INF/classes)。
Context的实现包括:ContextHandler,Servlet Context以及Web Application Context。
特别指出:一个Web应用上下文将负责安全、会话以及Servlet的handler集成到一个单一的部件中。并且该Web应用上下文可以通过部署描述符web.xml进行配置。
Server
在Handler的总体架构图中,注意到Server也是一个Handler的实现(过滤模式Handler)。其实在Server代理了所有其他的Handler,是所有Handler的入口。
Server代表一个Jerry服务器对象,它的作用就好象一个插线板,把Connector、Handler和ThreadPool集成在一起让它们协同起来工作。
为了使Jetty服务器工作起来,需要初始化一个Server对象实例,然后给它注册一个或多个Connector对象实例、注册一个ThreadPool对象、注册多个Handler对象并让这些Handler组合起来,这样一个Jetty服务器便组装完成。
ThreadPool
ThreadPool,Jetty为我们提供了两个实现版本:org.mortbay.thread.concurrent.ThreadPool和org.mortbay.thread.QueuedThreadPool。当j2se是1.5以上版本是我们选择ThreadPool的实现。ThreadPool存在的目的是因为线程的创建是非常昂贵的操作,所以使用Pool技术以便重复使用以创建的线程。
ThreadPool的大致工作方式是:如果存在一个空闲线程,则让它去执行请求处理。如果不存在且没有达到设定的最大线程数,那么就新建一个Thread去执行请求处理。如果已经达到最大线程数,那么就将工作任务放到队列里面排队,等到有空闲线程时再执行任务。
完整的Web应用
图 Jetty搭建的完整的Web应用
如上图所示,此类是一个完整的web应用结构图,由一个Server、一个ThreadPool以及各种类型的Connector、Handler构成。该应用构成了一个完整的Web应用,而其中的上下文环境就是由WebAppContext进行管理的。
WebAppContext继承于Servlet Context,它支持一个Web应用的标准布置,以及支持通过web.xml对会话、安全、监听器、过滤器、Servlet和JSP的配置。该web.xml配置文件通常位于一个web目录的WEB-INF文件夹内。
WebAppContext在本质上是一个类来方便地协助对其他handlers的配置和构建,以便达到一个标准的web应用配置,配置工作通常是由可插拔的Configuration的实现来完成的,一个可用的实现便是WebXmlConfiguration。
参考