【Netty】 工作原理详解(十一)
文章目录
- 前言
- 一、Netty 模型
- 二、代码示例
- 2.1、引入Maven依赖
- 2.2、服务端的管道处理器
- 2.3、服务端主程序
- 2.4、客户端管道处理器
- 2.5、客户端主程序
- 2.6、测试运行
- 总结
前言
回顾Netty系列文章:
- Netty 概述(一)
- Netty 架构设计(二)
- Netty Channel 概述(三)
- Netty ChannelHandler(四)
- ChannelPipeline源码分析(五)
- 字节缓冲区 ByteBuf (六)(上)
- 字节缓冲区 ByteBuf(七)(下)
- Netty 如何实现零拷贝(八)
- Netty 程序引导类(九)
- Reactor 模型(十)
一、Netty 模型
下图就是 Netty 的工作原理图:

执行流程如下:
-
Netty 抽象出两组线程池 BossGroup 专门负责接收客户端的连接,WorkerGroup 专门负责网络的读写。
-
BossGroup 和 WorkerGroup 类型都是 NioEventLoopGroup。
-
NioEventLoopGroup 相当于一个事件循环组,这个组中含有多个事件循环 ,每一个事件循环是 NioEventLoop。
-
NioEventLoop 表示一个不断循环的执行处理任务的线程, 每个NioEventLoop 都有一个selector ,用于监听绑定在其上的 socket 的网络通讯。
-
NioEventLoopGroup 可以有多个线程,即可以含有多个 NioEventLoop。
-
每个Boss NioEventLoop 循环执行的步骤有3步 :
- 轮询accept 事件 ;
- 处理accept 事件 ,与 client 建立连接 ,生成 NioScocketChannel,并将其注册到某个 worker NIOEventLoop 上的 selector;
- 处理任务队列的任务 , 即 runAllTasks。
-
每个 Worker NIOEventLoop 循环执行的步骤 :
- 轮询read,write 事件 处理 I/O 事件, 即 read , write 事件;
- 在对应NioScocketChannel处理;
- 处理任务队列的任务 , 即 runAllTasks;
-
每个Worker NIOEventLoop 处理业务时,会使用pipeline(管道),pipeline 中包含了channel ,即通过pipeline 可以获取到对应通道,管道中维护了很多的 处理器(ChannelHandler)。
二、代码示例
2.1、引入Maven依赖
<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.49.Final</version>
</dependency>
2.2、服务端的管道处理器
public class NettyServerHandler extends ChannelInboundHandlerAdapter {//读取数据实际(这里我们可以读取客户端发送的消息)/*1. ChannelHandlerContext ctx:上下文对象, 含有 管道pipeline , 通道channel, 地址2. Object msg: 就是客户端发送的数据 默认Object*/@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println("server ctx =" + ctx);Channel channel = ctx.channel();//将 msg 转成一个 ByteBuf//ByteBuf 是 Netty 提供的,不是 NIO 的 ByteBuffer.ByteBuf buf = (ByteBuf) msg;System.out.println("客户端发送消息是:" + buf.toString(CharsetUtil.UTF_8));System.out.println("客户端地址:" + channel.remoteAddress());}//数据读取完毕@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {//writeAndFlush 是 write + flush//将数据写入到缓存,并刷新//一般讲,我们对这个发送的数据进行编码ctx.writeAndFlush(Unpooled.copiedBuffer("公司最近账户没啥钱,再等几天吧!", CharsetUtil.UTF_8));}//处理异常, 一般是需要关闭通道@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close();}
}
2.3、服务端主程序
public class NettyServer {public static void main(String[] args) throws Exception {//创建BossGroup 和 WorkerGroup//说明//1. 创建两个线程组 bossGroup 和 workerGroup//2. bossGroup 只是处理连接请求 , 真正的和客户端业务处理,会交给 workerGroup完成//3. 两个都是无限循环//4. bossGroup 和 workerGroup 含有的子线程(NioEventLoop)的个数// 默认实际 cpu核数 * 2//EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup(); //8try {//创建服务器端的启动对象,配置参数ServerBootstrap bootstrap = new ServerBootstrap();//使用链式编程来进行设置bootstrap.group(bossGroup, workerGroup) //设置两个线程组.channel(NioServerSocketChannel.class) //bossGroup使用NioSocketChannel 作为服务器的通道实现.option(ChannelOption.SO_BACKLOG, 128) // 设置线程队列得到连接个数 option主要是针对boss线程组,.childOption(ChannelOption.SO_KEEPALIVE, true) //设置保持活动连接状态 child主要是针对worker线程组.childHandler(new ChannelInitializer<SocketChannel>() {//workerGroup使用 SocketChannel创建一个通道初始化对象 (匿名对象)//给pipeline 设置处理器@Overrideprotected void initChannel(SocketChannel ch) throws Exception {//可以使用一个集合管理 SocketChannel, 再推送消息时,可以将业务加入到各个channel 对应的 NIOEventLoop 的 taskQueue 或者 scheduleTaskQueuech.pipeline().addLast(new NettyServerHandler());}}); // 给我们的workerGroup 的 EventLoop 对应的管道设置处理器System.out.println(".....服务器 is ready...");//绑定一个端口并且同步, 生成了一个 ChannelFuture 对象//启动服务器(并绑定端口)ChannelFuture cf = bootstrap.bind(7788).sync();//给cf 注册监听器,监控我们关心的事件cf.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture future) throws Exception {if (cf.isSuccess()) {System.out.println("服务已启动,端口号为7788...");} else {System.out.println("服务启动失败...");}}});//对关闭通道进行监听cf.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
NioEventLoopGroup是用来处理I/O操作的多线程事件循环器。Netty 提供了许多不同的EventLoopGroup的实现来处理不同的传输。
上面的服务端应用中,有两个NioEventLoopGroup被使用。第一个叫作bossGroup,用来接收进来的连接。第二个叫作workerGroup,用来处理已经被接收的连接,一旦 bossGroup接收连接,就会把连接的信息注册到workerGroup上。
ServerBootstrap是一个NIO服务的引导启动类。可以在这个服务中直接使用Channel。
- group方法用于 设置EventLoopGroup。
- 通过Channel方法,可以指定新连接进来的Channel类型为NioServerSocketChannel类。
- childHandler用于指定ChannelHandler,也就是前面实现的NettyServerHandler。
- 可以通过option设置指定的Channel来实现NioServerSocketChannel的配置参数。
- childOption主要设置SocketChannel的子Channel的选项。
- bind用于绑定端口启动服务。
2.4、客户端管道处理器
public class NettyClientHandler extends ChannelInboundHandlerAdapter {//当通道就绪就会触发该方法@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("client ctx =" + ctx);ctx.writeAndFlush(Unpooled.copiedBuffer("老板,工资什么时候发给我啊?", CharsetUtil.UTF_8));}//当通道有读取事件时,会触发@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf = (ByteBuf) msg;System.out.println("服务器回复的消息:" + buf.toString(CharsetUtil.UTF_8));System.out.println("服务器的地址: "+ ctx.channel().remoteAddress());}//处理异常, 一般是需要关闭通道@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}
}
2.5、客户端主程序
public class NettyClient {public static void main(String[] args) throws Exception {//客户端需要一个事件循环组EventLoopGroup group = new NioEventLoopGroup();try {//创建客户端启动对象//注意客户端使用的不是 ServerBootstrap 而是 BootstrapBootstrap bootstrap = new Bootstrap();//设置相关参数bootstrap.group(group) //设置线程组.channel(NioSocketChannel.class) // 设置客户端通道的实现类(反射).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new NettyClientHandler()); //加入自己的处理器}});System.out.println("客户端 ok..");//启动客户端去连接服务器端//关于 ChannelFuture 要分析,涉及到netty的异步模型ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 7788).sync();//给关闭通道进行监听channelFuture.channel().closeFuture().sync();} finally {group.shutdownGracefully();}}
}
客户端只需要一个NioEventLoopGroup就可以了。
2.6、测试运行
分别启动服务器 NettyServer 和客户端 NettyClient程序
服务端控制台输出内容:
服务器 is ready...
服务已启动,端口号为7788...
server ctx =ChannelHandlerContext(NettyServerHandler#0, [id: 0xa1b2233c, L:/127.0.0.1:7788 - R:/127.0.0.1:63239])
客户端发送消息是:老板,工资什么时候发给我啊?
客户端地址:/127.0.0.1:63239
客户端控制台输出内容:
客户端 ok..
client ctx =ChannelHandlerContext(NettyClientHandler#0, [id: 0x21d6f98e, L:/127.0.0.1:63239 - R:/127.0.0.1:7788])
服务器回复的消息:公司最近账户没啥钱,再等几天吧!
服务器的地址: /127.0.0.1:7788
至此,一个简单的基于Netty开发的服务端和客户端就完成了。
总结
本篇文章主要讲解了 Netty 的工作原理及简单应用。下节我们来讲解 Netty 的编解码。
。
相关文章:
【Netty】 工作原理详解(十一)
文章目录 前言一、Netty 模型二、代码示例2.1、引入Maven依赖2.2、服务端的管道处理器2.3、服务端主程序2.4、客户端管道处理器2.5、客户端主程序2.6、测试运行 总结 前言 回顾Netty系列文章: Netty 概述(一)Netty 架构设计(二&…...
SQL面试必备:100道高频考题解析
前言 在众多IT职场中,SQL技术一直是一个非常重要的技能点。如果你正在准备SQL相关的面试,那么这份“SQL面试 100 问”绝对是你不能错过的宝藏! 这份清单涵盖了100道高频考题,从基础知识到复杂应用都有所涉及,帮助你全…...
基于区域的图像分割
文章目录 基于区域的图像分割基本原理常用的算法实现步骤示例代码结论 基于区域的图像分割 基于区域的图像分割是数字图像处理中常用的一种方法,它通过将图像中的像素分配到不同的区域或对象来实现图像分割的目的。相比于基于边缘或阈值的方法,基于区域…...
【Python json】零基础也能轻松掌握的学习路线与参考资料
Python中的JSON模块主要用于将Python对象序列化成JSON数据或解析包含JSON数据的字符串。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。由于JSON在Web应用中的广泛使用…...
大数据开发之Hive案例篇8-解析XML
文章目录 一. 问题描述二. 解决方案2.1 官方文档2.2 XML格式不规范 一. 问题描述 今天接到一个新需求,hive表里面有个字段存储的是XML类型数据 数据格式: <a><b>bb</b><c>cc</c> </a>二. 解决方案 2.1 官方文档 遇到不懂的…...
Sentinel降级规则
1.降级规则简介 官方文档 熔断降级概述 除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的…...
基于非靶向和靶向代谢组学分析婴幼儿血管瘤的氨基酸代谢
文章标题:Integrated nontargeted and targeted metabolomics analyses amino acids metabolism in infantile hemangioma 发表期刊:Frontiers in Oncology 影响因子:5.738 作者单位:四川大学华西医院 百趣提供服务…...
程序员困局:去大城市进大厂却买不了房,回老家又没有高薪工作…
对于在外打拼的程序员来说,难的是进大厂,而不是买不起房。 进大厂的程序员,能不能买得起房? 进大厂的程序员的薪资,还是相当可观的。以阿里P6为例,年薪50万,到手40万左右,刨去10万…...
数字化转型下企业 IT 发展趋势-大企业自主研发,中小企业上云
在当今数字化转型的时代,企业IT发展面临着许多挑战和机遇。对于大中小型企业而言,数字化转型已成为实现竞争优势和业务增长的关键因素之一。在这个过程中,大企业和中小企业采取了不同的策略来推动其IT发展,其中大企业更加注重自主…...
【Go语言从入门到实战】面向对象编程篇
面向对象编程 Go语言的面向对象编程和其他语言有非常大的差别。 Go 是一种面向对象的语言吗? 是和不是。虽然 Go 有类型和方法,并允许面向对象的编程风格,但没有类型层次结构(继承)。Go 中的“接口”概念提供了一种不…...
代码随想录算法训练营第四十五天 | 力扣 70. 爬楼梯(进阶), 322. 零钱兑换, 279.完全平方数
70. 爬楼梯(进阶) 题目 70. 爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 改为:一步一个台阶,两个台阶,三个台阶ÿ…...
dvwa靶场通关(三)
第三关:CSRF(跨站请求伪造) csrf跨站请求伪造:是一种对网站的恶意利用。尽管听起来像跨站脚本,但它与xss非常不同,xss利用站点内受信任用户,而csrf则通过伪造来自受信任用户的请求来利用受信任…...
【计算机图形学】理论考核回顾
写在前面: 1:题型主要是单选题多选题判断题计算题,题目量居多,一定要合理安排时间。 2:小题由于太琐碎了,遂不回顾,大致都是课件上做过的小题,嗯。 3:后续有时间更新期…...
一文了解国内外电子后视镜(CMS)现行法规标准
摘要: 本文小编分享一篇整合了国内外对CMS的安装及功能性做出要求的相关标准与法规。感兴趣的朋友可以专门去搜索学习。 前言:随着GB15084-2022的即将正式实施,以摄像头屏幕组合取代传统光学后视镜的新一代电子后视镜CMS相关车型将被允许上路…...
LabVIEWCompactRIO 开发指南36 确定“Clock Ticks”或模拟时间
LabVIEWCompactRIO 开发指南36 确定“Clock Ticks”或模拟时间 桌面执行节点可以控制模拟时间,因此开发人员可以使用模拟I/O在开发计算机上执行期间更改关键点的激励。要成功使用此功能,需要测量FPGA VI完成所需的时间,或者需要以直观地知道…...
ESP32 :项目的创建及项目架构解析
一、项目的创建 方式一:基于IDF示例创建 在ESP-IDF中有example示例库,以其中的一个示例为模板创建项目。 1、打开示例库 查看 - 命令面板(也可以按住CtrlShiftP 或 F1) 输入 show examples projects 2…...
TI EDI 项目数据库方案开源介绍
TI EDI 工作流简介 TI EDI到SQL Server示例流具有预配置的端口,用于从TI的EDI集成规范转换以下交易集: 850 采购订单,企业 -> TI855 采购订单确认,TI -> 企业860 采购订单变更,企业 -> TI865 采购订单变更确认,TI -> 企业856 发货通知,TI …...
报表控件FastReport使用指南——使用NuGet包创建PDF文档
FastReport 是功能齐全的报表控件,可以帮助开发者可以快速并高效地为.NET,VCL,COM,ActiveX应用程序添加报表支持,由于其独特的编程原则,现在已经成为了Delphi平台最优秀的报表控件,支持将编程开…...
策略模式-类型统计
文章目录 前言一、策略模式是什么?二、策略模式应用场景三、策略模式优点四、策略模式缺点五、场景案例:类型统计1.项目结构2.UML图解3.代码实现3.1 指标枚举3.2 请求体3.3 响应体3.4.分析统计指标策略3.5.接口3.6.扩展接口3.7.接口实现3.8.控制层 六、P…...
android 12.0app应用安装白名单
1.概述 在12.0定制化开发中,客户需求要实现应用安装白名单功能,在白名单之中的应用可以安装,其他的app不准安装,实现一个 控制app安装的功能,这需要从app安装流程入手就可以实现功能 PMS就是负责管理app安装的,功能就添加在这里就可以了, 2.app应用安装白名单核心代码 …...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
