ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Java IO从入门到精通12

Java IO从入门到精通12 第12章 Netty入门与综合项目实战学习目标理解Netty的架构设计及其在Java IO生态中的定位掌握Bootstrap和ServerBootstrap的使用方法深入理解EventLoopGroup和Reactor线程模型掌握ChannelPipeline与ChannelHandler的职责链模式理解ByteBuf的设计优势及其与ByteBuffer的区别掌握Netty中常见的编解码器能够基于Netty开发HTTP服务器和简易RPC框架识别并避免ByteBuf内存泄漏和EventLoop阻塞等常见陷阱核心概念Netty简介Netty是一个高性能、异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器和客户端。Netty对Java NIO进行了封装,提供了更易用的API和更强大的功能。Netty的核心优势:简化的API:屏蔽了NIO的复杂性高性能:零拷贝、内存池化、高效的Reactor线程模型可扩展性:基于ChannelPipeline的职责链模式丰富的协议支持:HTTP、WebSocket、SSL等社区活跃:广泛使用,文档丰富Netty架构概览Netty的架构可以分为以下几个核心层:+--------------------------------------------------+ | 业务逻辑层 | | ChannelHandler, SimpleChannelInboundHandler | +--------------------------------------------------+ | 编解码层 | | ByteToMessageDecoder, MessageToByteEncoder | | StringEncoder/Decoder, HttpObjectEncoder/Decoder | +--------------------------------------------------+ | 核心层 | | Channel, ChannelPipeline, ChannelHandlerContext | | EventLoopGroup, EventLoop | +--------------------------------------------------+ | 传输层 | | NIO (NioSocketChannel), Epoll, OIO, Local | +--------------------------------------------------+Bootstrap与ServerBootstrapBootstrap是Netty的启动辅助类,用于配置和启动Netty应用。ServerBootstrap:用于服务端,绑定到指定端口监听客户端连接。ServerBootstrapbootstrap=newServerBootstrap();bootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG,128).childOption(ChannelOption.SO_KEEPALIVE,true).childHandler(newChannelInitializerSocketChannel(){@OverrideprotectedvoidinitChannel(SocketChannelch){ch.pipeline().addLast(newMyServerHandler());}});ChannelFuturefuture=bootstrap.bind(8080).sync();Bootstrap:用于客户端,连接到远程服务器。Bootstrapbootstrap=newBootstrap();bootstrap.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY,true).handler(newChannelInitializerSocketChannel(){@OverrideprotectedvoidinitChannel(SocketChannelch){ch.pipeline().addLast(newMyClientHandler());}});ChannelFuturefuture=bootstrap.connect("localhost",8080).sync();EventLoopGroup与Reactor模型EventLoopGroup是Netty的线程池管理核心,其设计基于Reactor模式。Reactor模型的三种实现:单线程Reactor:一个EventLoop处理所有连接和IO事件。适用于小规模应用。EventLoop (单线程) ├── 处理accept事件 ├── 处理read事件 └── 处理write事件多线程Reactor:一个EventLoopGroup处理accept,多个EventLoop处理IO事件。适用于中等规模应用。BossGroup (1个线程) └── NioServerSocketChannel (accept) WorkerGroup (多个线程) ├── NioSocketChannel (read/write) ├── NioSocketChannel (read/write) └── NioSocketChannel (read/write)主从Reactor:多个Boss线程处理accept,多个Worker线程处理IO。适用于高并发应用。// 主从Reactor配置EventLoopGroupbossGroup=newNioEventLoopGroup(2);// 多个Boss线程EventLoopGroupworkerGroup=newNioEventLoopGroup(Runtime.getRuntime().availableProcessors()*2);EventLoop的绑定关系:一个EventLoop对应一个Selector一个EventLoop处理多个Channel一个Channel的所有操作都在同一个EventLoop上执行(线程安全的关键)ChannelPipeline与ChannelHandlerChannelPipeline是Netty的职责链(Chain of Responsibility)模式的核心实现。Pipeline的职责链结构:入站: Socket → HeadContext → Handler1 → Handler2 → ... → TailContext 出站: Socket ← HeadContext ← Handler1 ← Handler2 ← ... ← TailContextChannelHandler的类型:ChannelInboundHandler:处理入站事件(read、registered、active等)ChannelOutboundHandler:处理出站事件(write、connect、bind等)ChannelDuplexHandler:同时处理入站和出站事件publicclassMyHandlerextendsChannelInboundHandlerAdapter{@OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg){// 处理入站消息ByteBufbuf=(ByteBuf)msg;// ...ctx.fireChannelRead(msg);// 传递给下一个Handler}@OverridepublicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause){cause.printStackTrace();ctx.close();}}ByteBuf vs ByteBufferNetty的ByteBuf是对Java NIO ByteBuffer的重新设计,解决了ByteBuffer的诸多缺陷。特性ByteBufferByteBuf读写索引单一position独立的readerIndex和writerIndex扩容不支持,需手动重新分配自动扩容池化不支持支持(PooledByteBufAllocator)零拷贝有限支持支持CompositeByteBuf引用计数不支持支持(ReferenceCounted)API易用性复杂,需手动flip/clear直观,无需flipByteBuf的双指针设计:+-------------------+-------------------+------------------+ | 丢弃的字节 | 可读的字节 | 可写的字节 | | (discardable) | (readable) | (writable) | +-------------------+-------------------+------------------+ | | | | 0 readerIndex writerIndex capacity常用API示例:ByteBufbuf=Unpooled.buffer(256);// 写入数据buf.writeBytes("Hello".getBytes());buf.writeInt(42);// 读取数据byte[]bytes=newbyte[5];buf.readBytes(bytes);// 读取"Hello"intnum=buf.readInt();// 读取42// 无需flip!// readerIndex和writerIndex各自独立管理编解码器Netty提供了丰富的编解码器,将字节流和业务对象之间的转换封装在Pipeline中。常用编码器:StringEncoder/StringDecoder:字符串编解码HttpRequestEncoder/HttpResponseDecoder:HTTP协议编解码ProtobufEncoder/ProtobufDecoder:Protobuf编解码自定义编解码器:// 编码器:将对象转换为字节publicclassMessageEncoderextendsMessageToByteEncoderMessage{@Overrideprotectedvoidencode(ChannelHandlerContextctx,Messagemsg,ByteBufout){out.writeInt(msg.getLength());out.writeBytes(msg.getData());}}// 解码器:将字节转换为对象publicclassMessageDecoderextendsByteToMessageDecoder{@Overrideprotectedvoiddecode(ChannelHandlerContextctx,ByteBufin,ListObjectout){if(in.readableBytes(
返回列表