②I/O 多路复用:Poll
文章插图
简介:设计新的数据结构(链表)提供使用效率 。
Poll 和 Select 相比在本质上变化不大,只是 Poll 没有了 Select 方式的最大文件描述符数量的限制 。
缺点:逐个排查所有 FD 状态效率不高 。
③I/O 多路复用:Epoll
简介:没有 FD 个数限制,用户态拷贝到内核态只需要一次,使用事件通知机制来触发 。
通过 epoll_ctl 注册 FD,一旦 FD 就绪就会通过 Callback 回调机制来激活对应 FD,进行相关的 I/O 操作 。
缺点如下:
- 跨平台,Linux 支持最好 。
- 底层实现复杂 。
- 同步 。
而且就像上图中代码调用,处理网络连接的代码和业务代码解耦得不够好 。
Netty 提供了简洁、解耦、结构清晰的 API 。
publicstaticvoidmain(String[]args){newNettyServer().serverStart();System.out.println("Nettyserverstarted!");}publicvoidserverStart(){EventLoopGroupbossGroup=newNioEventLoopGroup();EventLoopGroupworkerGroup=newNioEventLoopGroup();ServerBootstrapb=newServerBootstrap();b.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).childHandler(newChannelInitializer<SocketChannel>(){@OverrideprotectedvoidinitChannel(SocketChannelch)throwsException{ch.pipeline().addLast(newHandler());}});try{ChannelFuturef=b.localAddress(Constant.HOST,Constant.PORT).bind().sync();f.channel().closeFuture().sync();}catch(InterruptedExceptione){e.printStackTrace();}finally{workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}}classHandlerextendsChannelInboundHandlerAdapter{@OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg)throwsException{ByteBufbuf=(ByteBuf)msg;ctx.writeAndFlush(msg);ctx.close();}@OverridepublicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause)throwsException{cause.printStackTrace();ctx.close();}}bossGroup 处理网络请求的大管家(们),网络连接就绪时,交给 workGroup 干活的工人(们) 。
总结回顾上文总结如下:
- 同步/异步,连接建立后,用户程序读写时,如果最终还是需要用户程序来调用系统 read() 来读数据,那就是同步的,反之是异步 。windows 实现了真正的异步,内核代码甚为复杂,但对用户程序来说是透明的 。
- 阻塞/非阻塞,连接建立后,用户程序在等待可读可写时,是不是可以干别的事儿 。如果可以就是非阻塞,反之阻塞 。大多数操作系统都支持的 。
了解计算机底层的知识才能更深刻地理解 I/O,知其然,更要知其所以然 。与君共勉!
作者:周胜帅
简介:宜信支付结算部支付研发团队高级工程师
【Redis,Nginx,Netty为什么这么香?】
推荐阅读
- 分享Nginx搭建图片服务器简单实现
- 部署Nginx+Apache动静分离
- Redis简单动态字符串 全面剖析
- 分布式系统之Redis主从架构
- 分享--部署Nginx+Apache动静分离
- PHP操作Redis常用方法总结
- 一篇详解Redis延时队列
- 阿里P9架构师分享:通俗易懂Redis原理,都是你没看过的
- Linux系统架构-----Apache与Nginx动静分离
- Linux下如何用nginx+ffmpeg搭建流媒体服务器