iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >分布式Netty源码分析概览
  • 292
分享到

分布式Netty源码分析概览

2024-04-02 19:04:59 292人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录服务器端demoEventLoopGroup介绍功能1:先来看看注册Channel功能2:执行一些Runnable任务ChannelPipeline介绍bind过程sync介绍误

服务器端demo

看下一个简单的Netty服务器端的例子

public static void main(String[] args){
	EventLoopGroup bossGroup=new NIOEventLoopGroup(1);
	EventLoopGroup workerGroup = new NioEventLoopGroup();
	try {
		ServerBootstrap serverBootstrap=new ServerBootstrap();
		serverBootstrap.group(bossGroup,workerGroup)
			.channel(NiOServerSocketChannel.class)
			.option(ChannelOption.SO_BACKLOG, 200)
			.childHandler(new ChannelInitializer<SocketChannel>() {
				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(80,0,4,0,4));
					ch.pipeline().addLast(new StringDecoder(Charset.forName("UTF-8")));
					ch.pipeline().addLast(new tcpServerHandler());
				}
			});
		ChannelFuture f=serverBootstrap.bind(8080).sync();
		f.channel().closeFuture().sync();
	} catch (InterruptedException e) {
		e.printStackTrace();
	}finally {  
        workerGroup.shutdownGracefully();  
        bossGroup.shutdownGracefully();  
    }  
}

先来简单说说上述遇到的类:

EventLoopGroup介绍

它主要包含2个方面的功能,注册Channel和执行一些Runnable任务。

功能1:先来看看注册Channel

即将Channel注册到Selector上,由Selector来调度Channel的相关事件,如读、写、Accept等事件。

而EventLoopGroup的设计是,它包含多个EventLoop(每一个EventLoop通常内部包含一个线程),在执行上述注册过程中是需要选择其中的一个EventLoop来执行上述注册行为,这里就出现了一个选择策略的问题,该选择策略接口是EventExecutorChooser,你也可以自定义一个实现。

从上面可以看到,EventLoopGroup做的工作大部分是一些总体性的工作如初始化上述多个EventLoop、EventExecutorChooser等,具体的注册Channel还是交给它内部的EventLoop来实现。

功能2:执行一些Runnable任务

EventLoopGroup继承了EventExecutorGroup,EventExecutorGroup也是EventExecutor的集合,EventExecutorGroup也是掌管着EventExecutor的初始化工作,EventExecutorGroup对于Runnable任务的执行也是选择内部中的一个EventExecutor来做具体的执行工作。

netty中很多任务都是异步执行的,一旦当前线程要对某个EventLoop执行相关操作,如注册Channel到某个EventLoop,如果当前线程和所要操作的EventLoop内部的线程不是同一个,则当前线程就仅仅向EventLoop提交一个注册任务,对外返回一个ChannelFuture。

总结:EventLoopGroup含有上述2种功能,它更多的是一个集合,但是具体的功能实现还是选择内部的一个item元素来执行相关任务。 这里的内部item元素通常即实现了EventLoop,又实现了EventExecutor,如NioEventLoop等

ChannelPipeline介绍

上述EventLoopGroup可以将一个Channel注册到内部的一个EventLoop的Selector上,然后对于这个Channel的相关读写等事件,Netty专门设计了一个ChannelPipeline来进行处理。每一个Channel都有一个ChannelPipeline来处理该Channel的读写等事件。

bind过程

上述serverBootstrap的bind过程如下:

  • 创建出你所指定的NioServerSocketChannel,然后初始化一些Socket方面的参数
  • 为上述Channel的ChannelPipeline配置一个ChannelHandler,该ChannelHandler的作用就是在该Channel成功注册到Selector上的时候,初始化一些逻辑,即initChannel方法中执行一些逻辑,该逻辑就是向ChannelPipeline中添加一个新的ChannelHandler即ServerBootstrapAcceptor
  • 然后开始将该Channel注册到上述EventLoopGroup bossGroup中,该EventLoopGroup bossGroup会选择内部的一个EventLoop来执行实际的注册行为(这个时候就是当前线程和操作的EventLoop不是同一个线程,即该过程是异步提交一个Runnable),一旦注册完成,就执行上述ChannelHandler的initChannel方法

至此,就完成了整个bind过程。一旦EventLoop内部的Selector检测到NioServerSocketChannel有新的连接到来的事件,则会交给NioServerSocketChannel的ChannelPipeline来处理,重点就是ChannelPipeline中的上述ServerBootstrapAcceptor,ServerBootstrapAcceptor做如下操作:

  • 1 为新的Channel的ChannelPipeline配置我们上述代码中的childHandler指定的ChannelHandler
  • 2 将新的Channel注册到了上述EventLoopGroup workerGroup中

sync介绍

bind方法返回的是一个ChannelFuture,从上面我们也知道该过程是异步的,sync方法则是一直等待到该异步过程结束。

再看下f.channel().closeFuture().sync()这个方法

每一个ChannelFuture都是和一个Channel绑定的,所以可以通过ChannelFuture来获取对应绑定的Channel对象

每一个Channel对象都有一个CloseFuture closeFuture对象,上述closeFuture方法并不是去执行close方法而是获取到这个CloseFuture closeFuture对象,然后调用它的sync方法即等待这个Future的结束。一般正常情况下是不会调用这个Future的结束方法的,只是在上述过程或者其他过程出现问题的时候,如注册到EventLoop失败等才会去调用这个Feture的结束方法,所以正常情况下主线程会一直阻塞在CloseFuture closeFuture的sync方法上。

误区

上述的bossGroup的创建问题。

我们都知道bossGroup是用来accept连接,然后将连接绑定到workerGroup中的,一般情况下bossGroup设置线程数为1即可(基本只能为1),我们同时知道Ractor模型中可以使用多个Acceptor线程来执行accept操作,加快accept的速度。

如果你想加快accept的速度,想开启多线程来accept,这时候想设置bossGroup的线程数为多个的话,就大错特错了,是根本没效果的。

结合上面的原理,只有在bind端口的时候才会创建一个ServerSocketChannel,然后注册到bossGroup内部的一个EventLoop中,仍然是单线程负责ServerSocketChannel的accept工作,而bossGroup中的多线程仅仅是为bind多个端口服务的。

我们来看下Tomcat是如何允许多个Acceptor线程来执行accept操作的:

  • 1 创建了一个ServerSocketChannel serverSock,并bind到某个端口
  • 2 开启多个Acceptor线程,每个线程逻辑都是执行上述serverSock的accept方法

没有使用Selector来执行accept操作,可以多线程并发执行上述serverSock的accept方法。

一旦使用了Selector,基本上就相当于将ServerSocketChannel serverSock绑定到了Selector所在线程上了(Selector不是线程安全的,只能在一个线程中被调度执行)

4 后续

下一篇就要详细描述下EventLoopGroup了。

以上就是分布式Netty源码分析概览的详细内容,更多关于分布式Netty源码分析的资料请关注编程网其它相关文章!

--结束END--

本文标题: 分布式Netty源码分析概览

本文链接: https://www.lsjlt.com/news/143818.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 分布式Netty源码分析概览
    目录服务器端demoEventLoopGroup介绍功能1:先来看看注册Channel功能2:执行一些Runnable任务ChannelPipeline介绍bind过程sync介绍误...
    99+
    2022-11-13
  • 分布式Netty源码分析
    这篇文章主要介绍了分布式Netty源码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇分布式Netty源码分析文章都会有所收获,下面我们一起来看看吧。服务器端demo看下一个简单的Netty服务器端的例子pu...
    99+
    2023-06-29
  • 分布式Netty源码EventLoopGroup分析
    这篇文章主要介绍“分布式Netty源码EventLoopGroup分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“分布式Netty源码EventLoopGroup分析”文章能帮助大家解决问题。Ev...
    99+
    2023-06-29
  • 分布式Netty源码分析EventLoopGroup及介绍
    目录EventLoopGroup介绍功能1:先来看看注册Channel功能2:执行一些Runnable任务EventLoop介绍NioEventLoop介绍EpollEventLoo...
    99+
    2022-11-13
  • Netty分布式ByteBuf的分类方式源码解析
    目录ByteBuf根据不同的分类方式 会有不同的分类结果1.Pooled和Unpooled2.基于直接内存的ByteBuf和基于堆内存的ByteBuf3.safe和unsafe上一小...
    99+
    2022-11-13
  • Netty分布式源码分析监听读事件
    前文传送门:NioSocketChannel注册到selector 我们回到AbstractUnsafe的register0()方法: private void register0(...
    99+
    2022-11-13
  • Netty分布式pipeline传播inbound事件源码分析
    目录传播inbound事件这里给大家看两种写法我们先以写法2为例, 将这种写法进行剖析我们跟进invokeChannelRead方法:我们跟到invokeChannelRead方法中...
    99+
    2022-11-13
  • Netty分布式NioEventLoop优化selector源码解析
    目录优化selectorselector的创建过程代码剖析这里一步创建了这个优化后的数据结构最后返回优化后的selector优化selector selector的创建过程...
    99+
    2022-11-13
  • Netty分布式NioEventLoop任务队列执行源码分析
    目录执行任务队列跟进runAllTasks方法:我们跟进fetchFromScheduledTaskQueue()方法回到runAllTasks(long timeoutNanos)...
    99+
    2022-11-13
  • Netty分布式ByteBuf缓冲区分配器源码解析
    目录缓冲区分配器以其中的分配ByteBuf的方法为例, 对其做简单的介绍跟到directBuffer()方法中我们回到缓冲区分配的方法然后通过validate方法进行参数验...
    99+
    2022-11-13
  • Netty分布式行解码器逻辑源码解析
    目录行解码器LineBasedFrameDecoder首先看其参数我们跟到重载的decode方法中我们看findEndOfLine(buffer)方法前文传送门:Netty分布式固定...
    99+
    2022-11-13
  • Netty分布式flush方法刷新buffer队列源码分析
    本文小编为大家详细介绍“Netty分布式flush方法刷新buffer队列源码分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Netty分布式flush方法刷新buffer队列源码分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入...
    99+
    2023-06-29
  • Netty分布式server启动流程Nio创建源码分析
    目录NioServerSocketChannel创建继承关系绑定端口端口封装成socket地址对象跟进initAndRegister()方法 创建channel父类的构造方法将jdk...
    99+
    2022-11-13
  • Netty分布式客户端接入流程初始化源码分析
    目录前文概述:第一节:初始化NioSockectChannelConfig创建channel跟到其父类DefaultChannelConfig的构造方法中再回到AdaptiveRec...
    99+
    2022-11-13
  • Netty分布式pipeline管道传播outBound事件源码解析
    目录outbound事件传输流程这里我们同样给出两种写法跟到其write方法中:跟到findContextOutbound中回到write方法:继续跟invokeWrite0我们跟到...
    99+
    2022-11-13
  • Netty分布式flush方法刷新buffer队列源码剖析
    目录flush方法这里最终会调用AbstractUnsafe的flush方法跟进addFlush方法回到addFlush方法回到AbstractUnsafe的flush方法我们重点关...
    99+
    2022-11-13
  • Netty分布式Server启动流程服务端初始化源码分析
    目录第一节:服务端初始化group方法初始化成员变量初始化客户端Handler第一节:服务端初始化 首先看下在我们用户代码中netty的使用最简单的一个demo: //创建boss和...
    99+
    2022-11-13
  • Netty分布式ByteBuf使用的底层实现方式源码解析
    目录概述AbstractByteBuf属性和构造方法首先看这个类的属性和构造方法我们看几个最简单的方法我们重点关注第二个校验方法ensureWritable(length)我们跟到扩...
    99+
    2022-11-13
  • Netty分布式抽象编码器MessageToByteEncoder逻辑分析
    目录MessageToByteEncoder首先看MessageToByteEncoder的类声明跟到allocateBuffer方法中前文回顾:Netty分布式编码器及写数据事件处...
    99+
    2022-11-13
  • Netty分布式获取异线程释放对象源码剖析
    目录获取异线程释放对象在介绍之前我们首先看Stack类中的两个属性我们跟到pop方法中继续跟到scavengeSome方法中我们继续分析transfer方法接着我们我们关注一个细节我...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作