Netty 网络编程的秘籍,看这一篇够了

news/2024/4/26 20:59:48/文章来源:https://blog.csdn.net/LINgZone2/article/details/131021506

Netty

version: 4.1.55.Final

传统的IO模型的web容器,比如老版本的Tomcat,为了增加系统的吞吐量,需要不断增加系统核心线程数量,或者通过水平扩展服务器数量,来增加系统处理请求的能力。 有了NIO之后,一个线程即可处理多个连接事件,基于多路复用模型的Netty框架,不仅降低了使用NIO的复杂度,

优点

Netty是一款以java NIO为基础,基于事件驱动模型支持异步、高并发的网络应用框架

  • API使用简单,开发门槛低,简化了NIO开发网络程序的复杂度

  • 功能强大,预置多种编解码功能,支持多种主流协议,比如Http、WebSocket。

  • 定制能力强,可以通过ChannelHandler对通信框架灵活扩展。

  • 性能高,支持异步非阻塞通信模型

  • 成熟稳定,社区活跃,已经修复了Java NIO所有的Bug。

  • 经历了大规模商业应用的考验,质量有保证。

IO模型

select、poll和epoll

操作系统内核基于这些函数实现非阻塞IO,以此实现多路复用模型

  • select

select

  1. select 调用需要传入 fd 数组,需要拷贝一份到内核,高并发场景下这样的拷贝消耗的资源是惊人的。(可优化为不复制)

  2. select 在内核层仍然是通过遍历的方式检查文件描述符的就绪状态,是个同步过程,只不过无系统调用切换上下文的开销。(内核层可优化为异步事件通知)

  3. select 仅仅返回可读文件描述符的个数,具体哪个可读还是要用户自己遍历。(可优化为只返回给用户就绪的文件描述符,无需用户做无效的遍历)

  • pool

和 select 的主要区别就是,去掉了 select 只能监听 1024 个文件描述符的限制

  • epool

epool

  1. 内核中保存一份文件描述符集合,无需用户每次都重新传入,只需告诉内核修改的部分即可。

  2. 内核不再通过轮询的方式找到就绪的文件描述符,而是通过异步 IO 事件唤醒。

  3. 内核仅会将有 IO 事件的文件描述符返回给用户,用户也无需遍历整个文件描述符集合。

Reactor模型

一、单Reactor单线程 1)可以实现通过一个阻塞对象监听多个链接请求

2)Reactor对象通过select监听客户端请求事件,通过dispatch进行分发

3)如果是建立链接请求,则由Acceptor通过accept处理链接请求,然后创建一个Handler对象处理完成链接后的各种事件

4)如果不是链接请求,则由Reactor分发调用链接对应的Handler来处理

5)Handler会完成Read->业务处理->send的完整业务流程

reactor

二、单Reactor多线程 1)Reactor对象通过select监听客户端请求事件,收到事件后,通过dispatch分发

2)如果是建立链接请求,则由Acceptor通过accept处理链接请求,然后创建一个Handler对象处理完成链接后的各种事件

3)如果不是链接请求,则由Reactor分发调用链接对应的Handler来处理

4)Handler只负责事件响应不做具体业务处理

5)通过read读取数据后,分发到worker线程池处理,处理完成后返回给Handler,Handler收到后,通过send将结果返回给client

reactor

三、主从Reactor多线程 1)Reactor主线程MainReactor对象通过select监听链接事件,通过Acceptor处理

2)当Acceptor处理链接事件后,MainReactor将链接分配给SubReactor

3)SubReactor将链接加入到队列进行监听,并创建Handler进行事件处理

4)当有新事件发生时,SubReactor就会调用对应的Handler处理

5)Handler通过read读取数据,分发到worker线程池处理,处理完成后返回给Handler,Handler收到后,通过send将结果返回给client

6)Reactor主线程可以对应多个Reactor子线程

reactor

三种模式用生活案例来理解 1)单Reactor单线程,前台接待员和服务员是同一个人,全程为顾客服务

2)单Reactor多线程,1个前台接待员,多个服务员,接待员只负责接待

3)主从Reactor多线程,多个前台接待员,多个服务员

Reactor模型具有如下优点 1)响应快,不必为单个同步事件所阻塞,虽然Reactor本身依然是同步的

2)可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销

3)扩展性好,可以方便的通过增加Reactor实例个数来充分利用CPU资源

4)复用性好,Reactor模型本身与具体事件处理逻辑无关,具有很高的复用性

核心组件

1.Bootstrap 一个Netty应用通常由一个Bootstrap开始,它主要作用是配置整个Netty程序,串联起各个组件。

Handler,为了支持各种协议和处理数据的方式,便诞生了Handler组件。Handler主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等。

2.ChannelInboundHandler 一个最常用的Handler。这个Handler的作用就是处理接收到数据时的事件,也就是说,我们的业务逻辑一般就是写在这个Handler里面的,ChannelInboundHandler就是用来处理我们的核心业务逻辑。

3.ChannelInitializer 当一个链接建立时,我们需要知道怎么来接收或者发送数据,当然,我们有各种各样的Handler实现来处理它,那么ChannelInitializer便是用来配置这些Handler,它会提供一个ChannelPipeline,并把Handler加入到ChannelPipeline。

4.ChannelPipeline 一个Netty应用基于ChannelPipeline机制,这种机制需要依赖于EventLoop和EventLoopGroup,因为它们三个都和事件或者事件处理相关。

EventLoops的目的是为Channel处理IO操作,一个EventLoop可以为多个Channel服务。

EventLoopGroup会包含多个EventLoop。

5.Channel 代表了一个Socket链接,或者其它和IO操作相关的组件,它和EventLoop一起用来参与IO处理。

6.Future 在Netty中所有的IO操作都是异步的,因此,你不能立刻得知消息是否被正确处理,但是我们可以过一会等它执行完成或者直接注册一个监听,具体的实现就是通过Future和ChannelFutures,他们可以注册一个监听,当操作执行成功或失败时监听会自动触发。

示例

通过一个简单的示例,首先了解怎么基于netty开发一个通信程序,包括服务的与客户端:

Server:

@Slf4j
public class Server {private EventLoopGroup boosGroup;private EventLoopGroup workGroup;public Server(int port){try {init(port);log.info("----- 服务启动成功 -----");} catch (InterruptedException e) {log.error("启动服务出错:{}", e.getCause());}}private void init(int port) throws InterruptedException {// 处理连接this.boosGroup = new NioEventLoopGroup();// 处理业务this.workGroup = new NioEventLoopGroup();ServerBootstrap bootstrap = new ServerBootstrap();// 绑定bootstrap.group(boosGroup, workGroup).channel(NioServerSocketChannel.class) //配置服务端.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000).option(ChannelOption.SO_BACKLOG, 1024).childOption(ChannelOption.TCP_NODELAY, true).childOption(ChannelOption.SO_RCVBUF, 1024).childOption(ChannelOption.SO_SNDBUF, 1024).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new ServerHandler());}});ChannelFuture channelFuture = bootstrap.bind(port).sync();channelFuture.channel().closeFuture().sync();}public void close(){this.boosGroup.shutdownGracefully();this.workGroup.shutdownGracefully();}}@Slf4j
class ServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {log.info(">>>>>>> server active");}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//1. 读取客户端的数据(缓存中去取并打印到控制台)ByteBuf buf = (ByteBuf) msg;byte[] request = new byte[buf.readableBytes()];buf.readBytes(request);String requestBody = new String(request, "utf-8");log.info(">>>>>>>>> receive message: {}", requestBody);//2. 返回响应数据ctx.writeAndFlush(Unpooled.copiedBuffer((requestBody+" too").getBytes()));}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {super.exceptionCaught(ctx, cause);}
}

Client:

@Slf4j
public class Client {private EventLoopGroup workGroup;private ChannelFuture channelFuture;public Client(int port){init(port);}private void init(int port){this.workGroup = new NioEventLoopGroup();Bootstrap bootstrap = new Bootstrap();bootstrap.group(workGroup).channel(NioSocketChannel.class).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000).option(ChannelOption.SO_RCVBUF, 1024).option(ChannelOption.SO_SNDBUF, 1024).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new ClientHandler());}});this.channelFuture = bootstrap.connect("127.0.0.1", port).syncUninterruptibly();}/**** @param message*/public void send(String message){this.channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer(message.getBytes()));}/****/public void close(){try {channelFuture.channel().closeFuture().sync();} catch (InterruptedException e) {throw new RuntimeException(e);}workGroup.shutdownGracefully();}
}@Slf4j
class ClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {log.info(">>>>>>> client active");}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {try {ByteBuf buf = (ByteBuf) msg;byte[] req = new byte[buf.readableBytes()];buf.readBytes(req);String body = new String(req, "utf-8");log.info(">>>>>>>>> receive message: {}", body);} finally {ReferenceCountUtil.release(msg);}}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {super.exceptionCaught(ctx, cause);}
}

测试:

 

public class StarterTests {static int port = 9011;@Testpublic void startServer(){Server server = new Server(9011);}@Testpublic void startClient(){Client client = new Client(port);client.send("Hello Netty!");while (true){}}}

生态

  • Dubbo

  • Spring Reactive

类似技术

Mina、Netty、Grizzly

其他

Proactor非阻塞异步网络模型

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

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

相关文章

小白如何快速入门?

入门 Web 安全、安卓安全、二进制安全、工控安全还是智能硬件安全等等&#xff0c;每个不同的领域要掌握的技能也不同。当然入门 Web 安全相对难度较低&#xff0c;也是很多人的首选。主要还是看自己的兴趣方向吧。 本文就以下几个问题来说明网络安全大致学习过程&#x1f447…

如何用Python写个网页爬取程序

如何用Python写个网页爬取程序 准备开发工具安装PythonPython安装pipPip安装爬取插件准备好网页地址代码实现 准备开发工具 额&#xff0c;作者用的是vscode。具体怎么安装自行百度哈&#xff0c;这个都不会建议就不要学爬取了。 不忍心藏着也&#xff0c;给你个方法吧 vsc…

Javascript的闭包,匿名函数,自动调用

这里写目录标题 验证文本框HTMLJavascript分析var引起的赋值错误最优的解决方案forEach(function(item){})最简单的方式&#xff0c;const/let 申明一个局部变量直接使用函数通过声明函数变量的方式定义函数申明匿名函数和自动调用函数的区别 在案例的基础上分析。 验证文本框 …

90后测试员:“入职阿里,这一次,我决定不跳槽了...”

所谓“舒适”生活 记得上一份工作是去年听从了朋友的意见&#xff0c;“你一定要找一份舒适的工作&#xff0c;这样你一天就有好多时间玩&#xff0c;好多时间干自己想干的事情&#xff0c;摸鱼真香&#xff01;” 在这份“教导”下&#xff0c;开始了我的找工作之旅&#xf…

内网穿透技术

文章目录 前言1. 安装JAVA2. MCSManager安装3.局域网访问MCSM4.创建我的世界服务器5.局域网联机测试6.安装cpolar内网穿透7. 配置公网访问地址8.远程联机测试9. 配置固定远程联机端口地址9.1 保留一个固定tcp地址9.2 配置固定公网TCP地址9.3 使用固定公网地址远程联机 转载自内…

【正点原子STM32连载】 第二十五章 TFT-LCD(MCU屏)实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十…

没有硬件资源?免费使用Colab搭建你自己的Stable Diffiusion在线模型!保姆级教程...

部署 Stable Diffusion 需要一定的硬件资源&#xff0c;具体取决于要处理的图像大小和处理速度等因素。一般来说&#xff0c;至少需要一台具有较高计算能力的服务器&#xff0c;而对 GPU 的高要求就限制了我们学习和使用SD来生成我们想要的图像。 GPU是深度学习开发的重要硬件条…

chatgpt赋能python:Python列表分割与排序:完美解决数据处理问题

Python列表分割与排序&#xff1a;完美解决数据处理问题 在Python的开发实践中&#xff0c;数据处理是一项必不可少的操作。列表&#xff08;list&#xff09;是Python语言中常用的数据类型之一&#xff0c;列表中的元素可以是任意类型。列表的分割和排序是Python中常见的操作…

数字孪生:数字世界与现实世界的交汇

数字孪生是一种崭新的技术,指将现实世界中的物理实体、系统或过程通过数字化技术在虚拟数字世界中建立起虚拟模型。数字孪生可以帮助人们以更小的成本地理解和预测现实世界中的物理实体、系统或过程的行为和性能,从而提高生产效率、降低成本、减少风险等。 如今数字孪生技术…

【CSS3系列】第三章 · CSS3新增边框和文本属性

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

【Python 文本分析】零基础也能轻松掌握的学习路线与参考资料

Python 常用的文本分析工具有很多&#xff0c;如 Natural Language Toolkit (NLTK)、TextBlob、spaCy、Jieba等。本文将分别介绍这些工具及其对应的学习路线、参考资料和优秀实践。 Natural Language Toolkit (NLTK) Natural Language Toolkit (NLTK) 是 Python 中文本分析研…

如何申请免费ChatGPT 2500刀初创金

近日OpenAI 推出了OpenAI for Startups项目&#xff0c;那么什么是Startups项目呢&#xff1a; 它是由全球知名的人工智能研究公司 OpenAI 推出的一个开放式的创业计划&#xff0c;旨在为初创公司提供一种新的激励机制和技术推广方式。 也就是说我们可以用自己账号申请&#x…

记一次Java生成SQL脚本文件换行格式为window/unix的笔记

今天在做一个SQL脚本文件生成需求&#xff0c;其中&#xff0c;需要设置&#xff1a; 文件编码为&#xff1a;UTF-8文件换行格式为&#xff1a;UNIX UTF-8这个好说&#xff0c;因为java代码可以指定文件编码&#xff0c;如&#xff1a; 但是Unix换行格式就很神奇了&#xff0…

快手三面全过了,却因为背调时leader手机号造假,导致offer作废了!

这是一个悲伤的故事&#xff1a; 快手本地三面全过了&#xff0c;但因为背调时leader手机号造假&#xff0c;导致offer作废了。 楼主感叹&#xff1a;大家背调填写信息时&#xff0c;一定要慎重再慎重&#xff0c;不要重复他的悲剧&#xff01; 网友愤慨&#xff0c;照这么说&a…

OSPF最优路径选择

路由比较 1、内部区域>区域间路由>NSSA1>Nssa2 2、如果只有Ex1、Ex2或者Nssa1、nNssa2开销类型。则Ex1>Ex2或者Nssa1>Nssa2 3、如果Ex1、Nssa1,Ex2和Nssa2,Ex1和Nssa1优于Ex2和Nssa2 4、如果外部开销加上内部开销,Ex1和Nssa1一样,则Ex1和Nssa1相同负载分担 5、如果外…

京东工作8年,肝到T8就剩这份心得了,已助朋友拿到10个Offer

在京东工作了8年&#xff0c;工作压力大&#xff0c;节奏快&#xff0c;但是从技术上确实得到了成长&#xff0c;尤其是当你维护与大促相关的系统的时候&#xff0c;熬到T7也费了不少心思&#xff0c;小编也是个爱学习的人&#xff0c;把这几年的工作经验整理成了一份完整的笔记…

【TreeSet集合】比较器排序Comparator的使用

比较器排序Comparator的使用 存储学生对象并遍历&#xff0c;创建TreeSet集合使用带参构造方法 要求&#xff1a;按照年龄从小到大排序&#xff0c;年龄相同时&#xff0c;按照姓名的字母顺序排序 创建学生类&#xff1a; package com.gather.set.treeset; public class Stude…

C语言——分段函数求值

一、题目描述 二、题目分析 本题是简单的分段函数的求解&#xff0c;应学会合理的运用for\if\swich函数解答问题。 三、代码实现 //for语句解题#include <stdio.h> int main() {int x,y;scanf("%d",&x);if(x<1){yx;}else if(1<x && x<…

win10微软Edge浏览器通过WeTab新标签页免费无限制使用ChatGPT的方法,操作简单,使用方便

目录 一、使用效果 二、注册使用教程 1.打开Edge浏览器扩展 2.选择Edge浏览器外接程序 3.搜索WeTab 4.进入管理扩展 5.启用扩展 ​编辑 6.进入WeTab新标签页 7.打开Chat AI 8.注册 9.使用 ChatGPT是OpenAI推出的人工智能语言模型&#xff0c;能够通过理解和学习人类…

不要再重复造轮子了,这几款开源工具类库贼好使

在实际项目开发中&#xff0c;从稳定性和效率的角度考虑&#xff0c;重复造轮子是不被提倡的。但是&#xff0c;自己在学习过程中造轮子绝对是对自己百利而无一害的&#xff0c;造轮子是一种特别能够提高自己系统编程能力的手段。 基于 SpringBoot Vue uni-app 实现的全套电商…