如何使用netty,netty调用方法

首页 > 实用技巧 > 作者:YD1662024-02-21 13:20:02

前言

Netty 祭天,法力无边。

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

第一步 : 理解场景

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

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

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

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

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

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

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

第二步 : 了解组件2.1 组件的层级展示

问题一 : Channel 和 EventLoop 的关系?

问题二 : EventLoopGroup 有什么作用?

2.2 关系图

Channel 和 EventLoop 的关系

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

Channel 和 Handler 的关系

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

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

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

3.2 搭建好 Server 端服务器

基于这个流程,整个 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 搭建好客户端

// 第一步 :准备客户端的 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总结

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

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

相关文档 :

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

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.