`
liangguanhui
  • 浏览: 113127 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

浅谈Tomcat6使用NIO后对ThreadLocal的影响

阅读更多
  很早就听说tomcat6使用nio了,这几天突然想到一个问题,使用nio代替传统的bio,ThreadLocal岂不是会存在冲突?
  
  
  
  首先,何谓nio?
  
  如果读者有socket的编程基础,应该会接触过堵塞socket和非堵塞socket,堵塞socket就是在accept、read、write等IO操作的的时候,如果没有可用符合条件的资源,不马上返回,一直等待直到有资源为止。而非堵塞socket则是在执行select的时候,当没有资源的时候堵塞,当有符合资源的时候,返回一个信号,然后程序就可以执行accept、read、write等操作,这个时候,这些操作是马上完成,并且马上返回。而windows的winsock则有所不同,可以绑定到一个EventHandle里,也可以绑定到一个HWND里,当有资源到达时,发出事件,这时执行的io操作也是马上完成、马上返回的。一般来说,如果使用堵塞socket,通常我们时开一个线程accept socket,当有socket链接的时候,开一个单独的线程处理这个socket;如果使用非堵塞socket,通常是只有一个线程,一开始是select状态,当有信号的时候马上处理,然后继续select状态。
  
  按照大多数人的说法,堵塞socket比非堵塞socket的性能要好。不过也有小部分人并不是这样认为的,例如Indy项目(Delphi一个比较出色的网络包),它就是使用多线程+堵塞socket模式的。另外,堵塞socket比非堵塞socket容易理解,符合一般人的思维,编程相对比较容易。
  
  nio其实也是类似上面的情况。在JDK1.4,sun公司大范围提升Java的性能,其中NIO就是其中一项。Java的IO操作集中在java.io这个包中,是基于流的阻塞API(即BIO,Block IO)。对于大多数应用来说,这样的API使用很方便,然而,一些对性能要求较高的应用,尤其是服务端应用,往往需要一个更为有效的方式来处理IO。从JDK 1.4起,NIO API作为一个基于缓冲区,并能提供非阻塞O操作的API(即NIO,non-blocking IO)被引入。
  
  BIO与NIO一个比较重要的不同,是我们使用BIO的时候往往会引入多线程,每个连接一个单独的线程;而NIO则是使用单线程或者只使用少量的多线程,每个连接共用一个线程。
  
  
  
  这个时候,问题就出来了:我们非常多的java应用是使用ThreadLocal的,例如JSF的FaceContext、Hibernate的session管理、Struts2的Context的管理等等,几乎所有框架都或多或少地应用ThreadLocal。如果存在冲突,那岂不惊天动地?
  
  后来终于在Tomcat6的文档(http://tomcat.apache.org/tomcat-6.0-doc/aio.html)找到答案。根据上面说明,应该Tomcat6应用nio只是用在处理发送、接收信息的时候用到,也就是说,tomcat6还是传统的多线程Servlet,我画了下面两个图来列出区别:
  
  
  
  tomcat5:客户端连接到达 -> 传统的SeverSocket.accept接收连接 ->  从线程池取出一个线程 -> 在该线程读取文本并且解析HTTP协议 -> 在该线程生成ServletRequest、ServletResponse,取出请求的Servlet -> 在该线程执行这个Servlet -> 在该线程把ServletResponse的内容发送到客户端连接 -> 关闭连接。
  
  我以前理解的使用nio后的tomcat6:客户端连接到达 -> nio接收连接 -> nio使用轮询方式读取文本并且解析HTTP协议(单线程) -> 生成ServletRequest、ServletResponse,取出请求的Servlet -> 直接在本线程执行这个Servlet -> 把ServletResponse的内容发送到客户端连接 -> 关闭连接。
  
  实际的tomcat6:客户端连接到达 -> nio接收连接 -> nio使用轮询方式读取文本并且解析HTTP协议(单线程) -> 生成ServletRequest、ServletResponse,取出请求的Servlet -> 从线程池取出线程,并在该线程执行这个Servlet -> 把ServletResponse的内容发送到客户端连接 -> 关闭连接。
  
  
  
  从上图可以看出,BIO与NIO的不同,也导致进入客户端处理线程的时刻有所不同:tomcat5在接受连接后马上进入客户端线程,在客户端线程里解析HTTP协议,而tomcat6则是解析完HTTP协议后才进入多线程,另外,tomcat6也比5早脱离客户端线程的环境。
  
  实际的tomcat6与我之前猜想的差别主要集中在如何处理servlet的问题上。实际上即使抛开ThreadLocal的问题,我之前理解tomcat6只使用一个线程处理的想法其实是行不同的。大家都有经验:servlet是基于BIO的,执行期间会存在堵塞的,例如读取文件、数据库操作等等。tomcat6使用了nio,但不可能要求servlet里面要使用nio,而一旦存在堵塞,效率自然会锐降。
  
  
  
  
  所以,最终的结论当然是tomcat6的servlet里面,ThreadLocal照样可以使用,不存在冲突。
  
  
  
  
  
  
  
分享到:
评论
3 楼 xuhang1128 2011-11-20  
  public boolean processSocket(NioChannel socket, SocketStatus status, boolean dispatch) {
        try {
            KeyAttachment attachment = (KeyAttachment)socket.getAttachment(false);
            attachment.setCometNotify(false); //will get reset upon next reg
            SocketProcessor sc = processorCache.poll();
            if ( sc == null ) sc = new SocketProcessor(socket,status);
            else sc.reset(socket,status);
            if ( dispatch && getExecutor()!=null ) getExecutor().execute(sc);
            else sc.run();
        } catch (RejectedExecutionException rx) {
            log.warn("Socket processing request was rejected for:"+socket,rx);
            return false;
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            // This means we got an OOM or similar creating a thread, or that
            // the pool and its queue are full
            log.error(sm.getString("endpoint.process.fail"), t);
            return false;
        }
        return true;
    }这是NioEndpoint.java的代码,我发现tomcat仅仅在处理客户端的请求的时候是Non Blocking,真正Read HTTP Body和之前的一系列的动作都是在线程池里面做的
2 楼 slangmgh 2007-10-06  
当控制权到达Servlet的时候,只要你不去调用创建新线程进行异步或者同步调用的情况(有可能产生这种情况的是你调用一个EJB,并且定义这个EJB在不同于Servlet的线程池中执行),当然一切都在同一个线程中,ThreadLocal当然也是安全的。

所谓NIO一般都在Servlet之前,和Servlet之后是没有关系的。
1 楼 mark.li.guyu 2007-10-05  
Thanks for your answer.
前几天还在担心这个问题。

相关推荐

    手写 tomcat nio

    这个过程不仅可以帮助我们深入理解Tomcat的工作原理,还能提升对Java NIO框架的掌握。然而,需要注意的是,实际的Tomcat服务器远比这个简化的实现复杂,它包含了更多的细节处理和优化。在实际项目中,如果需要高性能...

    tomcat7.0.69 + nio + redis session共享 配置优化版

    1、关闭了几乎不再使用的 ajp 协议配置(server.xml), 2、 启用nio 和 线程池配置 (server.xml) 3、修改了context.xml ,添加redis 支持(注意redis 连接密码) 4、在Root目录添加了test.jsp 用于查看多tomcat...

    浅谈tomcat一些细节配置

    【标题】:“浅谈Tomcat一些细节配置” Tomcat,作为Apache软件基金会的开源项目,是Java Servlet和JavaServer Pages(JSP)的容器,也是Java EE Web应用程序的标准实现。在实际开发和部署中,对Tomcat进行适当的...

    浅谈java中nio的使用方式

    读取数据时,数据会被读入Buffer,处理后再清空Buffer以备下次使用。 总结来说,Java NIO提供了一种高效、非阻塞的I/O模型,通过Channel、Selector和Buffer,可以更灵活地处理网络连接和文件I/O,尤其适合处理高...

    tomcat6到8windows版本.zip

    【标题】"tomcat6到8windows版本.zip" 涵盖了三个不同版本的Apache Tomcat,分别是Tomcat 6、Tomcat 7和Tomcat 8.5,这些都是针对Windows操作系统设计的64位版本。Apache Tomcat是一款开源的Java Servlet容器,主要...

    从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式

    在构建高性能的网络服务器时,非阻塞I/O...例如,作者创建了一个简单的NIO Server,能够在保持6万连接的同时承受3到4万TPS的负载,验证了这种模式的有效性。这个模式对于未来设计高性能的网络服务具有很高的参考价值。

    tomcat:Java使用nio模式实现tomcat

    为了更好地处理大量并发请求,Tomcat可以配置为使用NIO连接器,即`org.apache.coyote.nio.NioEndpoint`。这种连接器利用Java NIO的非阻塞特性,允许单个线程服务多个客户端请求,提高了服务器的资源利用率和吞吐量。...

    tomcat 版本6、7、8

    【标题】:“Tomcat版本6、7、8”的对比与演变 在Java Web开发领域,Apache Tomcat是一款广泛应用的开源Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)技术规范。Tomcat6、Tomcat7和Tomcat8是三个...

    3-5Tomcat响应请求源码与nio处理请求源码实现.mp4

    3-5Tomcat响应请求源码与nio处理请求源码实现.mp4

    tomcat8.5.56_X64_nio2模式性能优化版+垃圾处理机制.zip

    【标题】:“Tomcat 8.5.56 X64 NIO2模式性能优化版+垃圾处理机制.zip”指的是一个特别针对Windows x64平台优化的Tomcat 8.5.56版本,该版本集成了NIO2(非阻塞I/O)模式,并对垃圾收集(Garbage Collection, GC)...

    tomcat6到8系列.zip

    在实际应用中,Tomcat常与其他Java EE组件如EJB、JMS等结合使用,构建更复杂的企业级应用。同时,由于其轻量级和易于管理的特性,Tomcat也常被用作开发和测试环境。下载这个压缩包,开发者可以进行不同版本的比较,...

    tomcat6安装版

    【标题】"Tomcat6安装版"涉及到的核心知识点是Java Web服务器Apache Tomcat的第六个主要版本。Tomcat是一款开源的、轻量级的应用服务器,主要用于运行Servlet和JSP(JavaServer Pages)应用。它的易用性和高效性使得...

    tomcat6 免安装 解压版

    【描述】:“Tomcat6 免安装版”提供了更为简洁的使用方式,免去了安装程序的步骤,用户可以在下载后直接解压到任意目录。这个纯净版的特点在于,开发者或系统管理员在部署时,不会受到预装示例项目的干扰,因为这些...

    Tomcat6的源码

    4. **Pipeline和Valve**:Tomcat使用Pipeline和Valve概念来实现请求处理的链式结构,每个Valve代表一个处理阶段,Pipeline将它们串联起来。这种设计允许灵活地添加、删除或修改请求处理逻辑。 5. **ClassLoader机制...

    tomcat6 好东西啊

    Apache Tomcat 6 是一款广泛使用的开源应用服务器,专门用于部署和运行Java Servlets和JavaServer Pages(JSP)。这个版本在当时是Tomcat服务器的一个重要里程碑,它提供了许多改进和增强,使得开发者和管理员都能...

    深入浅出NIO

    《深入浅出NIO》 在Java编程领域,NIO(New Input/Output)是一种用于替代标准IO模型的机制,其核心在于非阻塞的I/O操作和通道(Channel)及缓冲区(Buffer)的使用。传统的IO模型,如描述中的“阻塞I/O”,在读写...

    Tomcat 6x应用服务器

    Tomcat 6x完全支持Servlet 2.5和JSP 2.1规范,提供了对这些技术的强大支持。 2. **轻量级架构** 与重量级的应用服务器如IBM WebSphere或Oracle WebLogic相比,Tomcat因其轻量级的特性而受到青睐。它的体积小、启动...

    tomcat6 源代码

    还可以启用NIO模式以提高并发能力,或者使用 APR(Apache Portable Runtime)库提升I/O性能。 9. **扩展性**: Tomcat的模块化设计使得它可以方便地添加或替换组件,如添加其他类型的连接器、替换默认的Jasper JSP...

    tomcat6 windows64位

    - 可以通过调整JVM参数、开启NIO连接器、使用连接池等方式提升Tomcat的性能。 10. **集成开发环境(IDE)**: - 多数IDE如Eclipse、IntelliJ IDEA都支持与Tomcat的集成,可以直接在IDE中启动和部署应用,便于开发...

    tomcat6,7和8

    【标题】:“Tomcat6,7和8”的详解与比较 Tomcat作为一款广泛应用的开源Java Servlet容器,是Apache软件基金会Jakarta项目的核心部分。它主要用于部署和运行Java Web应用程序,包括Servlet和JSP。本篇文章将深入...

Global site tag (gtag.js) - Google Analytics