`
zhaohaolin
  • 浏览: 1010959 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Netty服务器线程模型概览【转】

 
阅读更多

一切从ServerBootstrap开始

ServerBootstrap负责初始话netty服务器,并且开始监听端口的socket请求。

JAVA
1
2
3
4
5
6
7
8
9
10
bootstrap bootstrap = new ServerBootstrap(
	new NioServerSocketChannelFactory(
		Executors.newCachedThreadPool(),//boss线程池
		Executors.newCachedThreadPool()//worker线程池
	)
);
bootstrap.setPipelineFactory(new HttpChannelPipelineFactory());
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
bootstrap.bind(new InetSocketAddress(httpPort));//端口开始监听

ServerBootstrap用一个ServerSocketChannelFactory 来实例化。ServerSocketChannelFactory 有两种选择,一种是NioServerSocketChannelFactory,一种是OioServerSocketChannelFactory。前者使用NIO,后则使用普通的阻塞式IO。它们都需要两个线程池实例作为参数来初始化,一个是boss线程池,一个是worker线程池。

ServerBootstrap.bind(int)负责绑定端口,当这个方法执行后,ServerBootstrap就可以接受指定端口上的socket连接了。一个ServerBootstrap可以绑定多个端口。

 

boss线程和worker线程

可以这么说,ServerBootstrap监听的一个端口对应一个boss线程,它们一一对应。比如你需要netty监听80和443端口,那么就会有两个boss线程分别负责处理来自两个端口的socket请求。在boss线程接受了socket连接求后,会产生一个channel(一个打开的socket对应一个打开的channel),并把这个channel交给ServerBootstrap初始化时指定的ServerSocketChannelFactory来处理,boss线程则继续处理socket的请求。

ServerSocketChannelFactory则会从worker线程池中找出一个worker线程来继续处理这个请求。
如果是OioServerSocketChannelFactory的话,那个这个channel上所有的socket消息消息,从开始到channel(socket)关闭,都只由这个特定的worker来处理,也就是说一个打开的socket对应一个指定的worker线程,这个worker线程在socket没有关闭的情况下,也只能为这个socket处理消息,无法服务器他socket。

如果是NioServerSocketChannelFactory的话则不然,每个worker可以服务不同的socket或者说channel,worker线程和channel不再有一一对应的关系。
显然,NioServerSocketChannelFactory只需要少量活动的worker线程及能很好的处理众多的channel,而OioServerSocketChannelFactory则需要与打开channel等量的worker线程来服务。

线程是一种资源,所以当netty服务器需要处理长连接的时候,最好选择NioServerSocketChannelFactory,这样可以避免创建大量的worker线程。在用作http服务器的时候,也最好选择NioServerSocketChannelFactory,因为现代浏览器都会使用http keepalive功能(可以让浏览器的不同http请求共享一个信道),这也是一种长连接。

worker线程的生命周期(life circle)

当某个channel有消息到达或者有消息需要写入socket的时候,worker线程就会从线程池中取出一个。在worker线程中,消息会经过设定好的ChannelPipeline处理。ChannelPipeline就是一堆有顺序的filter,它分为两部分:UpstreamHandler和DownStreamHandler。本文着重介绍netty的线程模型,所以关于pipeline的内容从简说明。

 


客户端送入的消息会首先由许多UpstreamHandler依次处理,处理得到的数据送入应用的业务逻辑handler,通常用SimpleChannelUpstreamHandler来实现这一部分。

 

JAVA
1
2
3
4
5
public class SimpleChannelUpstreamHandler{
	public void messageReceived(ChannelHandlerContext c,MessageEvent e) throws Exception{
		//业务逻辑开始掺入
	}
}

对于Nio当messageReceived()方法执行后,如果没有产生异常,worker线程就执行完毕了,它会被线程池回收。业务逻辑hanlder会通过一些方法,把返回的数据交给指定好顺序的DownStreamHandler处理,处理后的数据如果需要,会被写入channel,进而通过绑定的socket发送给客户端。这个过程是由另外一个线程池中的worker线程来完成的。

对于Oio来说,从始到终,都是由一个指定的worker来处理。

减少worker线程的处理占用时间

worker线程是由netty内部管理,统一调配的一种资源,所以最好应该尽快的把让worker线程执行完毕,返回给线程池回收利用。worker线程的大部分时间消耗在在ChannelPipeline的各种handler中,而在这些handler中,一般是负责应用程序业务逻辑掺入的那个handler最占时间,它通常是排在最后的UpstreamHandler。所以通过把这部分处理内容交给另外一个线程来处理,可以有效的减少worker线程的周期循环时间。一般有两种方法:

messageReceived()方法中开启一个新的线程来处理业务逻辑

JAVA
1
2
3
4
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception{
	 ...
	 new Thread(...).start();
}

在messageReceived()中开启一个新线程来继续处理业务逻辑,而worker线程在执行完messageReceived()就会结束了。更加优雅的方法是另外构造一个线程池来提交业务逻辑处理任务。

利用netty框架自带的ExecutionHandler

基本使用方法

JAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 public class DatabaseGatewayPipelineFactory implements ChannelPipelineFactory {
 
     private final ExecutionHandler executionHandler;
 
     public DatabaseGatewayPipelineFactory(ExecutionHandler executionHandler) {
         this.executionHandler = executionHandler;
     }
 
     public ChannelPipeline getPipeline() {
         return Channels.pipeline(
                 new DatabaseGatewayProtocolEncoder(),
                 new DatabaseGatewayProtocolDecoder(),
                 executionHandler, // 多个pipeline之间必须共享同一个ExecutionHandler
                 new DatabaseQueryingHandler());//业务逻辑handler,IO密集
     }
 }

把共享的ExecutionHandler实例放在业务逻辑handler之前即可,注意ExecutionHandler一定要在不同的pipeline之间共享。它的作用是自动从ExecutionHandler自己管理的一个线程池中拿出一个线程来处理排在它后面的业务逻辑handler。而worker线程在经过ExecutionHandler后就结束了,它会被ChannelFactory的worker线程池所回收。

它的构造方法是ExecutionHandler(Executor executor) ,很显然executor就是ExecutionHandler内部管理的线程池了。netty额外给我们提供了两种线程池:
MemoryAwareThreadPoolExecutor和OrderedMemoryAwareThreadPoolExecutor,它们都在org.jboss.netty.handler.execution 包下。
MemoryAwareThreadPoolExecutor确保jvm不会因为过多的线程而导致内存溢出错误,OrderedMemoryAwareThreadPoolExecutor是前一个线程池的子类,除了保证没有内存溢出之外,还可以保证channel event的处理次序。具体可以查看API文档,上面有详细说明。

--EOF--
分享到:
评论

相关推荐

    Netty服务器线程模型概览-线程模型

    Netty服务器线程模型概览_线程模型

    Netty实现原理浅析.pdf

    3. **多Reactor多线程模型**:这是Netty默认采用的模型。它进一步将Reactor分为两个角色——主Reactor(Boss)和次Reactor(Worker)。主Reactor负责监听服务器套接字,接受新的连接请求,并将其分配给次Reactor。次...

    Netty_in_Action_v10_MEAP

    - **第15章:事件循环与线程模型**:深入研究Netty的线程模型,特别是事件循环机制。 - **第16章:案例研究,第一部分**:通过Droplr、Firebase和UrbanAirship等公司的实际案例,展示Netty的实际应用效果。 - **...

    netty权威指南

    虽然正文中没有提供书的具体章节安排,但可以推测,作为一本权威指南,它将从Netty的基础架构和工作原理讲起,可能包括网络IO模型的基础知识、Netty的事件模型、核心组件的介绍、实际案例的剖析以及性能优化和调试...

    Netty权威指南 第2版 带书签目录 完整版.pdf

    第二部分则深入到了Netty的内部原理,包括Netty的启动流程、核心组件的内部运作机制、线程模型与并发模型,以及如何进行高效的内存管理。 对于Netty的学习者来说,了解其架构设计是非常重要的。Netty采用了模块化的...

    netty源码解析视频

    - Netty采用了多线程模型来处理网络I/O操作。 - 主要包括`BossGroup`和`WorkerGroup`两种线程池。 - `BossGroup`负责接受客户端连接请求,而`WorkerGroup`则负责处理网络读写操作。 #### 四、Netty高级特性 1. ...

    Netty_in_Action(第五版目录修正)

    - **线程模型概述**:解释Netty中的不同线程模型及其优缺点。 - **最佳实践**:给出选择合适线程模型的最佳实践建议。 **第16章:在EventLoop中取消注册/重新注册** - **EventLoop机制**:深入探讨EventLoop的工作...

    Netty In Action(中文版)【高清】

    5. **线程模型与事件循环**:解析Netty的事件驱动模型,探讨EventLoopGroup和EventLoop的运作机制,以及如何通过它们实现线程池优化。 6. **Netty的连接管理**:讨论连接的创建、管理和关闭,包括连接的建立、心跳...

    Java Netty-入门教程.pdf

    - **Spring 5.x**:引入了 Flux API,并且完全放弃了 Tomcat,转而使用 Netty 作为服务器端。 - **Zookeeper**:分布式协调服务。 这些框架之所以选择 Netty,主要是因为其在网络通信方面提供了高性能、高可靠性的...

    尚硅谷NIO百度云连接

    4. **性能优化**:探讨如何利用NIO进行性能优化,比如合理配置缓冲区大小、优化多线程模型等。 5. **实战项目**:提供完整的实战项目,让学员能够在实践中巩固所学知识,增强解决实际问题的能力。 综上所述,...

    高并发编程实战1,2,3阶段

    - **Netty框架**:基于事件驱动模型的高性能网络通信框架。 ##### 4. 性能调优与监控 - **JVM参数调整**:如-Xms、-Xmx、-XX:+UseConcMarkSweepGC等。 - **线程分析工具**:VisualVM、jstack命令行工具。 - **性能...

    java网络编程高清pdf

    - **定义**:在BIO模型中,客户端与服务器建立连接后,客户端发起的数据读取或写入操作会导致线程阻塞,直至操作完成。这种模型简单易懂,但在高并发场景下,每个连接都需要分配一个独立的线程来处理,容易导致资源...

    seata源码研究.docx

    - **Netty**:Netty使用NIO实现了一套高效、可扩展的网络编程模型。通过提供一系列API,开发者可以专注于业务逻辑而非底层网络编程细节。 ##### 2. TM(Transactional Manager)实现原理解析 TM在分布式事务中扮演...

    跳槽涨薪精选面试题.pdf

    ### 跳槽涨薪精选面试题概览 在当今快速发展的IT行业中,技术更新换代的速度非常快,为了能够顺利地跳槽并获得理想的薪资涨幅,掌握最新的技术和面试技巧至关重要。本文将根据提供的文件标题、描述以及部分内容,对...

    consumer.start.pdf

    11. **NettyRemotingClient**:基于 Netty 的远程通信客户端,用于客户端与消息服务器之间的通信。 12. **PullMessageService**:负责从消息服务器拉取消息的服务。 13. **RebalanceService**:用于消息队列重平衡的...

    大数据课程体系

    - **Netty异步io通信框架**:学习Netty框架的特点及其在高并发服务器开发中的应用。 - **Zookeeper实现netty分布式架构的高可用**:利用Zookeeper保障Netty服务的高可用性。 #### 九、消息队列Kafka - **kafka是...

Global site tag (gtag.js) - Google Analytics