Netty Crash Course

一个Netty程序一般开始于Bootstrap类,通过设置程序后,使用Handlers来处理特定的event和设置Netty中的事件,从而处理多个协议数据,比如实现ChannelInBoundHandler类;

多个Handler通过ChannelInitializer的ChannelPipeline组合在一起,再配合EventLoop(整个生命周期内绑定对应一条线程)和EventLoopGroup来处理各种业务逻辑。

Channels, Events and Input/Ouput

Netty中所有操作都是异步执行的,例如连接一个主机、发消息。可以注册监听器来通知,如Futures(注册一个监听,当操作成功或者失败时会通知)和ChannelFutures(封装的是一个操作的相关信息,操作被执行会理科返回ChannelFuture)。

Bootstrap

两种引导,用于客户端或者DatagramChannel的Bootstrap(一个EventGroup)和用于服务端的ServerBootstrap(两个EventGroup)。

EventLoopGroup可以包含很多个EventLoop,每个channel绑定一个EventLoop不会被改变,很多channel共享一个EventLoop。这就意味着如果一个Channel保持EventLoop繁忙,会禁止其他channel绑定到相同的EventLoop,我们可以理解EventLoop为一个事件循环线程,而EventLoop是一个事件循环集合。

Channel Handler and Data Flow

Handlers自身依赖ChannelPipeline来决定它们的执行顺序。

ChannelHandler定义了一个父接口,ChannelInboundHandler(入站,读)和ChannelOutboundHandler(出站,写)是其子接口,ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter是桥接器类。

入站是从ChannelPipeline的头部开始传递到最后,而出站是从尾部开始。

Netty发消息有两种方法:1、直接写入通道导致消息从ChannelPipeline的尾部开始;2、写入ChannelHandlerContext对象导致处理消息从ChannelPipeline的下一个handler开始

编码器、解码器和业务逻辑

每个Handler负责转发时间到ChannelPipeline的下一个handler,但在*Adapter(和子类)中是自动完成的:

ChannelHandlerAdapter,ChannelInboundHandlerAdapter,ChannelOutboundHandlerAdapter,

ByteToMessageDecoder,MessageToByteEncoder,ProtobufEncoder,ProtobufDecoder

所有的解码器都继承或者实现ChannelInboundHandlerAdapter或者ChannelInboundHandler,channelRead放大调用decode方法,并通过ChannelHandlerContext.fireChannelRead(Object msg)传递给下一个handler。编码器类似。

也许最常见的应用程序处理接收到消息后进行解码,然后供相应的业务处理模块使用。那么有用程序只需要拓展SimpleChannelInboundHandler<T>,SimpleChannelOutboundHandler<T>即可。主要方法是channelRead0(ChannelHadnlerContext ctx, T msg); 消费msg时需要注意,Netty中梳理IO一般有很多线程,不要阻塞IO线程,因为阻塞会降低程序的性能,解决方案是添加ChannelHandler到ChannelPipeline时指定一个EventExecutorGroup,EventExecutorGroup会获得一个EventExecutor,EventExecutor将会执行ChannelHandler的所有方法:

double coefficient = 0.8;  //系数
int numberOfCores = Runtime.getRuntime().availableProcessors();
int poolSize = (int)(numberOfCores / (1 - coefficient));
static final EventExecutorGroup group = new DefaultEventExecutorGroup(poolSize); ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("decoder", new MyProtocolDecoder());
pipeline.addLast("encoder", new MyProtocolEncoder());
// Tell the pipeline to run MyBusinessLogicHandler's event handler methods
// in a different thread than an I/O thread so that the I/O thread is not blocked by
// a time-consuming task.
// If your business logic is fully asynchronous or finished very quickly, you don't
// need to specify a group.
pipeline.addLast(group, "handler", new MyBusinessLogicHandler());

如需要定时执行简单的任务,可以使用EventLoop:

ch.eventLoop().schedule(...);
或者
ScheduleFuture f = ch.eventLoop().scheduleAtFixedRate(...);
f.cancel(true);

Netty使用reference-counting来安全释放Buf和其他资源:

ByteBuf

字节数据容器,单独维护读写两个索引,最大容量限制是Integer.MAX_VALUE,三种不同类型的ByteBuf:

1、Heap Buffer(堆缓冲区)

数据存储在JVM的堆空间中,通过数组实现,可以使用ByteBuf的array()来获取数据。访问非堆缓冲区的ByteBuf的数组会导致UNsupportedOperationException,可以使用hasArray()来检查

2、Direct Buffer(直接缓冲区)

堆之外直接分配内存,性能很好,分配和释放比较复杂,使用内存池来解决。不支持直接数组访问数据:

ByteBuf buf = Unpooled.directBuffer(16);
if (!buf.hasArray()) {
int len = buf.readableBytes();
byte[] arr = new byte[len];
buf.getBytes(arr);
}

3、Composite Buffer(复合缓冲区)

提供一个视图组合多个buff,hasArray()总返回false。

CompositeByteBuf cbf = Unpooled.compositeBuffer();
ByteBuf heap = Unpooled.buffer(8);
ByteBuf direct = Unpooled.directBuffer(16);
cbf.addComponents(heap, direct); cbf.removeComponent(0); Iterator<ByteBuf> iter = cbf.iterator();
while(iter.hasNext()) {
System.out.println(iter.next().toString());
} if (!cbf.hasArray()) {
int len = cbf.readableBytes();
byte[] arr = new byte[len];
cbf.getBytes(0, arr);
}

相关方法:

isReadable()是否还可以继续读

writeableBytes()剩余可写空间

clear()重置读写的index为0

discardReadBytes()清空已读数据,会移动字节位置,设计到内存复制,注意性能问题

readerIndex(int idx)设置读索引位置

writerIndex(int idx)设置写索引位置

duplicate()、slice()、slice(int index, int length)、order(ByteOrder endianness)这些会创建缓冲区视图但有独立的读写索引

copy()或者copy(int index, int length)创建全新的副本

ByteBufProcessor

搜索操作,如bytesBefore(byte value)

ByteBufHolder

帮助更快捷的访问ByteBuf中的数据,当缓冲区没用了之后,尅只用这个辅助类释放资源。

ByteBufAllocator

负责分配ByteBuf实例,可以从Channel或者ChannelHandlerContext的alloc()方法获得该对象,有两种实现,一为将分配和回收成本以及内存使用降到最低,另一种是每次使用都创建新的ByteBuf实例。

Netty默认使用PooledByteBufAllocator,可以通过ChannelConfig或者引导设置不同的实现来改变。

Unpooled

创建缓冲区的工具类。

ByteBufUtil

工具类,hexDump(ByteBuf buff)

Netty入门(2) - 核心概念的更多相关文章

  1. ElasticSearch入门及核心概念介绍

      Elasticsearch研究有一段时间了,现特将Elasticsearch相关核心知识和原理以初学者的角度记录下来,如有不当,烦请指正! 0. 带着问题上路——ES是如何产生的? (1)思考:大 ...

  2. zookerper入门、核心概念和使用场景

    zookeeper是一个分布式程序的高性能协调服务,提供集中式信息存储服务,数据存储于内存中,类似文件系统的树形结构,高吞吐量和低延时,集群高可靠,基于zookeeper可以实现分布式统一配置中心.分 ...

  3. JAVAEE——BOS物流项目13:Quartz入门案例、核心概念、cron 表达式的格式(了解)

    1.quartz入门案例 本入门案例基于spring和quartz整合完成. 第一步:创建maven工程,导入spring和quartz相关依赖 第二步:创建任务类 第三步:在spring配置文件中配 ...

  4. lucene 核心概念及入门

    lucene Lucene介绍及核心概念 什么是Lucene Lucene是一套用于全文检索和搜索的开放源代码程序库,由Apache软件基金会支持和提供.Lucene提供了一个简单却强大的应用程序接口 ...

  5. Elasticsearch入门教程(二):Elasticsearch核心概念

    原文:Elasticsearch入门教程(二):Elasticsearch核心概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:ht ...

  6. JAVA入门(1.JAVA平台应用 2.核心概念:JVM,JDK,JRE 3.搭建JAVA开发环境 4.学习JAVA的原则)

    主要内容: 1.JAVA平台应用 2.核心概念:JVM,JDK,JRE 3.搭建JAVA开发环境 4.学习JAVA的原则 JAVA的平台应用 JAVA的平台应用分为3个部分: 一.JAVA SE,主要 ...

  7. Mycat入门核心概念

      Mycat中的核心概念     Mycat中的核心概念 1.数据库中间件    Mycat 是一个开源的分布式数据库系统,但是由于真正的数据库需要存储引擎,而 Mycat 并没有 存储引擎,所以并 ...

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

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

  9. 从零开始入门 K8s| 阿里技术专家详解 K8s 核心概念

    作者| 阿里巴巴资深技术专家.CNCF 9个 TCO 之一 李响 一.什么是 Kubernetes Kubernetes,从官方网站上可以看到,它是一个工业级的容器编排平台.Kubernetes 这个 ...

随机推荐

  1. mysql登录密码相关

    设置root登录密码 方法一:用root 进入mysql后 mysql>set password =password('你的密码'); mysql>flush privileges; 方法 ...

  2. python之参数解包

    # 参数解包:将整个list当做参数传给函数 list = [1, 2, 4] def add_fn(a, b, c): return a + b + c sum = add_fn(*list) pr ...

  3. Conjugate Function

    共轭函数 共轭函数的定义: 设函数f:Rn→R,定义函数f∗:Rn→R为: f∗(y)=sup(<y,x>−f(x))  x∈D 此函数称为函数f的共轭函数.即函数yx和函数f(x)之间差 ...

  4. python3实现感知器,简单神经网络

    三个输入,四个输出,四组数据 对numpy和矩阵运算还不是太熟悉,可能写的复杂了点,矩阵数组来回转换 代码请查看码云 运行结果片段

  5. 【AtCoder010】A - Addition(奇偶)

    AtCoder Grand Contest 010 A题 题目链接 题意 n个数,每次取两个奇偶性相同的数用他们的和代替他们,问最后能否只剩下一个数. 题解 因为奇偶相同的两个数之和一定是偶数,所以Y ...

  6. json序列化 & 反序列化

    json序列化: json的dumps方法可以将json格式数据序列为python的相关数据类型,比如str,常用于打印,另外,在序列化时,中文汉字被转换为unicode编码,在dumps函数中添加参 ...

  7. bzoj4985 评分 (二分答案+dp)

    首先二分一个答案x,然后我们把>=x的数看成1,<x的数看成0,那如果最后剩下1,这个答案就是合法的. 那我们就来算让某一位得1至少需要填几个1(设这个值是f[i]) i=1..n时,显然 ...

  8. 【bzoj2229】 Zjoi2011—最小割

    http://www.lydsy.com/JudgeOnline/problem.php?id=2229 (题目链接) 题意 给出一张无向图,$q$组询问,每次询问最小割不大于$c$的点对数量. So ...

  9. Linux中禁用命令历史记录

    关闭history记录功能 set +o history 打开history记录功能 set -o history 清空记录 history -c 记录被清空,重新登录后恢复. rm -f $HOME ...

  10. Luogu 1314 【NOIP2011】聪明的质检员 (二分)

    Luogu 1314 [NOIP2011]聪明的质检员 (二分) Description 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有n个矿石,从 1 到n逐一编号,每个矿石都有 ...