一个Netty程序始于Bootstrap类,Bootstrap类是Netty提供的一个可以通过简单配置来设置或“引导”程序的一个重要的类。Netty中设计了Handlers来处理特定的"event"和设置Netty中的事件,从而来处理多个协议和数据。ChannelInboundHandler用来接收消息。Netty提供ChannelInitializer用来配置Handler, ChannelInitializer通过ChannelPipeline来添加ChannelHandler。ChannelInitializer自身也是一个ChannelHandler,再添加完所有handlers之后会自动从ChannelPipeline中删除自己。

  所有Netty都是基于ChannelPipeline。ChannelPipeline和EventLoop和EventLoopGroup密切相关。

  Netty所有的IO操作都是异步执行的。Netty使用Futures和ChannelFutures来达到目的。Future注册一个监听,当操作成功或失败时会通知。ChannelFuture封装的是一个操作的相关信息,操作被执行时会立刻返回ChannelFuture。

  Netty是一个非阻塞,事件驱动和网络框架。Netty实际上是用多线程处理IO事件。

  当注册一个Channel时,Netty将这个Channel绑定到一个EventLoop,在Channel生命周期内总是被绑定到一个EventLoop。

  Bootstrap

    引导有两种类型:一种是用于客户端的Bootstrap(也适用于DatagramChannel),另一种是用于服务端的ServerBootstrap。

    Bootstrap和ServerBootstrap的差异:Bootstrap用来连接远程主机,有1个EventLoopGroup;ServerBootstrap用来绑定本地端口,有2个EventLoopGroup。

    ServerBootstrap监听在服务器监听一个端口轮询客户端的“Bootstrap”或DatagramChannel是否连接服务器。通常需要先调用bind()后再调用connect()进行连接。之后使用Channel的bind()返回ChannelFuture中。

    bootstarp/applications使用一个单例EventLoopGroup,而ServerBootstrap使用了2个EventLoopGroup。一个ServerBootstrao可以认为有两个channels组,第一个组包含一个单例ServerChannel,代表持有一个绑定了本地端口的socket,第二组包含所有Channel,代表服务器已接受了连接。

    EventLoopGroup可以包含多个EventLoop,每个Channel绑定一个EventLoop,很多Channel会共享一个EventGroup。这意味着在一个Channel保持EventLoop繁忙会禁止其他Channel绑定到相同的EventGroup。

   

  Channel Handlers and Data Flow

    Channel Handler是一段执行业务逻辑处理数据的代码,他们来来往往的通过ChannelPipeline。ChannelHandler是定义一个handler的父接口。

    Netty有两个方向的数据流。若数据是从用户应用程序到远程主机则是“出站(outbound)”,若数据从远程主机到用户应用则是“入站(inbound)”、为了使数据从一端到另一端,一个或多个ChannelHandler将以某种方式操作数据,这些ChannelHandler会在程序的“引导”阶段添加ChannelPipeline中,并且被添加的顺序将决定处理数据的顺序。ChannelPipeline的作用可以理解为用来管理ChannelHandler的一个容器,每个ChannelHandler处理各自的数据,处理完后将转换的数据放到ChannelPipeline中交给下一个ChannelHandler继续处理,直到最后一个ChannelHandler处理完成。

    在ChannelPipeline中,若消息被读取或有任何其他的入站事件,消息将从ChannelPipeline的头部开始传递给第一个ChannelInboundHandler,这个ChannelInboundHandler可以处理该消息或将消息传递到下一个ChannelInboundHandler中,一旦在ChannelPipeline中没有剩余的ChannelInboundHandler后,ChannelPipeline就知道消息已被所有的Handler处理完成了。任何出站事件或写入将从ChannelPipeline的尾部开始,并传递到最后一个ChannelOutboundHandler。ChannelOutboundHandler可以传递消息到下一个Handler或自己处理消息。

    Netty提供了抽象的事件基类ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter。每个都提供了在ChannelPipeline中通过调用相应的方法将事件传递给下一个Handler的方法的实现。

    当一个ChannelHandler添加到ChannelPipeline中时获得一个ChannelHandleContext。通常是安全的获得这个对象的引用,但当一个数据协议不正确时,这个对象可以在之后用来获取底层通道,因此要用它来read/write消息,因此消息通道将会保留。因此Netty发送消息有两种方法:直接写入通道或写入ChannelHandlerContext对象。这两种方法的区别为:直接写入通道导致处理消息从ChannelPipeline的尾部开始;写入ChannelHandlerContext对象导致处理消息从ChannelPipeline的下一个handler开始。

  

    自定义ChannelHandler需要继承编码/解码适配器类中的一个。Netty有ChannelHandlerAdapter,ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter三个适配器。

    应用程序只需要扩展SimpleChannelInboundHandler<I>,通过重写父类的方法可以获得一个ChannelHandlerContext的引用,它们接受一个ChannelHandlerContext参数。处理程序关注的主要方法是“channelRead0(ChannelHandlerContext ctx, I msg)”。可以添加ChannelHandler到ChannelPipeline中指定一个EventExecutorGroup,EventExecutorGroup会获得一个EventExecutor,EventExecutor将执行ChannelHandler的所有方法。EventExecutor将使用不同的线程和释放EventLoop。

    

Netty核心概念的更多相关文章

  1. Netty In Action中文版 - 第三章:Netty核心概念

            在这一章我们将讨论Netty的10个核心类.清楚了解他们的结构对使用Netty非常实用.可能有一些不会再工作中用到.可是也有一些非经常常使用也非常核心,你会遇到. Bootstrap ...

  2. Netty核心概念(10)之内存管理

    1.前言 之前的章节已经将启动demo中能看见的内容都分析完了,Netty的一个整体样貌都在第8节线程模型最后给的图画出来了.这些内容解释了Netty为什么是一个异步事件驱动的程序,也解释了Netty ...

  3. Netty核心概念(8)之Netty线程模型

    1.前言 第7节初步学习了一下Java原本的线程池是如何工作的,以及Future的为什么能够达到其效果,这些知识对于理解本章有很大的帮助,不了解的可以先看上一节. Netty为什么会高效?回答就是良好 ...

  4. Netty核心概念(7)之Java线程池

    1.前言 本章本来要讲解Netty的线程模型的,但是由于其是基于Java线程池设计而封装的,所以我们先详细学习一下Java中的线程池的设计.之前也说过Netty5被放弃的原因之一就是forkjoin结 ...

  5. Netty核心概念(6)之Handler

    1.前言 本节介绍Netty中第三个重要的概念——Handler,这个在前两节都提到了,尤其是Channel和Handler联系紧密.handler本身的设计非常简单,但是所起到的作用却很大,Nett ...

  6. Netty核心概念(5)之Channel

    1.前言 上一节讲了Netty的第一个关键启动类,启动类所做的一些操作,和服务端的channel固定的handler执行过程,谈到了不管是connect还是bind方法最终都是调用了channel的相 ...

  7. Netty核心概念(4)之Bootstrap

    1.前言 第三节介绍了Netty的一些基本概念,此节介绍Netty的第一个概念Bootstrap——启动类.Netty中服务端和客户端的启动类是不一样的,这个不要搞错了,类都在bootstrap包下. ...

  8. Netty核心概念(9)之Future

    1.前言 第7节讲解JAVA的线程模型中就说到了Future,并解释了为什么可以主线程可以获得线程池任务的执行后结果,变成一种同步状态.秘密就在于Java将所有的runnable和callable任务 ...

  9. 消息中间件——RabbitMQ(三)理解RabbitMQ核心概念和AMQP协议!

    前言 本章学习,我们可以了解到以下知识点: 互联网大厂为什么选择RabbitMQ? RabbiMQ的高性能之道是如何做到的? 什么是AMQP高级协议? AMQP核心概念是什么? RabbitMQ整体架 ...

随机推荐

  1. Leetcode 116

    /** * Definition for binary tree with next pointer. * struct TreeLinkNode { * int val; * TreeLinkNod ...

  2. Java中获得当前静态类的类名

    通常在打印日志的时候需要输出类名,普通类可以用this.getClass(),但是静态类没有this,直接写类名耦合度高. 参考了: https://stackoverflow.com/questio ...

  3. Cassandra V2.1.20单机安装

    1. 系统调优 [root@sht-sgmhadoopcm- ~]# echo "vm.max_map_count=131072" >> /etc/sysctl.con ...

  4. Spring注解之 @EnableScheduling计划任务注解

    要实现计划任务,首先通过在配置类注解@EnableScheduling来开启对计划任务的支持, 然后在要执行计划任务的方法上注解@Scheduled,声明这是一个计划任务 示例:计划任务执行类 在这个 ...

  5. Mybatis排序无效问题解决

    在 mybatis 的 xml中,为一个SQL语句配置order by 子句时,需要这个排序的字段是前端传递过来的,而且排序的顺序(升序 OR 降序)也是由前端传递过来的.对于这种需求,我起初写成了下 ...

  6. Minimum supported Gradle version is 4.1. Current version is 2.14.1

    Error:Minimum supported Gradle version is 4.1. Current version is 2.14.1. If using the gradle wrappe ...

  7. javascript 多个onclick function 取对应值

    方法1: 直接获取值 <button onclick="aa(1)">执行</button> <button onclick="aa(2)& ...

  8. windbg 定位崩溃问题

    三板斧如下: 使用windbg打开dump文件,设置好对应进程的 pdb 文件(这个很关键.为了避免releas优化导致符号文件错乱,我发布的所有                      relea ...

  9. 逆袭之旅.DAY08东软实训.多态~

    2018年7月4日

  10. 2.python函数编程-filter函数

    fileter功能主要使用在需要对数据进行多种操作,并对数据进行过滤的操作. 普通函数实现: movie = ['sb_alex', 'wupei', 'tiger', 'goosb','xxfd', ...