`
leibinhui
  • 浏览: 11310 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【原创】高性能WEB服务器——之Jetty (N)I/O

阅读更多

高性能WEB服务器——之Jetty (N)I/O组件

 

简介:Jetty是一个当前非常活跃的并且很有前景的Servlet引擎和WEB容器。本文所讨论的主题建立在Jetty 9版本之上,通过本文对Jetty I/O的组件结构的介绍,您将充分了解到Jetty是如何做到支持高并发网络请求的。

(一)先简单谈谈I/O

Jetty是一个WEB容器,所以本文所讨论的I/O主要是面向流的I/O,即:针对网络连接的I/O

UNIX下的五种I/O模型,分别是:

(1)阻塞式I/O模型;

(2)非阻塞式I/O模型;

(3)I/O复用模型;

(4)信号驱动I/O

5)异步I/O

根据POSIX的定义:同步I/O操作导致请求进程阻塞一直到I/O操作完成;而异步I/O不会导致请求进程的阻塞。根据上述定义,前四种模型都会阻塞请求进程的处理,所以都是同步I/O模型;只有最后一种满足POSIX的定义是异步I/O模型。

JettyIO组件采用的是那种I/O模型呢? Jetty基于NIO非阻塞的I/O复用模型来实现了IO组件。自JDK1.4 Java提供的NIO 1.0框架主要是基于I/O复用模型,从JDK1.7开始 Java NIO 2.0开始支持异步I/O所以本文的真正目的是带领大家窥视JettyJava NIO I/O复用模型包装的实现细节。

 

(二)为什么是NIO而不是OIO

NIO其实不是神话:通常只有在需要支持大量链接(通常数百或者数以千计的链接)和高并发场景下,NIO才能带来可观的性能优势。对于一般的应用如果连接数和并发都不高的场景中NIO 不会带来很大性能上提高,反而使用OIO也许会更快,比如桌面应用。

Jetty作为WEB容器需要支持大量链接和在高并发的场景中,所以NIO在某种程度上是Jetty作为高性能服务器的有力支点。

NIO虽然屏蔽了平台差异性,但基于不同OS平台的IO系统NIO实现仍然是存在差异的,这使得我们的编程陷阱重重。其实这也是本文的另一个理由:让我们来了解下Jetty是如何来规避这些问题。

(三)ReactorProactor

JDK1.7 之前,采用Reactor + Handler模式是大多数高性能服务器通讯框架的所采用的基础模型,如MinaNetty:主要针对于非阻塞同步I/O;相反Proactor模式是非阻塞异步I/O通讯框架采用的模型,有兴趣的读者可以研究下grizzly,在grizzly的最新版本中已经有基于异步I/O 的实现。

Reactor 的模型和Proactor模型的最大区别在于:真正的读写操作在Proactor中是由操作系统完成的(取决于操作系统支持异步API),请求进程在系统处理完之后会得到一个反馈或者是回调,这完全是系统级别的异步处理;而对于Reactor模式,实际的数据读写操作由发起请求的进程来处理:通过不断的注册感兴趣的事件操作,一直到数据处理完毕,事件取消为止。

通过在Reactor 上来模拟Proactor模式是大多数高性能服务器通讯框架通常在实际实现上采用的通用策略,无论是MinaNetty还是Jetty I/O

 

好了,到目前为止我们的基础知识就先聊到这里为止,在接下来让我们一起来探究Jetty I/O组件模型的实现吧。

(四)Jetty NIO实现

在具体分析代码之前先简单梳理下Jetty NIO组件的基本内容:

1EndPoint 网络上进行相互通信的对端实体抽象

2Connection:网络实体通信链接的抽象

3ByteBufferPool:缓冲区对象池

3SelectChannelEndPoint:基于NIO模型描述的EndPoint封装

4SelectorManager选择器管理器

JettyIO组件中大概就这么多内容,简单易懂非常适合研习。这也是本文想从Jetty入手来介绍NIO的一个考虑。

整个Jetty NIO组件架构是基于Reactor 模型,并采用异步处理方式,也就是我们上文提到的通过在Reactor 上来模拟Proactor模式的实现策略。要知道在高并发的网络请求处理中,不能因为某一个TCP链接的处理异常而导致其它连接无法及时的被响应,这在高性能网络服务器设计中是不能容忍的。基于Proactor或者是伪Proactor模型可以使得网络连接的处理具备极高的扩展性和响应性。

Jetty IO是基于非阻塞同步IO来设计和实现,也就是基于NIO 1.0 架构。好了,到了该上代码的时候了。

 

     a)缓冲区对象池

Jetty在连接开始建立之前,内置了一个缓冲区对象池。采用缓冲池的好处一个是:当需要通讯的网络对端有读写操作时,通过从缓冲区对象池获取可用的Buffer来提高读写的响应速度,有点类似于Memcache的内存处理方式。在Mina中也有这样的设计;那另外一个就是好处就是:便于内存管理。

 

下面ByteBufferPool 的部分代码清单:

public ArrayByteBufferPool() {

       this(64,2048,64*1024);

}

public ArrayByteBufferPool(int minSize, int increment, int maxSize) {

      _min=minSize;

      _inc=increment;

         _direct=new Bucket[maxSize/increment];

      _indirect=new Bucket[maxSize/increment];

      int size=0;

      for (int i=0;i<_direct.length;i++) {

            size+=_inc;

          _direct[i]=new Bucket(size);

          _indirect[i]=new Bucket(size);

   }

}

从上面代码可以看出,两个Bucket 桶分别用来存放直接缓冲区的大小和堆缓冲区的大小。Bucket 桶的大小都为32,最小的缓冲区大小为2048,最大为32 * 2048。当需要使用的时候可以直接从缓冲区中分配指定大小的缓冲区。

bReactor 机制

Java NIO最大的价值在于可以通过一个线程来监控大量链接的读写就绪状态,使得高并发的网络连接可以被及时的处理和响应。试想传统服务器采用每个请求一个进程的模式,或者每个请求一个线程的模型,这种模型在连接数不大的情况下是没有问题的,但是要处理成千上万的并发请求时,如果采用上述模式,那么服务器的资源很快就会被消耗殆尽,服务很快会变得不可用。在*nix系统中很早就有selectpoll函数的APIC 程序员使用,在Java中直到JDK 1.4的时才具备这样的IO处理能力。

Reactor线程在这里可以看作就是我们要将的Selector线程,用以监控大量通道的就绪状态。一般情况下启动一个Selector线程是完全可以,不仅消除了多个线程管理的额外开销,同时可以降低复杂性,提高吞吐量并可能大幅度提高性能。这对于单CPU系统来说是一个很好的策略,但是对于多于一个(比如N个)CPU的系统来说,可能就会有N-1CPU处于空闲状态。让我们来看看Jetty是如何做的呢?

 

下面Selector线程数大小的部分代码清单:

protected SelectorManager(Executor executor, Scheduler scheduler) {

 this(executor, scheduler, (Runtime.getRuntime().availableProcessors() + 1) / 2);

}

protected SelectorManager(Executor executor, Scheduler scheduler, int selectors) {

  this.executor = executor;

  this.scheduler = scheduler;

  _selectors = new ManagedSelector[selectors];

}

 

Jetty默认Selector线程数大小为: (Runtime.getRuntime().availableProcessors() + 1) / 2。且不说Jetty这样做性能到底能提升多少,笔者这里也没有对Jetty做过实际的压测分析,不可妄加推测。但是对于大多数场景中使用一个Selector线程通常完全可以满足要求,毕竟就绪选择的大多数工作是有底层操作系统完成的,使用一个Selector线程这样可能会简单一些,而简单的就是好的^_^

C)异步CallBack与线程池

从上文的讨论我们得知,真正能做到系统级别的异步IO,也就是我们所说的真正的异步IO能力,这需要操作系统在体层提供支持,如Linux aio_read函数,这一点非常重要否则就不能说是真正的异步IOJDK1.7 NIO 2.0框架中为我们提供了异步IO处理的选择。我们使用异步IO方式可以简单的归纳为两种方式:(1)基于Future模型;(2)基于CallBack机制。

Jetty中虽然没有使用异步IO模型,但是Jetty采用了回调机制来处理Socket读。注意这里的回调还是建立在非阻塞同步IO之上,不同于上面所说的异步IO CallBack机制。区别在于真正处理Socket数据读的线程是Reactor线程本身还是另外一个线程。

Jetty提供了一个开关,可以选在在Reactor线程上直接执行读操作,也可以在另外一个线程上处理真正的读操作。

 

下面ReadCallback的部分代码清单:

private class ReadCallback implements Callback, Runnable {

        @Override

        public void run() {

           // ...........................................................................

        }

        @Override

        public void succeeded() {

            if (_executeOnfillable)

                _executor.execute(this);

            else

                run();

        }

}

 

参数executeOnfillableJetty中默认的设置是true,这样做的好处非常明显。Reactor线程的职责定位非常清楚,仅监控大量通道连接上就绪事件,而真正繁重的IO任务处理交给其它线程处理,在高并发网络请求处理中请求响应的处理速度就会进一步的得到提升。

D)事件通知与状态机

Jetty在处理网络连接和Socket数据读写的时候基于事件机制,也可以理解为Java中观察者模式。当Connection连接建立时,Socket数据可读,数据已写,连接通道关闭时都是以事件的方式通知给各个观察者。这使得Jetty的整个IO生命周期的控制非常的松散,低耦合。这种方式日常工作当中运用的也是非常多的,不必细说,还是直接上代码吧。

 

下面NetworkTrafficListener的部分代码清单:

public interface NetworkTrafficListener

{

public void opened(Socket socket);

public void incoming(Socket socket, ByteBuffer bytes);

public void outgoing(Socket socket, ByteBuffer bytes);

public void closed(Socket socket);

}

 

Jetty在内部的使用了大量的状态机制用于控制处理的过程。比如对于socket读也使用了状态机机制,来协调、控制和监控socket数据的读取过程。

 

下面Socket读状态机:State 的状态标志代码清单:

private enum State

{

IDLE, INTERESTED, FILLING, FILLING_INTERESTED

}

(五)总结

本文以(NIO为主线,以Jetty NIO组件为依托,简单描述和分析了高性能WEN 容器Jetty在处理IO时的一些设计和考虑,当然本文只是抽出了Jetty IO实现的部分亮点来介绍的还不是很完整

 

 

如需转载,请注明出处。

分享到:
评论

相关推荐

    安卓Android源码——i-jetty开源项目.zip

    Jetty是一个轻量级、高性能的Java Web服务器和HTTP协议栈,广泛应用于嵌入式系统和移动设备中,如Android。 在Android平台上,由于系统资源有限,传统的Web服务器可能无法高效运行,而Jetty因其小巧、快速和低内存...

    jetty启动器资源配置文件

    它支持最新的Java EE标准,并且具备轻量级、高性能等特点,适用于开发测试环境以及生产环境中的Web应用服务器。Jetty通过一系列的配置文件来管理其运行时的行为与设置。本文主要介绍Jetty的启动配置文件——`jetty....

    jetty-distribution-9.1.0.v20131115

    3. **高性能**:Jetty使用NIO(非阻塞I/O)模型,提高了并发处理能力,适用于高流量的Web应用。 4. **模块化**:Jetty的组件设计允许用户只选择需要的部分,避免了不必要的资源消耗。 5. **兼容性**:Jetty完全支持...

    jetty-distribution-9.2.2.v20140723.zip

    Jetty是一个轻量级、高性能且开源的Java Web服务器和HTTP服务器库,广泛用于开发、测试和部署Web应用程序。在此次讨论中,我们关注的是Jetty的特定版本——"jetty-distribution-9.2.2.v20140723.zip"。这个压缩包...

    Jetty源码分析.pdf

    - **Jetty**是一款**100%纯Java编写**的轻量级Web服务器与Servlet容器,与Tomcat等其他流行的Web服务器相比,Jetty以其**体积小、启动快**而著称。 - **快速高效**:Jetty作为最快的Servlet服务器之一,能够处理大量...

    jetty 入门实例

    Jetty是一款轻量级、高性能的Java Web服务器和Servlet容器,它被广泛用于开发、测试和部署Web应用程序。本文将深入探讨Jetty的入门实例,帮助你快速掌握如何使用Jetty来运行简单的Web应用。 首先,让我们理解什么是...

    jmeter--web socket引用插件包

    1. **jetty-util-9.4.12.v20180830.jar**: Jetty是一个轻量级的Java Web服务器和Servlet容器,这里的jetty-util库提供了许多用于网络和I/O操作的实用工具。 2. **websocket-common-9.4.12.v20180830.jar**: 这是...

    Jetty cometd(Continuation)学习笔记

    它以其小巧、稳定和高性能的特点受到广泛赞誉,适合企业级应用的需求。Jetty遵循Apache Licence 2.0和Eclipse Public License 1.0,用户可以自由地将其应用于商业项目。 Jetty 7版本引入了一个重要的新特性——支持...

    maven工程在Jetty服务器上的自动化部署(开发者模式)

    3. **Jetty服务器**:Jetty是一个轻量级、高性能的Servlet容器,常用于开发和测试环境。它可以直接运行未打包的Web应用,适合快速迭代和调试。 4. **Jetty-Maven插件配置**:学习如何在`pom.xml`文件中配置Jetty...

    Eclipse Jetty插件

    Jetty是一款轻量级、高性能的Java Web服务器和HTTP协议栈,广泛用于开发、测试和部署Web应用程序。 在Eclipse中安装Jetty插件,可以通过以下步骤进行: 1. **下载插件**:首先,你需要获取到包含`features`和`...

    架构解析——Tomcat

    总的来说,《架构解析——Tomcat》是一本深入了解Tomcat工作原理、配置和优化的实用书籍,对于Java Web开发人员、系统管理员以及对Web服务器技术感兴趣的人来说,具有很高的学习价值。通过深入学习,读者不仅可以...

    Java Web应用教程——网上购物系统的实现

    在开发过程中,开发者通常会使用如Apache Tomcat、Jetty或GlassFish这样的Web服务器进行部署和运行。 ### 网上购物系统架构 网上购物系统是一种典型的电子商务应用,其架构设计需考虑高并发、安全性、数据一致性等...

    深入体验Java_Web开发内幕—核心基础 完整版 pdf

    9. **性能优化与调试**:如何通过优化代码、调整服务器配置等方式提高Web应用的性能,以及如何使用调试工具定位和解决问题。 10. **持续集成与自动化测试**:如Jenkins、Maven和JUnit等工具在持续集成和自动化测试...

    JSP源码——MeyboMail Web(Java)开源简化_meybomailweb.zip

    高性能的邮件系统需要处理大量的并发请求。MeyboMail Web可能利用了线程池、缓存技术等手段来提升性能。开发者可以从源码中学习如何设计和优化这类高并发的Web应用。 **用户界面与前端技术** 尽管MeyboMail Web...

    web学习笔记 —— 数据源

    3. **配置数据源**:在Web应用服务器如Tomcat、Jetty或JBoss中,数据源的配置通常在服务器的配置文件中完成,如Tomcat的`context.xml`或`server.xml`。配置项包括数据库驱动类、URL、用户名、密码等。在Spring框架中...

    jetty-util-ajax-9.2.1.v20140609.zip

    Jetty是一款轻量级、高性能的开源HTTP服务器和Servlet容器,广泛应用于Java Web应用的开发和部署。这个zip文件可能包含了源代码、构建脚本和其他相关资源,便于开发者理解和使用Jetty的AJAX库。 【描述】"nebula-...

    jboss内核(能运行web程序)

    Jetty是一款轻量级、高性能的服务器,常用于嵌入式系统和测试环境。JBoss内核可以集成Jetty,提供更快速的启动时间和较低的内存占用,适合小型Web应用程序或开发阶段的快速迭代。 ### 运行Web程序的步骤 1. **安装...

    pool-enhanced-2.0.0.zip

    Jetty Nosql Memcached是基于著名的Java Web服务器Jetty的一个扩展,其目的是通过集成NoSQL数据库——Memcached来实现高效率的会话存储。Memcached是一种分布式内存缓存系统,它能够快速存储和检索数据,为Web应用...

    学校课程设计——OA系统

    【标题】:“学校课程设计——OA系统” 【描述】:“技术栈:SpringBoot、Mybatis、JWToken、Mysql、Redis” 这个课程设计项目是一个办公自动化(OA)系统,采用了现代Java Web开发中的主流技术和框架。以下是这些...

    02 Web应用程序的工作原理.ppt

    动态网站提供了丰富的交互性和个性化体验,但同时也增加了服务器的计算和存储负担,对服务器性能和数据库管理提出了更高的要求。 总结起来,Web应用程序从静态网站到动态网站的发展,反映了互联网技术的演进和用户...

Global site tag (gtag.js) - Google Analytics