Jetty Basic Introduction

1. Jetty catalog analysis


  • bin: executable script file

  • demo- base:

  • etc: XML configuration defined by Jetty module File directory

  • lib: library files that Jetty depends on

  • logs: Jetty log directory

  • modules: Jetty’s modules

  • resources: directory of external resource configuration files

  • webapps: The directory of the project WAR file also needs to be concerned with a file in the root directory: start.d (the Windows system is the start.ini file), which defines Jetty’s active modules .


< p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; color:rgb(62 ,62,62); font-family:"Helvetica Neue",Helvetica,"Hiragino Sans GB","Microsoft YaHei",Arial,sans-serif; font-size:16px; word-wrap:break-word!important" > Two, basic configuration


1. Modify Jetty port


Jetty uses port 8080 by default. If you want it to use other ports (such as 7070), then edit start.d (the Windows system is the start.ini file), Find the jetty.http.port line and modify it to:


## Connector port to listen on

< span style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important; font-size:12px; color:rgb(136,136,136)">jetty.http.port=7070


Save and exit , Then restart Jetty.


2, modify the webapps directory


The webapps under Jetty is the default deployment directory of the Web project. If you want to modify this directory, you can modify the start.d configuration file (start.ini) and remove the comment symbol “#” in the following line.

< p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; color:rgb(62 ,62,62); font-family:"Helvetica Neue",Helvetica,"Hiragino Sans GB","Microsoft YaHei",Arial,sans-serif; font-size:16px; word-wrap:break-word!important" >

# jetty.deploy.monitoredDir=webapps


and modify the content to the directory you specify. Save and exit, then restart Jetty.


Three, Jetty’s modular architecture


Jetty runs on a modular architecture, which means that Jetty’s functions are run in modules, such as HTTP, HTTPS, SSL, logging, JMX, JNDI, WebSocket and other modules. Commonly used modules such as HTTP, JSP and WebSocket modules are activated by default, while other modules such as HTTPS and JMX need to be activated manually.


1. Analysis of a single module


< p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; color:rgb(62 ,62,62); font-family:"Helvetica Neue",Helvetica,"Hiragino Sans GB","Microsoft YaHei",Arial,sans-serif; font-size:16px; word-wrap:break-word!important" > Jetty’s modules subdirectory lists all modules. These modules are files with the extension .mod, which declare the JAR files to be activated (under Jetty’s lib subdirectory) and XML configuration files (in Jetty’s lib subdirectory). etc subdirectory), and other resources to be activated as modules. For example, you can view the contents of the logging.mod file in the modules subdirectory, and you can see that it states that the configuration file is etc/jetty-logging.xml, the required JAR package is in lib/logging, and the logs directory is required .


[ xml]

etc/jetty-logging.xml< /p>

[files]

logs/

[lib]

lib/logging/**.jar

resources/ p>


2. Activate the module through the command line


There are two ways to activate Jetty modules . The first way is to activate via the command line:


java -jar start.jar – add-to-startd=lo gging


The above command will create the logging.ini file in the Jetty directory, and the related configuration can be found in this file. After configuring the log, you can start Jetty again, and you can see that the log module is activated.


3. Activate the module through the configuration file start.ini


The second way is to activate the module through the configuration file start.ini


–module=logging


This method is similar to the previous one. And more commonly used.


4. Configuration module


< p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; color:rgb(62 ,62,62); font-family:"Helvetica Neue",Helvetica,"Hiragino Sans GB","Microsoft YaHei",Arial,sans-serif; font-size:16px; word-wrap:break-word!important" > As mentioned above, the mod file declares related XML configuration files. In the etc subdirectory of Jetty, the module can be configured through these configuration files. For example, the log module declares that the related configuration file is jetty-logging.xml, and the log can be adjusted by modifying this configuration file.


Four, accept the request


< p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; color:rgb(62 ,62,62); font-family:"Helvetica Neue",Helvetica,"Hiragino Sans GB","Microsoft YaHei",Arial,sans-serif; font-size:16px; word-wrap:break-word!important" > Jetty, as an independent Servlet engine, can independently provide Web services, but it can also be integrated with other Web application servers, so it can provide work based on two protocols, one is HTTP and the other is AJP protocol. If Jetty is integrated into Jboss or Apache, then Jetty can be made to work based on the AJP mode. The following describes how Jetty works based on these two protocols, and how they establish connections and accept requests.


1, based on HTTP


< p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; color:rgb(62 ,62,62); font-family:"Helvetica Neue",Helvetica,"Hiragino Sans GB","Microsoft YaHei",Arial,sans-serif; font-size:16px; word-wrap:break-word!important" > 2、基于AJP


3、NIO处理方式


Jetty 建立客户端连接到处理客户端的连接也支持 NIO 的处理方式,其中 Jetty 的默认 connector 就是 NIO 方式。


关于 NIO 的工作原理可以参考 developerworks 上关于 NIO 的文章,通常 NIO 的工作原型如下:


Selector selector = Selector.open(); 

ServerSocketChannel ssc = ServerSocketChannel.open(); 

ssc.configureBlocking( false ); 

SelectionKey key = ssc.register( selector, SelectionKey.OP_ACCEPT ); 

ServerSocketChannel ss = (ServerSocketChannel)key.channel(); 

SocketChannel sc = ss.accept(); 

sc.configureBlocking( false );

SelectionKey newKey = sc.register( selector, SelectionKey.OP_READ ); 

Set selectedKeys = selector.selectedKeys();


创建一个 Selector 相当于一个观察者,打开一个 Server 端通道,把这个 server 通道注册到观察者上并且指定监听的事件。然后遍历这个观察者观察到事件,取出感兴趣的事件再处理。这里有个最核心的地方就是,我们不需要为每个被观察者创建一个线程来监控它随时发生的事件。而是把这些被观察者都注册一个地方统一管理,然后由它把触发的事件统一发送给感兴趣的程序模块。这里的核心是能够统一的管理每个被观察者的事件,所以我们就可以把服务端上每个建立的连接传送和接受数据作为一个事件统一管理,这样就不必要每个连接需要一个线程来维护了。


这里需要注意的地方时,很多人认为监听 SelectionKey.OP_ACCEPT 事件就已经是非阻塞方式了,其实 Jetty 仍然是用一个线程来监听客户端的连接请求,当接受到请求后,把这个请求再注册到 Selector 上,然后才是非阻塞方式执行。这个地方还有一个容易引起误解的地方是:认为 Jetty 以 NIO 方式工作只会有一个线程来处理所有的请求,甚至会认为不同用户会在服务端共享一个线程从而会导致基于 ThreadLocal 的程序会出现问题,其实从 Jetty 的源码中能够发现,真正共享一个线程的处理只是在监听不同连接的数据传送事件上,比如有多个连接已经建立,传统方式是当没有数据传输时,线程是阻塞的也就是一直在等待下一个数据的到来,而 NIO 的处理方式是只有一个线程在等待所有连接的数据的到来,而当某个连接数据到来时 Jetty 会把它分配给这个连接对应的处理线程去处理,所以不同连接的处理线程仍然是独立的。


Jetty 的 NIO 处理方式和 Tomcat 的几乎一样,唯一不同的地方是在如何把监听到事件分配给对应的连接的处理方式。从测试效果来看 Jetty 的 NIO 处理方式更加高效。下面是 Jetty 的 NIO 处理时序图:



五、与 Tomcat 的比较


Tomcat 和 Jetty 都是作为一个 Servlet 引擎应用的比较广泛,可以将它们比作为中国与美国的关系,虽然 Jetty 正常成长为一个优秀的 Servlet 引擎,但是目前的 Tomcat 的地位仍然难以撼动。相比较来看,它们都有各自的优点与缺点。


Tomcat 经过长时间的发展,它已经广泛的被市场接受和认可,相对 Jetty 来说 Tomcat 还是比较稳定和成熟,尤其在企业级应用方面,Tomcat 仍然是第一选择。但是随着 Jetty 的发展,Jetty 的市场份额也在不断提高,至于原因就要归功与 Jetty 的很多优点了,而这些优点也是因为 Jetty 在技术上的优势体现出来的。


架构比较


从架构上来说,显然 Jetty 比 Tomcat 更加简单,如果你对 Tomcat 的架构还不是很了解的话,建议你先看一下 《Tomcat系统架构与设计模式》这篇文章。


Tomcat系统架构与设计模式

http://www.ibm.com/developerworks/cn/java/j-lo-tomcat2/index.html


Jetty 的架构从前面的分析可知,它的所有组件都是基于 Handler 来实现,当然它也支持 JMX。但是主要的功能扩展都可以用 Handler 来实现。可以说 Jetty 是面向 Handler 的架构,就像 Spring 是面向 Bean 的架构,iBATIS 是面向 statement 一样,而 Tomcat 是以多级容器构建起来的,它们的架构设计必然都有一个“元神”,所有以这个“元神“构建的其它组件都是肉身。


从设计模板角度来看 Handler 的设计实际上就是一个责任链模式,接口类 HandlerCollection 可以帮助开发者构建一个链,而另一个接口类 ScopeHandler 可以帮助你控制这个链的访问顺序。另外一个用到的设计模板就是观察者模式,用这个设计模式控制了整个 Jetty 的生命周期,只要继承了 LifeCycle 接口,你的对象就可以交给 Jetty 来统一管理了。所以扩展 Jetty 非常简单,也很容易让人理解,整体架构上的简单也带来了无比的好处,Jetty 可以很容易被扩展和裁剪。


相比之下,Tomcat 要臃肿很多,Tomcat 的整体设计上很复杂,前面说了 Tomcat 的核心是它的容器的设计,从 Server 到 Service 再到 engine 等 container 容器。作为一个应用服务器这样设计无口厚非,容器的分层设计也是为了更好的扩展,这是这种扩展的方式是将应用服务器的内部结构暴露给外部使用者,使得如果想扩展 Tomcat,开发人员必须要首先了解 Tomcat 的整体设计结构,然后才能知道如何按照它的规范来做扩展。这样无形就增加了对 Tomcat 的学习成本。不仅仅是容器,实际上 Tomcat 也有基于责任链的设计方式,像串联 Pipeline 的 Vavle 设计也是与 Jetty 的 Handler 类似的方式。要自己实现一个 Vavle 与写一个 Handler 的难度不相上下。表面上看,Tomcat 的功能要比 Jetty 强大,因为 Tomcat 已经帮你做了很多工作了,而 Jetty 只告诉,你能怎么做,如何做,有你去实现。


打个比方,就像小孩子学数学,Tomcat 告诉你 1+1=2,1+2=3,2+2=4 这个结果,然后你可以根据这个方式得出 1+1+2=4,你要计算其它数必须根据它给你的公式才能计算,而 Jetty 是告诉你加减乘除的算法规则,然后你就可以根据这个规则自己做运算了。所以你一旦掌握了 Jetty,Jetty 将变得异常强大。


性能比较


单纯比较 Tomcat 与 Jetty 的性能意义不是很大,只能说在某种使用场景下,它表现的各有差异。因为它们面向的使用场景不尽相同。从架构上来看 Tomcat 在处理少数非常繁忙的连接上更有优势,也就是说连接的生命周期如果短的话,Tomcat 的总体性能更高。


而 Jetty 刚好相反,Jetty 可以同时处理大量连接而且可以长时间保持这些连接。例如像一些 web 聊天应用非常适合用 Jetty 做服务器,像淘宝的 web 旺旺就是用 Jetty 作为 Servlet 引擎。


另外由于 Jetty 的架构非常简单,作为服务器它可以按需加载组件,这样不需要的组件可以去掉,这样无形可以减少服务器本身的内存开销,处理一次请求也是可以减少产生的临时对象,这样性能也会提高。另外 Jetty 默认使用的是 NIO 技术在处理 I/O 请求上更占优势,Tomcat 默认使用的是 BIO,在处理静态资源时,Tomcat 的性能不如 Jetty。


特性比较


作为一个标准的 Servlet 引擎,它们都支持标准的 Servlet 规范,还有 Java EE 的规范也都支持,由于 Tomcat 的使用的更加广泛,它对这些支持的更加全面一些,有很多特性 Tomcat 都直接集成进来了。但是 Jetty 的应变更加快速,这一方面是因为 Jetty 的开发社区更加活跃,另一方面也是因为 Jetty 的修改更加简单,它只要把相应的组件替换就好了,而 Tomcat 的整体结构上要复杂很多,修改功能比较缓慢。所以 Tomcat 对最新的 Servlet 规范的支持总是要比人们预期的要晚。


参考资料


  • 官方文档

    http://www.eclipse.org/jetty/documentation/current/

  • Jetty 的工作原理以及与 Tomcat 的比较

    http://www.ibm.com/developerworks/cn/java/j-lo-jetty/

Leave a Comment

Your email address will not be published.