分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

netty 原理

发布时间:2023-09-06 01:55责任编辑:白小东关键词:暂无标签

netty 实现

1. 各组件之间的关系


每个ServerBootstrap与一个事件循环对象(一个线程)都会与一个Channel绑定,如NioServerSocketChannel

2. 如何绑定

在做bind操作时,会执行方法,register进行注册

ChannelFuture regFuture = config().group().register(channel);

关键接口及类之间的关系:

EventLoopGroup与EventLoop及其类关系图之间形成组合模式。

@Overridepublic ChannelFuture register(Channel channel) { ???return next().register(channel);//选择一个线程执行器,调用register方法,绑定channel}
@Overridepublic ChannelFuture register(Channel channel) { ???return register(new DefaultChannelPromise(channel, this));}

3. 代表客户端的channel创建

注意到ServerBootstrap有两个EventLoopGroup,parent 负责代表客户端channel的分发,child负责代码客户端channel的处理。

  • Accept事件,创建代表客户端的channel
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) { ???unsafe.read();}
try { ???do { ???????int localRead = doReadMessages(readBuf); ???????if (localRead == 0) { ???????????break; ???????} ???????if (localRead < 0) { ???????????closed = true; ???????????break; ???????} ???????allocHandle.incMessagesRead(localRead); ???} while (allocHandle.continueReading());} catch (Throwable t) { ???exception = t;}int size = readBuf.size();for (int i = 0; i < size; i ++) { ???readPending = false; ???pipeline.fireChannelRead(readBuf.get(i));}readBuf.clear();allocHandle.readComplete();pipeline.fireChannelReadComplete();
protected int doReadMessages(List<Object> buf) throws Exception { ???SocketChannel ch = SocketUtils.accept(javaChannel()); ???try { ???????if (ch != null) { ???????????buf.add(new NioSocketChannel(this, ch)); ???????????return 1; ???????} ???} catch (Throwable t) { ???????logger.warn("Failed to create a new channel from an accepted socket.", t); ???????try { ???????????ch.close(); ???????} catch (Throwable t2) { ???????????logger.warn("Failed to close a socket.", t2); ???????} ???} ???return 0;}

注意到doReadMessages会创建代表客户端的channel,创建完成会触发,fireChannelRead 事件。

4. 代表客户端的channel分发

上一节知道,channel创建完成会触发fireChannelRead 事件。在ServerSocketChannel初始化时,会注册ServerBootstrapAcceptor 用户接收代表客户端channel并分发到child EventLoopGroup中执行。

p.addLast(new ChannelInitializer<Channel>() { ???@Override ???public void initChannel(final Channel ch) throws Exception { ???????final ChannelPipeline pipeline = ch.pipeline(); ???????ChannelHandler handler = config.handler(); ???????if (handler != null) { ???????????pipeline.addLast(handler); ???????} ???????ch.eventLoop().execute(new Runnable() { ???????????@Override ???????????public void run() { ???????????????pipeline.addLast(new ServerBootstrapAcceptor( ???????????????????????ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); ???????????} ???????}); ???}});
@Override@SuppressWarnings("unchecked")public void channelRead(ChannelHandlerContext ctx, Object msg) { ???final Channel child = (Channel) msg; ???child.pipeline().addLast(childHandler); ???setChannelOptions(child, childOptions, logger); ???for (Entry<AttributeKey<?>, Object> e: childAttrs) { ???????child.attr((AttributeKey<Object>) e.getKey()).set(e.getValue()); ???} ???try { ???????childGroup.register(child).addListener(new ChannelFutureListener() { ???????????@Override ???????????public void operationComplete(ChannelFuture future) throws Exception { ???????????????if (!future.isSuccess()) { ???????????????????forceClose(child, future.cause()); ???????????????} ???????????} ???????}); ???} catch (Throwable t) { ???????forceClose(child, t); ???}}

5. netty线程模型


不管是客户端还是服务端可以通过一个Channel同时读或者写,不需要阻塞,读写多路复用。

6. handler链模型

netty 原理

原文地址:https://www.cnblogs.com/dragonfei/p/9074752.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved