当前位置:首页 > 实用技巧 >

如何使用netty(netty调用方法)

来源:原点资讯(www.yd166.com)时间:2024-02-21 13:20:02作者:YD166手机阅读>>

前言

Netty 祭天,法力无边。

哈哈哈 , Netty 这组件,哪怕你从来没主动用过,但是它无时无刻都在你身边。可以说,阿里系或者一些高级开源工具在实现 Client 和 Server 的时候都选择使用了 Netty。

第一步 : 理解场景

首先我们要理解 Netty 到底能做什么?

Netty 是一个基于 JAVA NIO 类库的异步通信框架,用于创建异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性的网络客户端和服务器端.

那么很明显了,Netty 是为了通信的 ,其优势就是性能好,不会阻塞。这两点就足够大多数框架用它来做通信。

那么问题来了,系统间的通信用来做什么?

我们其实时时刻刻都在用 Netty ,比较常见的就是开源框架,包括 :Nacos ,Seata ,Sentinel

相对而言这些访问量都不会太高,更高并发的使用就包括 : Dubbo ,gRPC , RokcetMQ

而从业务角度讲主要2个方向 :通信 (IM 即时通讯) 和 数据传递 (消息发送工具)

第二步 : 了解组件2.1 组件的层级展示
  • 单个组件:
  • Channel : 一个网络连接的抽象表示 , 可以用于读取或者写入数据
  • ChannelPipeline :一个链路,channel 接收的数据会通过 ChannelPipeline 进行传递
  • ChannelHandler :一个处理器,在一个通道中有多个 Handler 用于处理事件和数据,执行各种特定的任务和逻辑
  • EventLoop : 一个线程,用于处理事件和执行任务,可以处理 Channel 上面所有的物理操作
  • 容器类型:
  • Bootstrap & ServerBootstrap : 用于创建和配置服务器,从而启动服务器入口
  • ChannelHandlerContext :用于绑定 ChannelHandler 和 ChannelPipeline

问题一 : Channel 和 EventLoop 的关系?

  • 一个EventLoopGroup 包含一个或者多个EventLoop;
  • 一个EventLoop 在它的生命周期内只和一个Thread 绑定;
  • 所有由EventLoop 处理的I/O 事件都将在它专有的Thread 上被处理;
  • 一个Channel 在它的生命周期内只注册于一个EventLoop,所有的事件处理和任务都会在这个 EventLoop 上处理
  • 一个EventLoop 可能会被分配给一个或多个Channel。
  • 多个 EventLoop 可以存在一个 EventLoopGroup 里面

问题二 : EventLoopGroup 有什么作用?

  • EventLoopGroup 用于管理 EventLoop ,包括将 EentLoop 分配给 Channel ,包括 EventLoop 的协同
2.2 关系图

Channel 和 EventLoop 的关系

如何使用netty,netty调用方法(1)

Channel 和 Handler 的关系

如何使用netty,netty调用方法(2)

第三步 : 熟悉用法3.1 一个最简单的 Netty 案例

首先需要我们理清楚思路,从无到有搭建 Server 和 Client 需要哪些步骤 :

  • 首先要准备好 Server 端和 Client 端 ,他们要监听同一个端口
  • 准备好 Handler 类用于对数据进行处理
  • 双端进行通信,然后互相发送消息
  • 完成后记得 Close ,和 IO 一样,都需要关闭流
3.2 搭建好 Server 端服务器
  • 创建好 ServerBootstrap 对象用于开始搭建整个服务器
  • 为 ServerBootstrap 配置好 eventLoopGroup , 这里的 Group 有2个 : BossGroup : 用于处理连接请求 ,本身包含多个 EventLoop ,用于创建 Channel 转发给 WorkerGroup workerGroup : 处理已建立的连接 ,同样包含自己的 EventLoop
  • 配置服务器处理的 Channel 连接的类型 , 包括 NIO 类型 , EPOLL 类型等
  • 配置整个处理流程的 ChannelHandler ,用于特定的处理
  • 为这个 Server 端 bind() 一个端口 , 同时阻塞等待绑定完成

基于这个流程,整个 Server 端的创建可以分为2个步骤 :

// 第一步 :准备后续处理业务的 Handler public class NettyServerHandler extends ChannelInboundHandlerAdapter { /** * 客户端连接会触发 */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("S2 : 服务端建立连接,触发 Active ....."); } /** * 客户端发消息会触发 */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("服务器收到消息: " msg.toString()); // 接收到消息后,返回一条消息给客户端 ctx.write(msg "World!"); ctx.flush(); } /** * 发生异常触发 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } // 第二步 :创建 Initializer 用于初始化 Channel public class ServerChannelInitializer extends ChannelInitializer<socketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { //添加编解码 socketChannel.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8)); socketChannel.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8)); // 此处将 Handler 绑定到 ChannelPipeline 中 socketChannel.pipeline().addLast(new NettyServerHandler()); } } // 第三步 : 准备好 Netty 客户端 public class NettyServer extends Thread { public void run() { // S1 : 准备 Boss 管理线程组 和 Worker 工作线程组 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workGroup = new NioEventLoopGroup(200); // S2 : 绑定 Group , 绑定渠道 , 绑定 Handler ServerBootstrap bootstrap = new ServerBootstrap() .group(bossGroup, workGroup) .channel(NioServerSocketChannel.class) .childHandler(new ServerChannelInitializer()); try { InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 8090); // S3 : 绑定对应端口和地址,用于后续阻塞监听 ChannelFuture future = bootstrap.bind(socketAddress).sync(); System.out.println("S1 : 服务端构建完成 ....."); future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { //关闭主线程组 bossGroup.shutdownGracefully(); //关闭工作线程组 workGroup.shutdownGracefully(); } } }3.3 搭建好客户端

  • 不同于 Server ,Client 端只需要一个 EventLoopGroup
  • 同样的,创建 Bootstrap ,绑定 Group / channel / handler
  • 通过 writeAndFlush 发送消息

// 第一步 :准备客户端的 Handler 接收消息 public class NettyClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("S2 : 客户端建立连接,触发 Active ....."); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("客户端收到消息: " msg.toString()); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } // 第二步 :创建 Initializer 用于初始化 Channel public class NettyClientInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast("decoder", new StringDecoder()); socketChannel.pipeline().addLast("encoder", new StringEncoder()); // 此处将 Handler 绑定到 ChannelPipeline 中 socketChannel.pipeline().addLast(new NettyClientHandler()); } } // 第三步 : 准备启动类 public class NettyClient extends Thread { public void run() { EventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap() .group(group) .channel(NioSocketChannel.class) .handler(new NettyClientInitializer()); try { ChannelFuture future = bootstrap.connect("127.0.0.1", 8090).sync(); System.out.println("S2 : 客户端构建完成 ....."); for (int i = 0; i < 10; i ) { String message = "第" i "条消息 , " "Hello "; future.channel().writeAndFlush(message); Thread.sleep(1000); // 暂停一秒钟 } future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } }3.4 发起请求

在这个环节里面通过2个线程模拟消息的发送和接收 :

public class DemoService { public static void main(String[] args) throws InterruptedException { System.out.println("Start :开始整个 Netty 搭建流程"); // S1 : 分别开2个线程模拟 Server 和 Client 的开启 NettyServer server = new NettyServer(); server.start(); NettyClient client = new NettyClient(); client.start(); } }

如何使用netty,netty调用方法(3)

可以看到流程很清晰了,先创建双端,然后双端建立连接,随后发生交互

四. API 高级用法4.1 Bootstrap 包含哪些方法 @ ChatGPT
  • group :设置用于处理事件循环(EventLoop)的 EventLoopGroup
  • channel :指定 Channel 的类型 (NioSocketChannel / NioServerSocketChannel)
  • handler : 在初始化过程中添加一个 ChannelHandler
  • childHandler : 用于 ServerBootstrap,在连接被接受后,为新注册的 Channel 设置 ChannelHandler
  • localAddress : 指定本地端口或地址,用于连接或绑定
  • remoteAddress : 指定远程服务器的地址
  • connect : 用于客户端连接指定远程地址
  • bind : 用于服务器绑定到指定的本地地址
总结

东西很简单,因为我在开发过程中对 Netty 的底层代码也只是轻度使用,大部分都是基于外层封装的组件在使用。

这一篇主要是为了学习,所以会写不深。后续会陆陆续续从高级用法 高并发用法 源码 等多个角度深入,欢迎关注。

相关文档 :

需要的老铁后台私信【笔记】获取Netty大纲及笔记!

,

栏目热文

netty框架教学(netty框架工作原理)

netty框架教学(netty框架工作原理)

一 什么是 Netty? 能做什么?netty 是一个致力于创建高性能网络应用程序的成熟的 IO 框架。相比较与直接使用...

2024-02-21 13:48:53查看全文 >>

为什么要学习netty(netty有必要学吗)

为什么要学习netty(netty有必要学吗)

2021年了,终于开始系统性总结Netty相关的东西了。这会是Netty系列的第一篇,我想先聊聊 “为什么要学习Nett...

2024-02-21 13:41:47查看全文 >>

怎么集成netty(netty操作原理)

怎么集成netty(netty操作原理)

Gateway和Netty都有盲区的感觉;一、Netty简介Netty是一个异步的,事件驱动的网络应用框架,用以快速开发...

2024-02-21 13:37:42查看全文 >>

netty 文件分发(netty详细步骤)

netty 文件分发(netty详细步骤)

一、异步非阻塞通信1.1 传统BIO1.2 非阻塞NIO1.3 拓展:AIO1.4 I/O多路复用机制1.4.1 sel...

2024-02-21 13:52:34查看全文 >>

netty文件传输(netty传输二进制文件)

netty文件传输(netty传输二进制文件)

本系列Netty源码解析文章基于 4.1.56.Final版本主从Reactor组完整结构.png在?《Netty如何高...

2024-02-21 13:35:28查看全文 >>

奥迪哪些车型使用贯穿尾灯(奥迪贯穿式尾灯的有哪些车型)

奥迪哪些车型使用贯穿尾灯(奥迪贯穿式尾灯的有哪些车型)

说到豪华小型SUV,大家最先想到的是谁呢?奥迪Q3作为奥迪旗下的畅销车,与宝马X1、奔驰GLA等车型同为豪华小型SUV代...

2024-02-21 13:20:56查看全文 >>

奥迪贯穿尾灯哪几款车有(奥迪贯穿尾灯哪几款车有的)

奥迪贯穿尾灯哪几款车有(奥迪贯穿尾灯哪几款车有的)

日前,外媒曝光了一组全新奥迪S5 Sportback的谍照,这似乎是新车的谍照第一次被曝光,它是下一代奥迪A5的性能版,...

2024-02-21 13:49:40查看全文 >>

奥迪哪几款有贯穿式尾灯(奥迪哪些车型使用贯穿尾灯)

奥迪哪几款有贯穿式尾灯(奥迪哪些车型使用贯穿尾灯)

随着全新奥迪Q3测试谍照频繁曝光,很快有外媒根据相关信息绘制出了实车渲染图。按照规划,全新奥迪Q3将在2024年首发亮相...

2024-02-21 13:23:29查看全文 >>

奥迪轿车贯穿尾灯是哪款(奥迪哪款轿车的尾灯是贯穿的)

奥迪轿车贯穿尾灯是哪款(奥迪哪款轿车的尾灯是贯穿的)

提到贯穿尾灯,想必你一定不会感到陌生,这可是现在最红的设计语言,不仅造型好看,辨识度也相当高,当它点亮的那一刻,保管从老...

2024-02-21 13:54:25查看全文 >>

奥迪哪一款是贯穿尾灯(奥迪哪些车自带贯穿式尾灯)

奥迪哪一款是贯穿尾灯(奥迪哪些车自带贯穿式尾灯)

文:懂车帝原创 张凯[懂车帝原创 产品] 日前,新款奥迪Q8家族正式发布。新车针对外观和内饰设计细节进行了一定幅度的调整...

2024-02-21 13:13:21查看全文 >>

文档排行