Netty:Netty的介绍以及它的核心组件(一)—— Channel
1. Netty 介绍
Netty 是一个无阻塞的输入/输出(NIO)框架,它使开发低级网络服务器和客户端变得相对简单。Netty为需要在套接字级别上工作的开发人员提供了令人难以置信的强大功能,例如,在开发客户端和服务器之间的自定义通信协议时。它支持SSL / TLS,具有阻塞和非阻塞统一API,以及灵活的线程模型。它又快又高效。
Netty 的异步、非阻塞 I/O 模型是为高度可扩展的体系结构设计的,与类似的其他阻塞模型相比,它可能允许更高的吞吐量。基本上,非阻塞服务器在单个线程上异步运行所有请求(没有函数会“阻塞”事件循环)。这与阻塞服务器模型形成对比,后者通常在单独的线程上运行每个请求。通过不必在负载增加时切换线程或创建新线程,非阻塞模型可以减少开销,并在流量增加时更快地进行扩展。
Netty 的核心组件:Channel、回调、Future、事件和ChannelHandler。
2. Channel 通道
Channel 与网络套接字或能够进行 I/O 操作(例如读取,写入,连接和绑定)的组件的枢纽。
Channel 为用户提供:
通道的当前状态(例如,它是否打开?是否已连接?)
通道的 ChannelConfig 配置参数(例如,接收缓冲区大小)
通道支持的 I/O 操作(例如,读取,写入,连接和绑定)
处理所有与该通道关联的I/O事件和请求的 ChannelPipeline
Netty 的 Channel 接口的一些类型(Java类图):
Channel 主要衍生有这几个类型的接口:
Http2StreamChannel:支持 HTTP/2 协议的 Channel。
ServerChannel:一个接收新连接然后创建子Channel的Channel组件, ServerSocketChannel 就是一个很好的例子, ServerSocketChannel 接受连接,然后创建出 SocketChannel。
SctpChannel:一个处理 SCTP/IP 协议(流控制传输协议 (Stream Control Transmission Protocol))的 Channel。
DatagramChannel:一个处理 UDP/IP 协议的 Channel。
DuplexChannel:一个拥有两个端点并能在每个端点独立关闭的全双工Channel。
Channel 的一些特性:
1)所有I / O操作都是异步的
Netty中的所有I / O操作都是异步的。这不意味着任何I / O调用都将立即返回,不能保证所请求的I / O操作已在调用结束时完成。相反,你将获得返回一个ChannelFuture实例,该实例将在请求的I / O操作成功,失败或取消时通知你。
2)Channel是分层的
Channel可以有一个parent(父级},具体取决创建方式。例如,ServerSocketChannel接受的SocketChannel将返回ServerSocketChannel作为其在parent上的父级。层次结构的语义取决于Channel所属的transport实现。
3)向下访问特定于传输的操作
某些传输会公开特定于传输的其他操作。将 Channel 向下转换为子类型以调用此类操作。例如,对于旧的 I/O 数据报传输,DatagramChannel提供了多播加入/离开操作。
4)释放资源
一旦完成Channel,调用 #close 或 #close(ChannelPromise)释放所有资源很重要。这样可以确保以适当的方式释放所有资源,即文件句柄。
那么 Channel 在什么时候创建?
Netty 服务端引导类 ServerBootstrap#bind() 方法中的 doBind() 方法调用 initAndRegister() ,方法具体内容再移步到父类 AbstractBootstrap#initAndRegister 方法处,创建是有 Channel 工厂来创建的,类型是由 Netty 的 BootStrap 实例化时指定的 Channel 类型,例如 NioSocketChannel.class。
1 /**
2 * Create a new {@link Channel} and bind it.
3 */
4 public ChannelFuture bind(SocketAddress localAddress) {
5 validate();
6 if (localAddress == null) {
7 throw new NullPointerException("localAddress");
8 }
9 return doBind(localAddress);
10 }
doBind(localAddress); 具体方法:
1 private ChannelFuture doBind(final SocketAddress localAddress) {
2 final ChannelFuture regFuture = initAndRegister();
3 final Channel channel = regFuture.channel();
4 if (regFuture.cause() != null) {
5 return regFuture;
6 }
7
8 if (regFuture.isDone()) {
9 // At this point we know that the registration was complete and successful.
10 ChannelPromise promise = channel.newPromise();
11 doBind0(regFuture, channel, localAddress, promise);
12 return promise;
13 } else {
14 // Registration future is almost always fulfilled already, but just in case it's not.
15 final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
16 regFuture.addListener(new ChannelFutureListener() {
17 @Override
18 public void operationComplete(ChannelFuture future) throws Exception {
19 Throwable cause = future.cause();
20 if (cause != null) {
21 // Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
22 // IllegalStateException once we try to access the EventLoop of the Channel.
23 promise.setFailure(cause);
24 } else {
25 // Registration was successful, so set the correct executor to use.
26 // See https://github.com/netty/netty/issues/2586
27 promise.registered();
28
29 doBind0(regFuture, channel, localAddress, promise);
30 }
31 }
32 });
33 return promise;
34 }
35 }
initAndRegister() 方法通过 ChannelFactory 创建 NioServerSocketChannel。
1 final ChannelFuture initAndRegister() {
2 Channel channel = null;
3 try {
4 channel = channelFactory.newChannel();
5 init(channel);
6 } catch (Throwable t) {
7 if (channel != null) {
8 // channel can be null if newChannel crashed (eg SocketException("too many open files"))
9 channel.unsafe().closeForcibly();
10 // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
11 return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
12 }
13 // as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
14 return new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE).setFailure(t);
15 }
16
17 ChannelFuture regFuture = config().group().register(channel);
18 if (regFuture.cause() != null) {
19 if (channel.isRegistered()) {
20 channel.close();
21 } else {
22 channel.unsafe().closeForcibly();
23 }
24 }
25
26 // If we are here and the promise is not failed, it's one of the following cases:
27 // 1) If we attempted registration from the event loop, the registration has been completed at this point.
28 // i.e. It's safe to attempt bind() or connect() now because the channel has been registered.
29 // 2) If we attempted registration from the other thread, the registration request has been successfully
30 // added to the event loop's task queue for later execution.
31 // i.e. It's safe to attempt bind() or connect() now:
32 // because bind() or connect() will be executed *after* the scheduled registration task is executed
33 // because register(), bind(), and connect() are all bound to the same thread.
34
35 return regFuture;
36 }
Channel 的四个状态:
状态 | 描述 |
---|---|
channelUnRegistered | 频道创建后但未注册到一个EventLoop |
channelRegistered | 频道注册到一个EventLoop |
channelActive | channel的活动的(连接到了它的remote peer),现在可以接收和发送数据了 |
channelInactive | channel没有连接到远程对等 |
Channel 的正常生命周期如下图,当这些状态变化出现,对应的事件将会生成,这样与 ChannelPipeline 中的 ChannelHandler 的交互能够及时响应:
参考:Netty源码分析之一揭开Bootstrap神秘的红盖头(客户端),Netty分析--Channel的创建
Netty:Netty的介绍以及它的核心组件(一)—— Channel的更多相关文章
- Netty:Netty的介绍以及它的核心组件(二)—— ChannelFuture与回调
Callback 回调 一个 Callback(回调)就是一个方法,一个提供给另一个的方法的引用. 这让另一个方法可以在适当的时候回过头来调用这个 callback 方法.Callback 在很多编程 ...
- Netty重要概念介绍
Netty重要概念介绍 Bootstrap Netty应用程序通过设置bootstrap(引导)类开始,该类提供了一个用于网络成配置的容器. 一种是用于客户端的Bootstrap 一种是用于服务端的S ...
- 5. 彤哥说netty系列之Java NIO核心组件之Channel
你好,我是彤哥,本篇是netty系列的第五篇. 简介 上一章我们一起学习了如何使用Java原生NIO实现群聊系统,这章我们一起来看看Java NIO的核心组件之一--Channel. 思维转变 首先, ...
- netty05(netty的一些介绍)
netty的一些理论 netty是一个异步事件驱动的网络应用框架(NIO框架),所有IO操作都是异步非阻塞的,NIO是对IO的一个补充 用于开发客户端和服务器的通信(TCP/UDP)长短连接 nett ...
- [Netty] - Netty IN ACTION(导言)
最近没什么事儿做,刚好看到有需要网络编程的知识,java中有NIO和IO两种不同的方式,但是NIO的编写比较麻烦,刚好找到一个成熟的网络框架Netty.接下来的一个月就准备将Netty IN ACTI ...
- Netty:Netty的介绍以及它的核心组件(三)—— 事件和ChannelHandler
Netty 使用异步事件驱动(Asynchronous Event-Driven)的应用程序范式,因此数据处理的管道(ChannelPipeLine)是经过处理程序(ChannelHandler)的事 ...
- Netty——基本使用介绍
https://blog.csdn.net/haoyuyang/article/details/53243785 1.为什么选择Netty 上一篇文章我们已经了解了Socket通信(IO/NIO/AI ...
- netty核心组件之channel、handler、ChannelHandlerContext、pipeline
channel介绍: netty中channel分为NioServerScoketChannel和NioSocketChannel,分别对应java nio中的ServerScoketChannel和 ...
- Java NIO框架Mina、Netty、Grizzly介绍与对比(zz)
Mina:Mina(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用 ...
随机推荐
- [第十五篇]——Swarm 集群管理之Spring Cloud直播商城 b2b2c电子商务技术总结
Swarm 集群管理 简介 Docker Swarm 是 Docker 的集群管理工具.它将 Docker 主机池转变为单个虚拟 Docker 主机. Docker Swarm 提供了标准的 Dock ...
- 使用 mysql 的 Docker 镜像
使用 mysql 的 Docker 镜像 前言 之前搞了很多都是手工在操作系统的镜像中安装使用 mysql,作为自己折腾也就算了,作为实际使用实为不妥:Docker最重要的特性就是可扩展性,把各种程序 ...
- 论文解读(PCL)《Prototypical Contrastive Learning of Unsupervised Representations》
论文标题:Prototypical Contrastive Learning of Unsupervised Representations 论文方向:图像领域,提出原型对比学习,效果远超MoCo和S ...
- DP之背包经典三例
0/1背包 HDU2602 01背包(ZeroOnePack): 有N件物品和一个容量为V的背包,每种物品均只有一件.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使价值总和最大 ...
- 超详细:command not found:scrapy解决办法(Mac下给zsh添加scrapy环境变量)
背景:本来打算用scrapy 创一个爬虫项目,但是无论如何都显示zsh: command not found: scrapy,看了很多篇blog才解决了问题,决定记录一下. 主要参考的blog: ht ...
- html jquey的选择器checkbox,select
1 判断checkbox是否选中 用到 jquery的 is方法 jquery: <div id="divId" class="divTable"> ...
- WireShark新手使用教程
Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息.常用于开发测试过程各种问题定位.本文主要内容包括: 1.Wireshark软件下载和安装以及Wiresha ...
- Appium WebView控件定位
背景 移动应用可以粗分为三种:原生应用(native app), 网页应用(web app,或HTML5 app),以及它们的混血儿--混合模式移动应用(hybrid app). 什么是Hybrid ...
- 《使用Jmeter进行批量发送http请求》
本文主要针对批量接口发送数据 一:接口测试的环境准备 1:JDK的安装:网上下载即可>1.6.0版本以上 2:jemeter工具的下载 (免安装):网上下载即可 3:插件的下载安装地址:http ...
- 『PyTorch』矩阵乘法总结
1. 二维矩阵乘法 torch.mm() torch.mm(mat1, mat2, out=None),其中mat1(\(n\times m\)),mat2(\(m\times d\)),输出out的 ...