Spring架构篇--2.7 远程通信基础--使用Netty

news2024/12/23 8:15:08

前言:Netty 作为Nio 模型的实现,相较于Selector ,进一步将api进行封装,使用更加的简单;在平常的开发中会发现许多组件的底层通信都使用了Netty,所以就非常有必要对Netty 的使用以及其工作原理进行了解了。

1 Netty介绍:

Netty是一个NIO基于事件驱动的客户端服务器框架,可以快速轻松地开发网络应用程序,例如协议服务器和客户端。它极大地简化和简化了网络编程,如TCP和UDP套接字服务器开发。
它是一个高性能、异步事件驱动的网络编程框架,它基于Java NIO(New I/O)开发,提供了一种简单易用的API,使得开发者能够轻松地构建高性能、可扩展的网络应用程序。Netty的设计目标是提供一个可嵌入、高性能、灵活、易于使用的网络编程框架,支持多种传输协议,如TCP、UDP、HTTP、WebSocket等,并且提供了丰富的功能,如SSL/TLS支持、压缩、编解码、流量控制、负载均衡、连接管理等。
Netty的核心组件包括:Channel、EventLoop、ChannelFuture、ChannelHandler和Bootstrap等。其中,Channel是网络通信的载体,EventLoop是异步事件驱动的核心,ChannelFuture是异步操作的结果,ChannelHandler是处理网络事件的组件,Bootstrap则是启动Netty应用程序的入口点。
Netty的优点在于其高性能、可扩展性和灵活性。它采用了异步非阻塞的IO模型,能够处理大量并发连接,同时提供了丰富的功能和扩展性,可以通过自定义ChannelHandler来实现各种业务逻辑。此外,Netty具有良好的文档和社区支持,能够在开发过程中提供及时的帮助和支持。

2 netty 使用:

2.1 服务端:
1)netty 服务端:

package org.lgx.bluegrass.bluegrasscoree.netty.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.lgx.bluegrass.bluegrasscoree.netty.hadler.DiscardServerHandler;

/**
 * @Description TODO
 * @Date 2023/3/13 16:49
 * @Author lgx
 * @Version 1.0
 */
public class DiscardServer {

    private int port;

    public DiscardServer(int port) {
        this.port = port;
    }

    public static void main(String[] args) {
        new DiscardServer(8080).run();
    }

    private void run() {
    	// 总线程
        NioEventLoopGroup boss = new NioEventLoopGroup();
        // 工作线程
        NioEventLoopGroup worker = new NioEventLoopGroup();
        try {
        	//netty 服务端
            ServerBootstrap server = new ServerBootstrap();
             // 服务端参数
            server.group(boss,worker)
            		  // nio socket 处理
                    .channel(NioServerSocketChannel.class)
                     // 子线程事件回调处理
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new DiscardServerHandler());
                        }
                    })
                     // 主线程最大的分配线程数
                    .option(ChannelOption.SO_BACKLOG,128)
                      // 保持长连接
                    .childOption(ChannelOption.SO_KEEPALIVE,true);
             // 启动服务
            ChannelFuture f = server.bind(this.port).sync();
             System.out.println("8080服务已启动");
              // 关闭通道
            f.channel().closeFuture().sync();
              
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
        	// 线程关闭
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}

2) 事件处理 Handler:

package org.lgx.bluegrass.bluegrasscoree.netty.hadler;


import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

/**
 * @Description TODO
 * @Date 2023/3/13 16:38
 * @Author lgx
 * @Version 1.0
 */
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // super.channelRead(ctx, msg);
        // ((ByteBuf) msg).release();
        // ByteBuf in = (ByteBuf) msg;
        // try {
        //     while (in.isReadable()) { // (1)
        //         System.out.print((char) in.readByte());
        //         System.out.flush();
        //     }
        // }finally {
        //     ReferenceCountUtil.release(msg);
        // }
        ctx.write(msg); // (1)
        ctx.flush(); // (2)
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // super.exceptionCaught(ctx, cause);
        cause.printStackTrace();
        ctx.close();
    }
}

2.2 客户端:
1) 客户端连接

package org.lgx.bluegrass.bluegrasscoree.netty.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.lgx.bluegrass.bluegrasscoree.netty.hadler.ClientHandler;


/**
 * @Description TODO
 * @Date 2023/3/13 17:17
 * @Author lgx
 * @Version 1.0
 */
public class Client {
    private int port;

    public Client(int port) {
        this.port = port;
    }

    public static void main(String[] args) {
        new Client(8080).run();
    }

    private void run() {
    	// 工作线程
        NioEventLoopGroup worker = new NioEventLoopGroup();
        try {
        	// netty 客户端
            Bootstrap b = new Bootstrap();
            b.group(worker)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new ClientHandler());
                        }
                    });

            ChannelFuture f = b.connect("localhost",this.port).sync();
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            worker.shutdownGracefully();

        }
    }
}

  1. 事件处理Handler:
package org.lgx.bluegrass.bluegrasscoree.netty.hadler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

/**
 * @Description TODO
 * @Date 2023/3/13 17:21
 * @Author lgx
 * @Version 1.0
 */
public class ClientHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // super.channelRead(ctx, msg);
        ByteBuf in = (ByteBuf) msg;
        try {
            while (in.isReadable()) { // (1)
                System.out.print((char) in.readByte());
                System.out.flush();
            }
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // super.exceptionCaught(ctx, cause);
        cause.printStackTrace();
        ctx.close();
    }
}

Netty 中对于其 配置的参数如ChannelOption.SO_KEEPALIVE,ChannelOption.SO_BACKLOG等,在后续对ServerBootstrap 进行解读时在进行探究;

3 netty 特点:

3.1 netty 解决Selector的使用不便:
Nio 模式,实现多路复用,一个线程监听,采用事件回调机制,处理多个客户端的数据传输;虽然使用selector 可以实现多路复用,但是需要自己进行注册的维护,轮训,对管道数据的读写也比较麻烦;

3.2 netty 的api流程简单:
服务端:
在这里插入图片描述

客户端:
在这里插入图片描述
3.3 零拷贝:netty 在接收到数据后,可以直接将数据在系统空间进行处理,并且通过系统空间写会到管道中;
1、接收和发送ByteBuffer使用堆外直接内存进行Socket读写;
2、提供了组合Buffer对象,可以聚合多个ByteBuffer对象;
3、transferTo0直接将文件缓冲区的数据发送到目标Channel;

3.4 提前分配后数据要存放的内存空间,并且可以反复利用;
3.5 责任链串行设计(连过长一定程度影响性能)
在这里插入图片描述
3.6 Netty 支持多语言,多协议;高性能序列化;

4 参考:
1 Netty 4.x 版用户指南;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

改进YOLOv8 | 主干网络篇 | YOLOv8 更换骨干网络之 GhostNet | 从廉价操作中获取更多特征

论文地址:https://arxiv.org/abs/1911.11907 代码地址:https://github.com/huawei-noah/ghostnet 由于内存和计算资源有限,在嵌入式设备上部署卷积神经网络(CNN)很困难。特征图中的冗余是那些成功的神经网络的重要特征,但在神经架构设计中很少研究。本文提出了一种新的G…

JVM学习笔记二

1. JVM内存参数 要求 熟悉常见的 JVM 参数&#xff0c;尤其和大小相关的 堆内存&#xff0c;按大小设置 解释&#xff1a; -Xms 最小堆内存&#xff08;包括新生代和老年代&#xff09; -Xmx 最大堆内存&#xff08;包括新生代和老年代&#xff09; 通常建议将 -Xms 与 -…

【复杂网络建模】——基于微博数据的影响力最大化算法(PageRank)

&#x1f935;‍♂️ 个人主页&#xff1a;Lingxw_w的个人主页 ✍&#x1f3fb;作者简介&#xff1a;计算机科学与技术研究生在读 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4a…

pdf怎么转换成word?一分钟解决

PDF文件是一种广泛使用的电子文档格式&#xff0c;因为它们可以保留文档的完整性和格式。但是&#xff0c;有时候我们需要对PDF文件进行编辑和修改&#xff0c;这时候就需要将其转换成Word格式。在本篇文章中&#xff0c;我们将讨论PDF转换Word的方法及其优缺点。 有很多在线工…

易点易动打通财务系统,打破数据孤岛,实现固定资产的账实一致

固定资产管理涉及资产的采购、验收、账务处理、折旧管理等全流程,同时也牵涉到财务系统和资产系统两大信息孤岛。这两个系统之间数据不互通,导致资产的账实信息无法同步,无法真正实现资产管理的账实一致。 固定资产系统作为固定资产管理的业务系统,负责资产的采购申请、验收入…

IDEA2023.1配置Git

一、前言 在使用新设备整理git项目时&#xff0c;报了以下问题&#xff0c;在整理项目的同时&#xff0c;做下记录。 二、下载git 2.1.官网下载git 官网下载地址&#xff1a; git官网&#xff0c;如下图所示&#xff1a; 如果选方法二&#xff0c; 接下来会让选择系统&#…

Halcon得出三角形内切圆

Halcon得出三角形内切圆 news2023/5/27 7:14: 目录 一、得出三角形的三个角点二、用类似尺规作图法得出三角形圆心 1、以三角形三角点画出圆形轮廓2、求出三角形轮廓与圆形轮廓之间的交点3、获得角平分线&#xff0c;三边角平分线交点为圆心三、求出圆心到边最短距离即半径 …

接口自动化测试框架-Requests库简介及安装

接口测试工具的不足点&#xff1a; 测试数据不可控制 无法测试加密接口 扩展能力不足 Ps&#xff1a;对上述问题&#xff0c;Robot Framework都能满足&#xff0c;但是其脚本的可读性差是它最大弱点&#xff0c;如果需要为它开发系统关键字&#xff0c;还不如直接写Python程…

LiangGaRy-学习笔记-Day19

1、回顾知识 1.1、文件系统说明 xfs与ext4文件系统 CentOS7以上&#xff1a;默认的就是XFS文件系统 xfs 使用的就是restore、dump等工具 CentOS6默认的就是ext4文件系统 extundelete工具就是用于ext4系统 1.2、回顾Linux文件系统 Linux文件系统是由三个部分组成 inode文…

01 云原生生态系统解读

云计算的技术革命 互联网时代的历程 云计算到底是什么 云计算历程 云平台的优缺点 优势 稳定性&#xff1a;云平台大量资源&#xff0c;分布式集群部署&#xff0c;保障服务永不宕机&#xff0c;几个9弹性扩展&#xff1a;按需索取&#xff0c;一键秒级开通需要的资源安全性&…

500道网络安全/WEB安全面试题合集!附答案解析

前言 随着国家政策的扶持&#xff0c;网络安全行业也越来越为大众所熟知&#xff0c;想要进入到网络安全行业的人也越来越多。 为了拿到心仪的 Offer 之外&#xff0c;除了学好网络安全知识以外&#xff0c;还要应对好企业的面试。 作为一个安全老鸟&#xff0c;工作这么多年…

vue3+element-plus的后台管理系统模板 和 vue3+ant-design-vue的后台管理系统模板

项目介绍 规范&#xff1a;后台系统模板&#xff0c;按照企业级别的规范搭建的。 权限控制&#xff1a;通过后端返回的路由表&#xff08;这个路由表是由前端这边在系统配好的然后存储在后端的&#xff09;来动态渲染菜单和注册路由&#xff0c;同时也根据页面内的接口权限对页…

能用excel批量提取网页内特定数据吗?

这个需求其实是采集数据&#xff0c;用第三方软件比较合适&#xff0c;当然&#xff0c;用excel也可以批量提取网页内特定文字。请按照以下步骤操作&#xff1a; 1. 打开要提取的网页&#xff0c;并选中要提取的文字&#xff0c;例如一个表格里的数据。 2. 复制选中的文字。 …

你的 ChatGPT 使用姿势是错的!告诉你 4 个使用 ChatGPT 的小技巧

大部分人使用 ChatGPT 的方式都是错的&#xff0c;比如&#xff1a; 没有在提问时提供案例。忽略了可以通过设置 ChatGPT 的角色来控制它的行为。没有提供过多有效信息&#xff0c;而是让 ChatGPT 猜猜猜。 之所以会犯这些错误&#xff0c;是因为我们使用 ChatGPT 时还停留在…

HarmonyOS3 Stage模型介绍

Stage模型是HarmonyOS 3.1 Develper Preview&#xff08;API 9&#xff09;版本开始新增的模型&#xff0c;也是目前HarmonyOS主推且会长期演进的模型。在该模型中&#xff0c;由于提供了AbilityStage、WindowStage等类作为应用组件和Window窗口的“舞台”&#xff0c;因此称这…

一款红队批量脆弱点搜集工具

功能 指纹识别:调用“三米前有香蕉皮“前辈工具&#xff0c;他的工具比finger好用 寻找资产中404&#xff0c;403&#xff0c;以及网页中存在的其他薄弱点&#xff0c;以及需要特定路径访问的资产 后续会把nuclei加进来 目前只有windows可以用 使用 第一次使用脚本请运行p…

Neo4j安装配置教程

目录结构 前言Neoj4简介安装JDKNeo4j安装步骤Neo4j下载解压Neo4j压缩包配置环境变量启动Neo4j执行命令报错&#xff0c;报错信息如下&#xff1a; 启动Neo4j&#xff0c;再次测试浏览器访问Neo4j参考链接 前言 安装所需配件网盘一键下载。以下描述中&#xff0c;官网下载均有描…

1、2、3类LSA解析

拓扑 需求 &#xff08;1&#xff09;企业核心机房&#xff0c;连接不同楼宇&#xff0c;实现不同楼宇互通&#xff1b; &#xff08;2&#xff09;企业核心机房设置为OSPF骨干区域&#xff1b; &#xff08;3&#xff09;其他办公楼宇为非骨干区域&#xff0c;通过路由器与…

Vue+SpringBoot打造超市商品管理系统(附源码文档)

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;Java全栈软件工程师一枚&#xff0c;来自浙江宁波&#xff0c;负责开发管理公司OA项目&#xff0c;专注软件前后端开发、系统定制、远程技术指导。CSDN学院、蓝桥云课认证讲师&#xff0c;全栈领域优质创作者。 目录 一…

C++学习之旅 - 指针

文章目录 指针的基本概念指针的定义与使用指针占用的内存空间空指针野指针cont修饰指针指针&数组访问数组中第一个元素(访问&指针)如何访问数组中的第二个字节 指针和函数 指针的基本概念 指针的作用: 可以通过指针间接访问内存 内存编号是从0开始记录的&#xff0c;一…