设为首页 收藏本站
查看: 1139|回复: 0

[经验分享] jetty源码架构分析

[复制链接]

尚未签到

发表于 2017-2-26 09:46:13 | 显示全部楼层 |阅读模式
from: http://docs.huihoo.com/jetty/1.html

一、 总括
    你了解Jetty 吗,就像我们所熟知的Tomcat一样,Jetty是一个免费的开放源码的100%纯Java的Http服务器和Servlet容器。
[/td]<!-- 开始正文-->[td=1,1,98%]


  Jetty具备以下特点:
    快速高效
  。Jetty是最快的Servlet服务器之一
    。Jetty可以处理上千个并发连接
     小巧嵌入
    。Jetty的jar只有600多K
    。可动态嵌入到应用程序,适合开发web2.0等应用
  应用广泛
  。开源项目有Geronimo, JBoss,JOnAS等
  。商业项目有IBMTivoli, Sonic MQ and Cisco SESM等
  可到Jetty网站http://jetty.mortbay.org/jetty/查看最新信息
    本文将通过对Jetty最新稳定版 Jetty5.1.5RC2源码的研究,向读者展示Jetty在设计方面使用的不同设计理念, 希望对广大开发者在设计自己的系统时有所帮助。
  Jetty按照功能可以分为四个主个主要的部分,HttpServer,HttpContext,HttpHandler,HttpListener,详见如下类图:
DSC0000.jpg
  <图 1-1>
二、HttpServer及配置
    对于初次接触Jetty的人一定会对上图感到迷惑,其实在Jetty中HttpServer是一个服务器的核心控制类,我们可以看到,其它的组件类都是由该类扩展开来,HttpServer的作用就是在一系列的监听器类和处理器类之间搭起了一个桥梁,有效的控制着消息在系统内的传递,如下图:
DSC0001.jpg
<图 1-2 >
    HttpServer职责是接受从HttpListener传递过来的request(请求),HttpServer通过对request的Host(主机)或Path(路径)进行匹配,然后分发给相应的HttpContext(可以理解为一个web application)。
    这里举个例子,假设我们现在要建立一个提供静态页面web服务,页面内容在c:\root\下,可以通过如此配置HttpServer:
     HttpServerserver = new HttpServer(); // 创建一个新的HttpServer
    SocketListener listener = newSocketListener(); // 创建一个新监听器
    listener.setPort(8080);// 设置监听端口为8080
    server.addListener(listener);//将监听类注册到server中
     HttpContextcontext = new HttpContext(); // 创建一个新HttpContext
    context.setContextPath("/app/*"); //设置访问路径
    context.setResourceBase("c:/root/"); //设置静态资源路径
    context.addHandler(newResourceHandler()); // 为这个HttpContext添加一个静态资源处理器
    server.addContext(context); //将这个HttpContext注册到server中
    server.start();// 最后启动这个server
    当我们要建立一个提供动态页面web服务时, 假设我们自己的 web应用放在Jetty目录下的webapps下并打好包文件名为myapp.war, 可以通过如此配置HttpServer:
     Server server= new Server(); // 创建一个新的HttpServer
     SocketListenerlistener = new SocketListener();// 创建一个新监听器
    listener.setPort(8080); // 设置监听端口为8080
    server.addListener(listener ); //将监听类注册到server中
    server.addWebApplication("myapp","./webapps/myapp/");// 将这个web应用注册到这个Server中
    server.start(); // 最后启动这个server
    短短数行代码就可创建一个web服务器并启动它,这有点类似于我们windows中的即插即用的概念,需要什么就添加什么,把这些类以HttpServer为核心组合在一起,就可以完成强大的功能。
 
三、Jetty Server
    1.上面我们探讨了HttpServer的启动,读者一定还存在这样疑问,整个Jetty服务器是怎样启动的?
     首先我们可以在图 1-1看到左下角有一个Server类,这个类实际上继承了HttpServer,当启动Jetty服务器时,具体来说,在Jetty根目录下命令行下如输入java -jar start.jar etc/demo.xml,注意这里有一个配置文件demo.xml做为运行参数,这个参数也可以是其它的配置文件,也可是多个xml配置文件,其实这个配置文件好比我们使用struts时的struts-config.xml文件,将运行Server需要用到的组件写在里面,比如上一节中HttpServer的配置需要的组件类都可以写在这个配置文件中。
    2.我们自己部署到Jetty的webapps目录下的webapplication,Jetty如何运行我们自己的web application?
    首先当我们按上述方法启动JettyServer时,就会调用Server类里面的main方法,这个入口方法首先会构造一个Server类实例(其实也就构造了一个HttpServer),创建实例过程中就会构造XmlConfiguration类的对象来读取参数配置文件,之后再由这个配置文件产生的XmlConfiguration对象来配置这个Server,配置过程其实是运用Java的反射机制调用Server的方法并传入配置文件中所写的参数来向这个Server添加HttpListener,HttpContext,HttpHandler,webapplication(对应我们自己部署的web应用)。
     添加我们自己的webapplication过程中相应的就会读取我们所熟知的/WEB-INF/web.xml来创建一个WebApplicationContext(这个类继承了HttpContext)的实例,同时也会创建WebApplicationContext自身的ServletHandler(实现了HttpHandler接口),注意到ServletHandler中包含一组ServletHolder指向实际的Servlet,譬如说我们在web.xml文件中配置了两个Filter和一个Servlet,这里就会有三个ServletHolder,实际处理请求时ServeletHandler就会依次调用这三个ServletHolder传入request,response处理(实际最后交给这两个Filter和Servlet处理),这样我们自己做好的一个web应用就挂载到这个Server上了,可以接受客户端相应的request(请求)。
 
四、运行原理(请参考如下时序图)
DSC0002.jpg
  <图 1-7 >
  上图展示了一个request的处理过程,首先HttpListener监听到客户端发来的请求创建一个HttpConnection实例(封装了连接细节,比如从Socket连接中获取的输入流和输出流),HttpConnection对象构建过程中会创建Jetty内部自定义的HttpRequest和HttpResponse对象,接着HttpListener会调用这个HttpConnection实例的handle方法,HttpConnection实例就调用HttpRequest对象的read()方法读取信息,调用HttpServer的service方法以HttpRequest,HttpResponse为参数传给HttpServer,HttpServer又将HttpRequest和HttpResponse分发给相应的HttpCotext,HttpContext最后将HttpRequest和HttpResponse交给自身的HttpHandler处理,在这里HttpRequest,HttpResponse被再次封装为ServletHttpRequest和ServletHttpResponse,其实这两个类实现了我们所熟知的HttpServletRequest和HttpServletResponse接口。
 
五、高级性能
  1.HttpHandler:
    该接口的实现类用于处理HttpContext分发过来的reqeust,不同的实现类的有不同的处理功能,这里介绍几常用的HttpHandler实现类:
    ReourceHandler:用于处理静态内容,如以扩展名为.html的文件
  SecurityHandler:提供基本的安全验证
  ForwardHandler:转发一个request到另一个url
    ServletHandler:用于将request交由具体的Servlet类进行处理
     2.当你在看图 1-2时候会注意到HttpServer和HttpListener,HttpServer与HttpContext,HttpContext与HttpHandler存在一对多的关系,下面就介绍一下它们之间的这种关系如何通过程序来配置.
  HttpListener& HttpServer:
  HttpListener是所有监听器类的接口,如图中的SocketListener(基于传统的Socket技术)就实现了该接口,Jetty还有其它的实现该接口类,如SocketChannelListener(基于NIO技术)类等,HttpListener职责主要是在服务器启动后监听相应端口的来自客户端请求并建立连接(图 1-1中所示用HttpConnection封装连接细节),监听器可在同个IP上开启多个端口为同一个HttpServer进行监听,所以HttpListener和HttpServer是多对一的关系,如下图:
DSC0003.jpg
  <图 1-3 >
     配置代码:
     HttpServerserver = new HttpServer();
     HttpListenrerlistener1 = new SocketChanneListener();
    Listener1.setPort(8080);
     HttpListenrer listener1= new SocketListener();
    Listener1.setPort(8443);
    server.addListener(listener1);
    server.addListener(listener2);
 
  HttpContext& HttpHandler:
  HttpContext相当于对应客户端请求的URL或某个虚拟机,其子类中包含若干个HttpHandler,当接受到request(请求)时,HttpContext会依次(按某个预定的次序)把request交给这些HttpHandler处理,直到这个request被标示处理过为止,需要注意的是这个request可能被多个HttpHandler处理,但只能有一个HttpHandler能标示这个request已被处理过.
    一个典型的HttpContext有用于安全处理、静态资源处理及Servlet类的HttpHandler,如下图:
DSC0004.jpg
<图 1-4>
     配置代码:
     HttpContextcontext = new HttpContext();
    context.setContextPath(“/myapp/*”);
     HttpHandlersecuritHandler = new SecurityHandler();
     HttpHandlerresourceHandler = new ResourceHandler();
     HttpHandlerservletHandler = new ServletHandler();
    context.addHandler(securitHandler);
    context.addHandler(resourceHandler);
    context.addHandler(servletHandler);
 
     HttpServer& HttpContext:
    一般的HTTP服务器软件可以同时处理多个webapplication,同样一个HttpServer可以包含多个HttpContext,如下图可以通过同一个端口的监听类来映射多个HttpContext:
DSC0005.jpg
  <图 1-5 >
     配置代码:
     HttpServerserver = new HttpServer();
     HttpContextcontext1 = new HttpContext();
    context1.setContextPath(“/app1/*”);
     HttpContextcontext2 = new HttpContext();
    context2.setContextPath(“/app2/*”);
    server.addContext(context1);
 
     HttpServer& HttpLister & HttpContext:
  另外Jetty对多网卡(多个IP地址,不同的主机名)的服务器也提供了很好的支持,每个HttpContext都有自身的HttpServer:
DSC0006.jpg
  <图 1-6 >
     配置代码:
     HttpServerserver1 = new HttpServer();
     SocketListenerlistener1 = new SocketListener();
  listener1.setHost(“www.app1.com”);//orListener1.setHost(“www.app2.com”)
  listener2.setPort(80);
  HttpContextcontext1 = new HttpContext();
  context1.setContextPath(“/”);
    server1.addListener(listener1);
  server1.addContext(context1);
 
     3.Jetty对高并发的支持
DSC0007.jpg
<图 1-8>
    如果多用户请求服务就会涉及到多线程的管理,如图1-8,Jetty中主要由ThreadPool负责管理多线程,注意其中Pool.PondLife是Pool的一个内部接口,ThreadPool.PoolThread是ThreadPool的一个内部线程类,我们看到Pool.PondLife和Pool存在一个聚集的关系,实际上Pool对象中存放在是一个个ThreadPool.PoolThread线程对象,当有新用户连接上Server时,ThreadPool就从Pool中取一个空闲的线程为当前用户连接服务。
 
六、小结
  本文通过图示简要介绍了Jetty整个体系架构和主要的组件类及服务器的启动执行过程,其实Jetty 通常被用来做为内嵌的Web Server来使用,一些常见的服务器软件,如Apache Cocoon、JBoss,JOnAs等都会采用Jetty作为Web解決方案;另外由于Jetty在性能及稳定性要优于同类HTTPServer的原因,Jetty已在国外已很流行,鉴于这一点,本文作者可以预测在不久的将来Jetty同样也会在国内流行开来。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-347300-1-1.html 上篇帖子: jetty源码架构分析 下篇帖子: jetty中的JNDI实现分析
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表