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

java nio&netty系列之二reactor模型基础

    博客分类:
  • java
 
阅读更多



        上一篇章介绍了下NIO的基础,并且也给出了一个简单的代码示例,但是如果想享受NIO带来的高速的快感,就得使用多线程编程了。那么在使用多线程编程之前,有一些关于多线程的东西想分享下:

一、关于多线程

  • 分享点一:在单核CPU上,多线程不一定能比单线程更好。为什么要使用多线程?很多人也许未必去考虑过,我个人认为,使用多线程是为了减少CPU等待的时间,最大化的利用CPU的性能。那为什么说多线程未必比单线程好呢?我简单举个案例。你要扫地和洗马桶,扫地要10分钟,洗马桶要10分钟,你一个人完成这两件事要多少时间?使用单线程工作方式是20分钟,而你如果使用多线程,扫一半地跑过去洗马桶再回过来扫地再回去去洗马桶,那么完成这两件事必定要超过20分钟了。但是如果你要做的事是煮饭和扫地,那么使用多线程就体现出优势了。
  • 分享点二:选择多少个线程能充分利用服务器的性能呢?有很多理论是服务器用的是几核CPU就使用几个线程,这是一个比较通用的配置方式,仅限当你线程中执行的代码无阻塞时。要服务器性能越高,就是等同于让CPU处理业务逻辑的时间越长,所以开几个多线程就是考虑能充分利用这些CPU,但是注意不要过度开多线程,线程间的调度本身会消耗CPU,开越多,调度的代价越高。

      多线程的开发要比单线程复杂很多,所以在进行多线程编程的情况下,要特别的小心。

二、网络模型

      Reactor模式是我在接触netty之后才知道的一个模式,关于这个模式,在Netty实现原理浅析的网络模型里面有详尽的描述,当然作者文章也说,是参考Doug Lea的Scalable IO in Java这位大牛的文章,想要理解这个模型的,可以先去看上述两篇文章,接下去的内容,是基于我对于这些模式的理解的记录,顺便会根据Doug Lea文章的内容稍微翻译摘出来点:

      一个最简单的网络模型拥有的基本模型大概是这样的:

  1. 读取数据
  2. 对数据解码
  3. 处理数据
  4. 对数据编码
  5. 发送数据

      模型一:单线程的reactor模型:

     


       读取数据,对数据解码,处理数据,对数据编码和发送都是在一个线程中的。此时的Reactor可以认为是服务器端的主线程,负责接受客户端的链接,链接建立完毕后将此链接负责分派到一个handler线程去处理剩下的事情。伪代码如下:

       

/**
 * 代码来自Doug Lea
**/
Class Server implements Runnable{
    public void run(){
        try{
            ServerSocket ss = new ServerSocket(port);
            while(!Thread.interrupted()){
                 new Thread(new Handler(ss.accept())).start();
            }
        }
    }
}

static class Handler implements Runnable{
    final Socket socket;
    Handler(Socket s){ 
        socket = s;
    }
    public void run(){
        try{
            byte[] input = new byte[MAX_INPUT];
            socket.getInputStream().read(input);
            byte[] output = process(input);
            socket.getOutputStream().write(output);
        }catch(IOException ex){
             /*...*/
        }
    }
}

 

       这个模式有什么优缺点?我一个单词一个单词的查询翻译了下Doug Lea的文章,也貌似没明确说,但在Netty原理浅析里面是这样阐述的:

  

       该模型 适用于处理器链中业务处理组件能快速完成的场景。不过,这种单线程模型不能充分利用多核资源,所以实际使用的不多。

       那怎么样才算能充分利用多核CPU资源呢?难道开了多个Handler操作就只是用到了一个CPU核么?想想也不可能,

       我用下面代码测试:

        

public class Test {
	public static void main(String[] ben){
		Thread work1 = new Work();
		work1.start();
		Thread work2 = new Work();
		work2.start();
	}
}

class Work extends Thread{
	public void run(){
		Long sum=0l;
		int i=0;
		while(i<100000){
			sum+=i;
		}
		System.out.println("end");
	}
}

    我CPU是双核,两个核立马彪满:

    

     所以说上面的这个模型不能充分利用多核CPU,我是持保留意见滴。那么怎样的情况不能利用多核CPU呢?

 

     假设当前服务器为四核CPU,当前只有一个handler线程,handler线程里面执行的业务处理很庞大,比如像上面我的示例,1到100万相加总和这样的计算,在这种情况下,如果把1到100万相加的handler再拆成四个线程去计算,各计算四分之一的数据,那么就可以充分利用四核CPU了(但是如果执行很快,比如计算1到10,拆了反而更慢,因为CPU还要调度的)。

 

      但是又假设如果当前已经有四个handler线程甚至更多,就算不拆也已经用到四核了。

      但是真的如果handler的业务逻辑执行很慢(非阻塞,计算量大的情况),要不要拆呢,因为在服务器端我相信同一个时间用户的访问并发应该会超过CPU的核数?所以个人认为不到需要极端优化性能的前提下还是没必要去拆,太复杂。

      所以说,该模型适用于能快速执行的业务逻辑的系统或者多核CPU系统,在某种场景或者程度上是可以这么理解。

 

 

      题外话,假设handler线程里面出现堵塞,会不会让CPU处于空闲呢?回答这个问题钱这,我又回去翻阅了Think in java中线程的一章,首先看线程的四个状态:

 

  1. 新(New):线程对象已经创建,但尚未启动,所以不可运行
  2. 可运行(Runnable):意味着一旦时间分片机制有空闲的CPU周期提供给一个线程,那这个线程便可立即运行。因此线程可能在、也可能不在运行当众,但一旦条件许可,没有什么能阻止它的运行------它既没有“死”掉,也未被"堵塞"。

  3.  

     

    死(Dead):从自己的run()方法中返回后,一个线程便已经"死"掉。亦可调用stop()令其死掉。.

     

     

  4. 堵塞(Blocked):线程可以运行,但有种东西阻碍了它。若线程处于堵塞状态,调度机制可以简单的跳过它,不给他分配任何CPU时间。除非线程再次进入"可运行"状态,否则不会采取任何操作

      那么何为线程堵塞:

 

  1. 调用sleep(毫秒数),使线程进入"睡眠"状态。在规定的时间内,这个线程是不会运行的。

  2. 用suspend()暂定了线程的执行。除非线程收到resume()消息,否则不会返回"可运行"状态。

  3. 用wait()暂停了线程的执行。除非线程收到notify()或者notifyAll()消息,否则不可变成"可运行".
  4. 线程正在等候一些IO(输入输出)操作完成。
  5. 线程实体调用另一个对象的"同步"方法,但那个对象处于锁定状态,暂时无法使用.

      所以如果handler线程里面有堵塞操作,那么就多开几个线程让CPU去切换执行即可,至于开多少个合适,看堵塞的时间而定。这个淘宝内部有公式的,但是堵塞时间不一定,所以还是需要通过TPS测试才能确定.

 

      模型二:多线程处理的Reactor模式

      所以说上面那个模型也不能说不好,继续跟着Doug Lea的文章继续前行了。Doug Lea提出了几点模型可扩展性的目标(Scalability Goals).

 

 

  • 优雅的流量降级(当客户端连接持续增大到很多时,能避免系统被压垮)
  • 能够持续的控制资源的使用增长(CPU,memory,disk,bandwidth)
  • 能满足一些性能方面的目标,包括低延迟,满足高峰需求,服务质量的保证。
  • 分而自治(Divide-and-conquer)通常是最好的方式.其实就是模块化吧。

    Doug Lea首先介绍了Divide-and-conquer,其核心是将任务划分成小任务来处理,并且是非堵塞的小任务.我猜应该是支持了我上述的理论,将较大的任务分拆成小任务来处理,可能可以更好的利用多核CPU的性能,所以才有了下面这个模型:

    

 

      这个模型把原来handler(这个大handler也可叫worker线程)中的对数据解码,数据处理,对数据编码抽离出来行程一个小handler,用过netty的都知道,netty可以添加多个handler并顺序执行,不知道大家有没有思考过,handler是处理业务逻辑的,我为什么要写多个handler?我一个handler就可以写完。如果放到这个模型里面来,就可以理解了,netty希望我们自己将大的handler分解成一个一个小的handler进行执行,只不过默认情况下这些handler都是在一个线程里面顺序执行(其实就跟一个handler是一样的概念,所以默认情况下netty在worker的选择上是模型一)的,或者更多默认情况下,我们只写了一个handler而已。关于此模型,暂时认为讲到这里即可,暂时还不需要深入.

    

       模型三:多Reator线程的Reator模式 (好怪的名字,将就下)

      上述两个模型都有一个通病,Reactor的Acceptor中,首先是建立链接,然后再把链接分配给指定的handler线程去执行,那么我们知道,建立链接是个阻塞动作,操作很慢,那么Doug Lea为了匹配CPU和IO的速率(Use to match CPU and IO rates)提出了下面这个模型:

       

 

 

       Doug Lea的所谓匹配IO和CPU的速率,其实所得直白点是因为只有一个Reator情况下,因为Reator只能一个一个处理创建连接这个请求,如果客户端连接数量一大,就会在Reator形成一个单线程操作,并且创建链接又是一个阻塞动作,只有前一个客户的链接创建完毕才会处理下一个客户的链接请求,性能直线下降。所以这个模型就有了mainReator和subReactor这两个reactor。mainReator负责将用户请求的链接提交给subReactor去执行,subReactor则负责建立链接,并将建立后的链接发送到具体的work线程去执行.

       下一篇章:会先写netty所使用的reactor模型与其根据netty源码简化后的代码。.

 

 

 

 

 

 

 

 

 

 

        

     

     

  • 大小: 63.7 KB
  • 大小: 70.3 KB
  • 大小: 86.2 KB
  • 大小: 90 KB
分享到:
评论

相关推荐

    java nio&netty系列之三netty网络模型代码以及简化版代码示例

    总的来说,Netty的网络模型基于Java NIO,利用非阻塞I/O和事件驱动的机制,实现了高并发、低延迟的网络通信。同时,Netty提供的API简单易用,使得开发者可以更加专注于业务逻辑,而不是底层的网络细节。结合源码阅读...

    Netty核心精讲之Reactor线程模型源码分析.mp4

    1. `NioEventLoop`:这是Netty针对Java NIO实现的EventLoop类,其中包含了对选择器(Selector)的管理和事件的分发。 2. `ChannelHandlerContext`:它是Netty的上下文对象,用于封装了与特定Channel相关的所有操作...

    Java网络编程 NIO Netty

    Java网络编程领域中,NIO(Non-blocking Input/Output,非阻塞I/O)和Netty框架是两个关键概念。NIO是一种I/O模型,它与传统的BIO(Blocking I/O)模型不同,BIO在处理连接时一旦进行读写操作就会阻塞,直到数据传输...

    NIO框架Netty实现高性能高并发

    Java异步NIO框架Netty实现高性能高并发无标题笔记 1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨 节点...

    NIO+Netty5视频教程2018

    第二部分"NIO+Netty5各种RPC架构实战演练",则侧重于将NIO与Netty结合应用于实际的RPC(Remote Procedure Call)系统中。RPC允许程序调用另一个计算环境中执行的程序,而无需了解底层网络协议和细节。这部分可能涵盖...

    基于Java NIO的网络服务器Netty生产实例.zip

    3. **Netty的事件驱动模型**:Netty采用 reactor 模式,通过EventLoopGroup来管理事件循环线程,每个线程负责处理多个连接的事件。当有新连接、读写事件发生时,会触发相应的ChannelHandler进行处理。 4. **Netty的...

    聊聊 Netty 那些事儿之 Reactor 在 Netty 中的实现(创建篇).doc

    在 Netty 服务端,核心引擎采用了主从 Reactor 多线程模型,该模型在 Doug Lea 的“Scalable IO in Java”论文中有所提及,但 Netty 在实现上有所不同。 主 Reactor Group 和从 Reactor Group 是 Netty 中的两个...

    简单了解Java Netty Reactor三种线程模型

    在Netty中,Reactor线程模型是其核心设计之一,用于处理并发连接和网络I/O操作。本文将详细介绍Reactor的三种线程模型,并结合Netty的线程模型进行解析。 ### 1. Reactor 单线程模型 Reactor单线程模型是指所有的I...

    NIO框架netty

    1. **异步非阻塞I/O**:Netty采用基于Reactor模式的事件驱动架构,利用Java NIO的非阻塞I/O模型,提高了系统的并发能力,降低了CPU的等待时间。 2. **高性能**:Netty通过优化内存分配、零拷贝技术、高效的缓冲区...

    java nio 原理浅析

    Netty是基于Java NIO的一个高性能、异步事件驱动的网络应用程序框架,它简化了开发复杂的网络应用,比如TCP和UDP协议的应用。 Netty的整体结构复杂且灵活,它包含了多种组件,如Bootstrap、Channel、EventLoopGroup...

    基于Java NIO反应器模式设计与实现

    Mina是一个完全由Java编写的NIO框架,而Netty则是由JBOSS提供的一个高性能的异步事件驱动的网络应用框架,它们都是基于Java反应器模式设计的,用于处理大量并发连接的场景。 综上所述,基于Java NIO的反应器模式...

    netty 入门Reactor示例

    在Java中,NIO(非阻塞I/O)库为实现Reactor模式提供了基础。Netty基于NIO,并在其之上构建了一套高效且易用的网络编程框架。 Netty中的Reactor分为两个主要部分:主线程(BossGroup)和工作线程(WorkerGroup)。...

    reverse-proxy:通过Netty基于Java NIO的https代理服务器的实现

    通过Netty基于Java NIO的https代理服务器的实现。 这是一个简单的工作原理: 要通过浏览器对其进行测试,我们将需要设置一个虚拟主机名,如下所示: 127.0.0.1 test.localdomain 这样浏览器就能将SNI发送到我们...

    socket-nio-single-reactor.zip

    Socket NIO 单 Reactor 模式是一种在 Java 中实现高性能网络编程的技术,它结合了非阻塞I/O(New I/O,即NIO)和Reactor设计模式。本示例代码旨在帮助开发者理解如何使用Java NIO和Reactor模式构建网络服务。尽管...

    10道Java高级必备的Netty面试题

    Java Netty 面试题知识点总结 Java Netty 是一个基于 Java 的网络编程框架,使用 NIO 实现高...这些知识点是 Java Netty 面试题中的重要内容,掌握这些知识点能够帮助您更好地理解 Java Netty 框架和 NIO 编程模型。

    Netty系列之Netty高性能实践.pdf

    Netty通过优化的Reactor线程模型解决了这些问题,它可以有效地处理大规模并发连接,减少线程创建和销毁的开销。 Netty的高性能主要体现在以下几个方面: 1. **传输层**:Netty支持多种传输模式,包括BIO、NIO和AIO...

    reactor-netty-jar.zip

    Reactor Netty提供了多种性能优化选项,如线程模型的选择(NIO或Epoll)、内存池配置、连接超时等。根据具体的应用场景,合理配置这些选项可以进一步提升系统的性能。 总结,Reactor Netty是Java开发高性能网络应用...

    java netty通信

    Netty基于Reactor模式,采用主从线程模型,即一个BossGroup处理连接请求,多个WorkerGroup处理I/O事件。这种设计能够确保高并发下的性能和稳定性。 2. **Channel与Handler** Channel是Netty的核心概念,代表一个...

    一文聊透 Netty 核心引擎 Reactor 的运转架构.doc

    总的来说,Netty的Reactor模型通过高效地处理I/O事件和调度任务执行,实现了网络服务的高性能和可扩展性。理解Reactor的工作原理对于优化和调试Netty应用程序至关重要。本文提供的概述是后续深入研究Reactor如何处理...

Global site tag (gtag.js) - Google Analytics