Netty基本介绍!
发表于更新于
中间件NettyNetty基本介绍!
月伴飞鱼
官网:https://netty.io/
Netty 是一个基于 JAVA NIO 类库的异步通信框架
。
用于创建异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性的网络客户端和服务器端
。
Netty
主要针对在 TCP协议下
,面向Clients端的高并发应用。
- 或者
Peer-to-Peer
场景下的 大量数据持续传输
的应用。
Netty本质是一个 NIO框架
,适用于 服务器通讯
相关的多种应用场景。

原生NIO存在的问题
NIO 的类库和 API 繁杂,使用麻烦。
要熟悉 Java 多线程编程
- 因为 NIO 编程涉及到
Reactor
模式
- 必须对多线程和网络编程非常熟悉,才能编写出高质量的 NIO 程序。
开发工作量和难度都非常大:
- 例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常流的处理等等。
JDK NIO 的 Bug:
- 例如臭名昭著的
Epoll Bug
:它会导致 Selector
空轮询,最终导致 CPU 100%。
- 直到 JDK 1.7 版本该问题仍旧存在,没有被根本解决。
应用场景
互联网行业:
- 在 分布式系统中,各个节点之间需要 远程服务调用,高性能的
RPC
框架必不可少
- Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些
RPC
框架使用
典型的应用有:
- 阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信
- Dubbo 协议默认使用
Netty
作为基础通信组件,用于实现各进程节点之间的内部通信
游戏行业
Netty案例
搭建 Server 端服务器:
ServerBootstrap
配置eventLoopGroup
:
- BossGroup : 处理连接请求,用于创建 Channel 转发给 WorkerGroup。
- workerGroup : 处理已建立的连接。
- 配置服务器处理的
Channel
连接的类型 ,包括 NIO 类型 , EPOLL 类型等。
- 配置整个处理流程的
ChannelHandler
,用于特定的处理。
- Server 端
bind()
一个端口 , 同时阻塞等待绑定完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| 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(); } }
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)); socketChannel.pipeline().addLast(new NettyServerHandler()); } }
public class NettyServer extends Thread {
public void run() {
EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workGroup = new NioEventLoopGroup(200);
ServerBootstrap bootstrap = new ServerBootstrap() .group(bossGroup, workGroup) .channel(NioServerSocketChannel.class) .childHandler(new ServerChannelInitializer());
try { InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 8090); ChannelFuture future = bootstrap.bind(socketAddress).sync(); System.out.println("S1 : 服务端构建完成 ....."); future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } } }
|
搭建客户端:
- 不同于 Server ,Client 端只需要一个
EventLoopGroup
。
- 创建 Bootstrap ,绑定
Group / channel / handler
。
- 通过
writeAndFlush
发送消息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| 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(); } }
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()); 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(); } } }
|
发起请求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class DemoService {
public static void main(String[] args) throws InterruptedException { System.out.println("Start :开始整个 Netty 搭建流程");
NettyServer server = new NettyServer(); server.start();
NettyClient client = new NettyClient(); client.start(); }
}
|