Netty(二)——Netty简介、核心组件及如何编写
创始人
2024-03-27 20:33:59
0

一、简介

Netty是一款用于创建高性能网络应用程序的高级框架。通俗地讲,其实就是远程通信框架,即rpc框架。正因为netty强大的性能,它也因此被用于很多流行框架或组件的底层通信机制。比如常见的Spring Cloud Gateway,Dubbo。它们的底层通信机制就是Netty。

由于JDK中用于操作nio的api太偏底层,使用这些底层api较为复杂。而Netty用较简单的抽象隐藏了底层实现的复杂性,封装了更为简单易用的api。

二、核心组件

1、Channel

        通道,作为NIO的三大组件之一。可参考 BIO/伪异步IO/NIO/AIO四种IO模型的演变 一文。

2、回调

        一个回调其实就是一个方法,一个指向已经被提供给另外一个方法的方法的引用。这使得后者可以在适当的时候调用前者。 Netty在内部使用回调来处理事件。

3、Future

        Future 提供了另一种在操作完成时通知应用程序的方式。这个对象可以看作是一个异步操作的结果的占位符;它将在未来的某个时刻完成,并提供对其结果的访问。

(笔者感觉这段描述十分到位,因为是异步,所以我们无法同步等待获取结果,而在操作线程池的时候,执行ExecutorService.submit()接口的返回值就是Future,之前笔者一直以为这个返回值还是阻塞等待获取到的。现在看到这段描述,如醍醐灌顶。)

        JDK的JUC下的Future,只允许手动检查对应的操作是否完成,或一直阻塞直到它完成,十分繁琐。因此Netty提供了自己的实现——ChannelFuture,用于在执行异步操作的时候使用。

4、事件和ChannelHandler

        Netty 使用不同的事件来通知我们状态的改变或者是操作的状态。这使得我们能够基于已经发生的事件来触发适当的动作。

三、编写Netty服务端和客户端

1、引入Netty的maven依赖

    io.nettynetty-all5.0.0.Alpha2

2、Netty服务端编写

所有的 Netty 服务器都需要以下两部分。

  • 至少一个 ChannelHandler——该组件实现了服务器对从客户端接收的数据的处理,即它的业务逻辑。
  • 引导——这是配置服务器的启动代码。至少,它会将服务器绑定到它要监听连接请求的端口上。

// 标示一个ChannelHandler可以被多个Channel安全地共享
@ChannelHandler.Sharable
public class EchoServerHandler extends ChannelHandlerAdapter {@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {// 打印异常栈跟踪cause.printStackTrace();// 关闭该Channelctx.close();}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf in = (ByteBuf) msg;System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8));// 将接收到的消息写给发送者,而不冲刷出战消息ctx.write(in);}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {// 将未决消息冲刷到远程节点,并且关闭该Channelctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);}
}
public class EchoServer {private final int port;public EchoServer(int port) {this.port = port;}public static void main(String[] args) throws Exception {if (args.length != -1) {System.err.println("Usage: " + EchoServer.class.getSimpleName() + " ");}// 设置端口值(如果端口参数的格式不正确,则抛出一个NumberFormatException)int port = Integer.parseInt(args[0]);new EchoServer(port).start();}public void start() throws Exception {final EchoServerHandler serverHandler = new EchoServerHandler();// 1.创建EventLoopGroupEventLoopGroup group = new NioEventLoopGroup();try {// 2.创建ServerBootstrapServerBootstrap b = new ServerBootstrap();b.group(group).channel(NioServerSocketChannel.class) // 3.指定所使用的NIO传输Channel.localAddress(new InetSocketAddress(port)) // 4.使用指定的端口设置套接字地址.childHandler(new ChannelInitializer() {  //5.添加一个EchoServerHandler到子Channel的ChannelPipelineprotected void initChannel(SocketChannel ch) throws Exception {// EchoServerHandler被标注为@Shareable,所以我们可以总是使用同样的实例ch.pipeline().addLast(serverHandler);}});ChannelFuture f = b.bind().sync(); // 6.异步地绑定服务器;调用sync()方法阻塞等待直到绑定完成f.channel().closeFuture().sync(); // 7.获取Channel的CloseFuture,并且阻塞当前线程直到它完成} finally {// 8.关闭EventLoopGroup,释放所有的资源group.shutdownGracefully().sync();}}
}

3、Netty客户端编写

 同服务端的编写类似,客户端也要通过 ChannelHandler 来实现其逻辑。只不过客户端一般会使用某个ChannelHandler的具体实现类。

@ChannelHandler.Sharable
public class EchoClientHandler extends SimpleChannelInboundHandler {@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {super.channelRead(ctx, msg);}protected void messageReceived(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {}
}

相关内容

热门资讯

中证A500ETF摩根(560... 8月22日,截止午间收盘,中证A500ETF摩根(560530)涨1.19%,报1.106元,成交额...
A500ETF易方达(1593... 8月22日,截止午间收盘,A500ETF易方达(159361)涨1.28%,报1.104元,成交额1...
何小鹏斥资约2.5亿港元增持小... 每经记者|孙磊    每经编辑|裴健如 8月21日晚间,小鹏汽车发布公告称,公司联...
中证500ETF基金(1593... 8月22日,截止午间收盘,中证500ETF基金(159337)涨0.94%,报1.509元,成交额2...
中证A500ETF华安(159... 8月22日,截止午间收盘,中证A500ETF华安(159359)涨1.15%,报1.139元,成交额...
科创AIETF(588790)... 8月22日,截止午间收盘,科创AIETF(588790)涨4.83%,报0.760元,成交额6.98...
创业板50ETF嘉实(1593... 8月22日,截止午间收盘,创业板50ETF嘉实(159373)涨2.61%,报1.296元,成交额1...
港股异动丨航空股大幅走低 中国... 港股航空股大幅下跌,其中,中国国航跌近7%表现最弱,中国东方航空跌近5%,中国南方航空跌超3%,美兰...
电网设备ETF(159326)... 8月22日,截止午间收盘,电网设备ETF(159326)跌0.25%,报1.198元,成交额409....
红利ETF国企(530880)... 8月22日,截止午间收盘,红利ETF国企(530880)跌0.67%,报1.034元,成交额29.0...