从零开始学习Netty - 学习笔记 -Netty入门-ChannelFuture

5.2.2.Channel

Channel 的基本概念

在 Netty 中,Channel 是表示网络传输的开放连接的抽象。它提供了对不同种类网络传输的统一视图,比如 TCP 和 UDP。

Channel 的生命周期

Channel 的生命周期包括创建、激活、连接、读取、写入和关闭等阶段。Netty 中的 Channel 具有状态,根据不同的事件触发状态转换。

Channel channel = ...; // 获取 Channel 实例// 检查 Channel 是否打开
if (channel.isOpen()) {// 进行数据读取操作channel.read();
}// 关闭 Channel
channel.close();

Channel 的异步 I/O

Netty 中的 Channel 支持异步的 I/O 操作,这意味着可以在不阻塞线程的情况下进行网络通信。下面是一个简单的读取操作示例:

// 从 Channel 中读取数据
channel.read(new ChannelHandler() {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {// 处理读取到的数据ByteBuf buf = (ByteBuf) msg;System.out.println(buf.toString(Charset.defaultCharset()));buf.release(); // 释放资源}
});

ChannelHandler 和 ChannelPipeline

ChannelHandler 用于处理入站和出站的事件,而 ChannelPipeline 是一系列 ChannelHandler 的链,负责处理 Channel 传递的事件。

// 创建一个 ChannelInitializer 用于初始化 ChannelPipeline
ChannelInitializer<SocketChannel> initializer = new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ChannelPipeline pipeline = ch.pipeline();// 添加自定义的 ChannelHandler 到 ChannelPipeline 中pipeline.addLast("handler", new MyChannelHandler());}
};// 在 ServerBootstrap 中应用 ChannelInitializer
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(eventLoopGroup).channel(NioServerSocketChannel.class).childHandler(initializer); 

channel的主要作用

  • close():主要用来关闭channel
  • **closeFuture():**用来处理channel的关闭
    • sync方法作用是同步等待channel的关闭
    • addListener方法是异步等待channel关闭
  • **pipeline():**方法添加处理器
  • **write():**方法是将数据写入
  • **writeAndFlush():**方法是将数据写入并刷出

例如刚刚的客户端代码

		// 1.创建启动器try {new Bootstrap()// 2.指定线程模型 一个用于接收客户端连接,另一个用于处理客户端读写.group(new NioEventLoopGroup())// 3.选择客户端的Channel的实现.channel(NioSocketChannel.class)// 4.添加处理器.handler(new ChannelInitializer<NioSocketChannel>() {// 5.初始化处理器@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {// 6.添加具体的handler 客户端是需要一个编码器ch.pipeline().addLast(new StringEncoder());}})// 7.连接到服务器.connect(new InetSocketAddress("localhost", 8080)).sync() // 阻塞方法 知道连接建立.channel() // 代表客户端和服务端的连接// 8.向服务器发送数据.writeAndFlush("hello, world");} catch (InterruptedException e) {throw new RuntimeException(e);}
5.2.2.1.连接问题sync
			// 1.创建启动器try {ChannelFuture channelFuture = new Bootstrap().group(new NioEventLoopGroup()).channel(NioSocketChannel.class).handler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast(new StringEncoder());}})// 7.连接到服务器// connect方法是异步的,返回一个ChannelFuture(异步调用 就是不关心结果,直接返回)// main线程发起了调用,真正执行了connect是另外一个线程 nio线程.connect(new InetSocketAddress("localhost", 8080));// 7.1.同步等待连接成功 如果不调用sync()方法,main线程会继续往下执行,不会等待connect()方法的执行结果channelFuture.sync();// 7.2.获取连接对象 如果没有调用sync()方法,这里的channel此时还没有真正建立起连接Channel channel = channelFuture.channel(); // 连接对象logger.error("channel: {}", channel);// 8.向服务器发送数据channel.writeAndFlush("hello, world");} catch (Exception e) {throw new RuntimeException(e);}

image-20240226071218470

image-20240226071322706

5.2.2.2.处理结果

带有Future Promise 的类型,都是和异步方法配套使用的,用来正确处理结果的

  • 调用channelFuture.sync()处理同步结果,sync()主要是阻塞当前线程,直到nio线程连接建立完毕

  • 使用addListener(new ChannelFutureListener() )

    • 	// 使用addListener(回调对象)方法,可以在ChannelFuture执行完成后,再执行一些操作channelFuture.addListener(new ChannelFutureListener() {// 在NIO线程连接建立好后,会调用operationComplete方法@Overridepublic void operationComplete(ChannelFuture channelFuture) throws Exception {if (channelFuture.isSuccess()) {// 7.2.获取连接对象 如果没有调用sync()方法,这里的channel就会是nullChannel channel = channelFuture.channel(); // 连接对象logger.error("channel: {}", channel);// 8.向服务器发送数据channel.writeAndFlush("hello, world");} else {// 7.3.连接失败Throwable cause = channelFuture.cause();logger.error("connect failed: {}", cause);}}});
      
5.2.2.3.处理关闭

小需求 : 客户端 不断接收用于输入的信息,然后发送给客户端,当用户端输入q 退出 关闭channel

/**** @author 13723* @version 1.0* 2024/2/27 21:46*/
public class CloseFutureClient {private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());public static void main(String[] args) throws InterruptedException {ChannelFuture channelFuture = new Bootstrap().group(new NioEventLoopGroup()).channel(NioSocketChannel.class).handler(new ChannelInitializer<NioSocketChannel>() {@Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast(new StringEncoder());}}).connect(new InetSocketAddress("localhost", 8080));// 客户端 不断接收用于输入的信息,然后发送给客户端,当用户端输入q 退出// 建立建立Channel channel = channelFuture.sync().channel();logger.error("channel: {} ",channel);// 接收用户输入的需求new Thread(()->{Scanner scanner = new Scanner(System.in);while (true){String s = scanner.nextLine();if ("q".equals(s)){// 退出 关闭channel// 1s 后才真正的关闭channel.close();// 退出循环logger.error("处理关闭之后的操作!");break;}// 向服务器 发送数据channel.writeAndFlush(s);}},"input").start();}
}

在这里插入图片描述

在这里插入图片描述

  • 解决

    • 使用CloseFuture.sync()

      		// 关闭Channel// 获取closeFuture对象 1.同步受理关闭 2.异步处理关闭ChannelFuture closeFuture = channel.closeFuture();logger.error("wait close... ");closeFuture.sync();logger.error("处理关闭之后的操作!");
      

      在这里插入图片描述

    • 使用addListener(new ChannelFutureListener())

      		closeFuture.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture channelFuture) throws Exception {logger.error("处理关闭之后的操作!");}});
      

      在这里插入图片描述

`

此时关闭,会会发现客户端并没有结束,因为线程虽然结束,但是NioEventLoopGroup 里面可能还有线程,这是时关闭,需要调

**shutdownGracefully()**方法

// 将NioEventLoopGroup提出来  
NioEventLoopGroup group = new NioEventLoopGroup();
ChannelFuture channelFuture = new Bootstrap().group(group)
.........// 然后在处理善后中调用 
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {logger.error("处理关闭之后的操作!");// 需要保证整个全部关闭group.shutdownGracefully();
}

在这里插入图片描述

5.2.2.4.为什么使用异步

思考下面这样的场景,4个医生给人看病,每个病人花费20分钟,而且医生看病的过程中,是以病人为单位的,一个病人看完了,才能看下一个病人,假设病人源源不断来,可以计算一天4个医生工作8小时,处理病人总数 4 * 8 * 3 = 96

在这里插入图片描述

经研究 发现 看病可以分为 四个步骤 经拆分后每个步骤仅需要五分钟

在这里插入图片描述

因此 可以做如下优化,只有一开始, 医生 2 3 4 需要分别等待 5 10 15分钟开能开始执行工作,但是只要后续病人源源不断的来,他们就能满负荷工作,并且处理病人的能力提高 到了, 4 * 8 * 12 整个效率 是原先的 4 倍

(满负载情况下)第一个医生 只挂号,一个号五分钟,那么 一个小时 可以处理 12个,之前一个医生从头到尾只能看一个病人,那么一个小时只能看3个

在这里插入图片描述

  • 单线程没法异步提高效率,必须配合多线程,多核心cpu才能发挥异步的优势
  • 异步并没有缩短响应时间,反而有所增加(提高的是吞吐量,单位时间内能够处理请求的速度)
  • 合理任务的拆分,也是利用异步的关键

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/496450.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习-02-机器学习算法分类以及在各行各业的应用

总结 本系列是机器学习课程的第02篇&#xff0c;主要介绍机器学习算法分类以及在各行各业的应用 本门课程的目标 完成一个特定行业的算法应用全过程&#xff1a; 定义问题&#xff08;Problem Definition&#xff09; -> 数据收集(Data Collection) -> 数据分割(Data…

harbor配置目录被误删后救援

我司微服务产品的业务镜像&#xff0c;在客户现场上云安全检测中发现需要打补丁&#xff1b;放在角落、时不常用一次的harbor镜像仓库需要用到了&#xff1a;将加固后的基础镜像上传以备份&#xff0c;方便其他同学拉取使用。 然鹅&#xff0c;启动后harbor-db频繁重启 harbo…

Niginx介绍和安装使用

Nginx是什么&#xff1f; Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.ru站点&#xff08;俄文&#xff1a;Рамблер&#xff09;开发的&#xff0c;第一…

C语言————结构体

接下来我们来了解C语言中很重要的内容&#xff1a;结构体。虽然到现在我们可以创建常量&#xff0c;变量&#xff0c;数组&#xff0c;但是存储的都是相同类型的数据&#xff0c;如果我们需要写入不同数据类型的信息怎么办&#xff0c;例如常见的身份证上的信息&#xff0c;有身…

FL Studio 21 Mac汉化免费版 附安装教程

FL Studio 21 Mac是Mac系统中的一款水果音乐编辑软件&#xff0c;提供多种插件&#xff0c;包括采样器、合成器和效果器&#xff0c;可编辑不同风格的音乐作品&#xff0c;Pattern/Song双模式&#xff0c;可兼容第三方插件和音效包&#xff0c;为您的创意插上翅膀。FL Studio 2…

腾讯云4核8G的云服务器性能水平?使用场景说明

腾讯云4核8G服务器适合做什么&#xff1f;搭建网站博客、企业官网、小程序、小游戏后端服务器、电商应用、云盘和图床等均可以&#xff0c;腾讯云4核8G服务器可以选择轻量应用服务器4核8G12M或云服务器CVM&#xff0c;轻量服务器和标准型CVM服务器性能是差不多的&#xff0c;轻…

js 面试题--事件循环event loop--宏任务和微任务

1 事件循环event loop概念&#xff1a; js 是非阻塞单线程语言&#xff0c;js在执行过程中会产生执行环境&#xff0c;执行环境会按顺序添加到执行栈中&#xff0c;先执行同步栈中的任务&#xff0c;当遇到异步任务时会添加到task队列中&#xff0c;同步栈执行完后&#xff0c…

【从零开始学习重要知识点 | 第一篇】快速了解什么是幂等性以及常见解决方案

前言&#xff1a; 当我们在设计和实现分布式系统时&#xff0c;幂等性是一个非常重要的概念。幂等性可以简单地理解为&#xff1a;对于同一操作&#xff0c;不论执行多少次&#xff0c;产生的影响都是相同的。这个概念在分布式系统中非常重要&#xff0c;因为在这种环境下&…

NC65 rest接口 开发 NC65接口开发

一、在对应模块META-INF下编写 xxx.rest 文件,也要放在Home里对应的目录下。 二、开发接口&#xff0c;继承extends AbstractUAPRestResource&#xff0c;&#xff08;有的项目会继承别的方法如&#xff1a;AbstractNCCRestResource&#xff0c;MTFRestResource&#xff1b;有…

可视化图文报表

Apache Echarts介绍 Apache Echarts是一款基于Javascript的数据可视化图表库&#xff0c;提供直观&#xff0c;生动&#xff0c;可交互&#xff0c;可个性化定制的数据可视化图表。 官网&#xff1a;Apache ECharts 入门案例&#xff1a; <!DOCTYPE html> <html>…

Openstack云计算架构及前期服务搭建

openstack介绍 Openstack是一个开源的云计算管理平台项目&#xff0c;由几个主要的组件组合起来完成具体工作&#xff0c;支持几乎所有的云环境&#xff0c;项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台 ----百度百科 Openstack是一个云操作系统&a…

【Day59】代码随想录之动态规划_583两个字符串的删除操作_72编辑距离

文章目录 动态规划理论基础动规五部曲&#xff1a;出现结果不正确&#xff1a; 1. 583两个字符串的删除操作2. 72编辑距离 动态规划理论基础 动规五部曲&#xff1a; 确定dp数组 下标及dp[i] 的含义。递推公式&#xff1a;比如斐波那契数列 dp[i] dp[i-1] dp[i-2]。初始化d…