初识Netty:背景、现状与趋势

    技术2026-08-17  18

    文章目录

    Netty概述Netty之Hello World不直接使用JDK NIO选择Netty的原因Netty发展史

    Netty概述

    Netty由Trustin Lee (韩国,Line公司) 2004年开发。

    Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.

    本质:网络应用程序框架 实现:异步、事件驱动 特性:高性能、可维护、快速开发 用途:开发服务器和客户端

    Netty的结构图: 其结构主要分三个部分:

    最底层的核心层:零拷贝的功能丰富的Byte Buffer、通用的通信层API、可扩展的事件模型支持的传输层服务:TCP-Socket&UDP-Datagram、HTTP Tunnel、In-VM Pipe支持的协议:HTTP(应用层协议)、WebSocket、Protobuf( 编解码方式)等

    Netty之Hello World

    Netty的Hello world代码相对来说要复杂一些,但客户端和服务端都包含了NioEventLoopGroup,Pipeline等相同的脚手架代码。

    在pom中引入netty的依赖

    <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.50.Final</version> </dependency>

    创建Netty的Hello World。下面的示例程序使用netty的构建了一个基本的客户端-服务端的模型,由NioEventLoopGroup、ServerBootstrap、ChannelInitializer等组件构成。

    服务端代码:

    /** 构建netty Server端启动的bootstrap. */ public class EchoServer { public static void main(String[] args) throws InterruptedException { // 接收客户端连接 EventLoopGroup bossGroup = new NioEventLoopGroup(); // 处理客户端连接 EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new EchoServerInitializer()); ChannelFuture channelFuture = serverBootstrap.bind(8030).sync(); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } } /** 初始化server端的socket channel pipiline。 */ public class EchoServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast(new LoggingHandler(LogLevel.INFO)); pipeline.addLast(new EchoServerHandler()); } } /** Server handler */ public class EchoServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // 接收到客户端消息后,将消息原样输出给客户端 ctx.write(msg); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }

    客户端代码

    public class EchoClient { public static void main(String[] args) throws InterruptedException { // configure the client. EventLoopGroup group = new NioEventLoopGroup(); try{ Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY,true) .handler(new EchoClientInitializer()); // start the client. ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",8030).sync(); // wait util the connection is closed. channelFuture.channel().closeFuture().sync(); } finally { // shut down the event loop to terminate all threads. group.shutdownGracefully(); } } } public class EchoClientInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast(new LoggingHandler(LogLevel.INFO)); pipeline.addLast(new EchoClientHandler()); } } public class EchoClientHandler extends ChannelInboundHandlerAdapter { private final ByteBuf firstMessage; public EchoClientHandler() { firstMessage = Unpooled.wrappedBuffer("I am echo message".getBytes()); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.writeAndFlush(firstMessage); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ctx.write(msg); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { TimeUnit.SECONDS.sleep(3); ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }

    不直接使用JDK NIO

    Netty相比于Java Nio

    做的更多:

    支持常用应用层协议(如http),无需再过多考虑编解码的实现;解决TCP层传输问题:粘包、半包现象支持流量整形(流量控制,黑白名单等)完善的断连、Idle等异常处理

    做的更好:

    规避JDK NIO bug epoll bug:异常唤醒空转导致CPU 100%IP_TOS参数(IP包的优先级和QoS选项)使用时抛出异常 API更友好更强大 JDK的NIO一些API不够友好,功能薄弱。如ByteBuffer -> Netty’s ByteBuf除NIO外,也提供了其它一些增强:ThreadLocal -> Netty’s FastThreadLocal 隔离变化、屏蔽细节 隔离JDK NIO的实现变化:nio -> nio2(aio) -> …屏蔽JDK NIO的实现细节

    选择Netty的原因

    业界流行的网络通信框架,但是Java网络编程,只选择Netty。

    Apache Mina netty对MINA进行重构,并解决了已知问题Sun Grizzly 用的少、文档少、更新少Apple Swift NIO、ACE 其它语言,不考虑Cindy 生命周期不长Tomcat、Jetty 还没有独立出来

    Netty发展史

    从归属组织上看发展

    JBoss 在4.0之前属于JBoss,在包命名管理上可以看出Netty 4.0之后在Netty社区进行管理

    从版本演变上看发展

    2004年6月Netty2发布 声称Java社区中第一个基于事件驱动的易用网络框架2008年10月Netty3发布2013年7月Netty4发布2013年12月发布5.0.0.Alpha12015年1月废弃5.0.0 复杂(使用ForkJoinPool) 没有证明有明显性能优势 维护不过来

    Netty社区 https://github.com/netty/netty

    分支

    4.1 master,支持Android(最优版本选择)4.0 相较于之前版本主要变更有:线程模型优化、包结构、命名(更新缓慢)

    一些典型项目

    数据库:Cassandra大数据处理:Spark、Hadoop消息队列:RocketMQ检索:Elasticsearch框架:gRPC、Apache Dubbo、Spring5分布式协调器:Zookeeper工具类:async-http-client其它参考:https://netty.io/wiki/adopters.html

    趋势

    更多流行协议的支持 目前已经支持dns、http、https、redis、xml等主流协议紧跟JDK新功能步伐更多易用、人性化功能IP地址黑白名单、流量整形等使用Netty的应用越来越多
    Processed: 0.011, SQL: 9