源码分析
Java · 33 篇笔记
- 2.19 Netty3.x源码分析historical
1. 总览 创建两个线程池,一个用于boss数组初始化,一个用于worker数组初始化 2. boss数组初始化的过程 所有的boss共享同一个线程池 1. 使用Selector.open打开选择器 2. 通过线程池执行一个run方法(这个方法是个死循环) 2.1 设置wakeup为false 2.
- 2.51 堆外内存historical
1. 什么是堆外内存 就是内存不是分配在Java堆上的,而是在操作系统内存上的 2. NIO堆外内存 JDK NIO ByteBuffer.allocate方法分配的内存是在Java堆上面的,当数据需要传输的时候需要把堆上的这块内存数据原封不动的copy到操作系统内存中 而Java NIO Byte
- 2.56 1.创建NioEventLoopGrouphistorical
1. NioEventLoopGroup类体系 如图,NioEventLoopGroup就是一个线程池,因此我们可以把任务封装成Runnable提交给NioEventLoopGroup执行 由继承的MultithreadXXX的名字可以看出,这玩意是一个多线程的池子,每个线程是什么呢--其实是Nio
- 2.57 2.Bootstrap的创建historical
1. 要分析的代码 2. 创建ServerBootstrap 创建ServerBootstrap没什么好说的,就是调用构造方法 3. 设置ServerBootstrap的属性 接下来就是设置他的属性,包括channel、handler、childHandler、option等 其中最重要channe
- 2.58 3.绑定端口historical
1. 要分析的代码 2. 服务端绑定端口 我们继续看绑定监听端口的逻辑 - bind 沿着bind往下追,最后到达doBind--关键方法 分为两步,一个是实例化、初始化并注册channel,另一个是真正绑定监听端口 2.1. 实例化、初始化并注册channel 1.实例化channel.md 2.
- 2.59 1.检测新连接historical
1. 打断点 有新连接过来的时候,会调用NioEventLoop中run方法的processSelectedKeys中OP ACCEPT逻辑 1.1. 启动客户端连接 我们在unsafe.read打个断点,启动服务器,并用telnet或者nc链接 2. 新连接进入 - 进入AbstractNioMe
- 2.60 pipeline的初始化historical
1. pipeline在什么时候被创建 不管是客户端还是服务端channel,都会在AbstractChannel的构造函数创建,每个channel都有一个自己的pipeline - newPipeline 2. pipeline是怎样的 - DefaultChannelPipeline pipel
- 2.61 1.服务端的创建historical
bind 从这行代码开始,追踪bind 最终会来到io.netty.bootstrap.AbstractBootstrap#doBind - initAndRegister channel 要知道channelFactory是哪个,我们需要回到这行代码 - io.netty.bootstrap.Ab
- 2.64 创建Executorhistorical
1. 要分析的代码 2. 创建构造线程的工厂 - newDefaultThreadFactory() 2.1. 设置线程池以及线程名 - DefaultThreadFactory - 设置了线程池的名字:nioEventLoopGroup - 每个线程的名字则是:nioEventLoopGroup-
- 2.65 2.创建NioSocketChannelhistorical
1. 要分析的代码 this是netty服务端的channel,ch是jdk nio客户端的channel,NioSocketChannel是netty客户端的channel 2. NioSocketChannel构造函数 2.1. 设置对OP READ感兴趣 - 父类AbstractNioByte
- 2.66 添加删除ChannelHandlerhistorical
1. 添加handler - DefaultChannelPipeline#addLast 1.1. 判断是否重复添加 - checkMultiplicity 1.2. 创建节点并添加至链表 - newContext - DefaultChannelHandlerContext - addLast0
- 2.67 2.服务端初始化historical
调用 bind - doBind - initAndRegister - channelFactory.newChannel() - init(channel) 我们重点看这个 ServerBootstrap - init
- 2.70 创建NioEventLoop数组historical
1. 要分析的代码 2. 传入NioEventLoop构造的参数 我们接着看 newChild(executor, args) ,跳转到 - NioEventLoopGroup#newChild 调用构造方法传入的参数 - this是NioEventLoopGroup自己 - executor是刚刚
- 2.71 3.分配线程及注册selectorhistorical
1. 要分析的代码 - io.netty.channel.nio.AbstractNioMessageChannel.NioMessageUnsafe#read中有一段逻辑 2. 通过pipeline传播 pipeline.fireChannelRead(readBuf.get(i)) 会从pipe
- 2.72 3.注册selectorhistorical
调用 bind - doBind - initAndRegister - channelFactory.newChannel() - init(channel) - ChannelFuture regFuture = config().group().register(channel);我们重点看这
- 2.74 4.向selector注册读事件historical
1. 要分析的代码 - io.netty.channel.AbstractChannel.AbstractUnsafe#register中的register操作 2. 打断点使用nc连接 其实跟服务器启动的时候向selector注册accept一样,我们看io.netty.channel.Abstr
- 2.75 4.服务端口绑定historical
调用 bind - doBind - initAndRegister - channelFactory.newChannel() - init(channel) - ChannelFuture regFuture = config().group().register(channel); - doB
- 2.79 1.实例化channelhistorical
1. 要分析的代码 2. 反射调用Channel.class的构造方法创建实例 通过反射调用NioServerSocketChannel的构造方法 3. NioServerSocketChannel 3.1. 类体系 3.2. 构造方法 3.2.1. 创建JDK NIO底层的ServerSocket
- 2.80 2.真正绑定监听端口historical
1. 要分析的代码 这段逻辑将 channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE ON FAILURE); 做成一个Runnable,丢进channel关联的NioEventLoop去执行 1.1.
- 2.81 Inbound事件historical
1. 添加handler以备实验 我们添加三个InboundHandler进行试验 - InboundHandlerA - InboundHandlerB、C都一样 - NettyServer 2. 从pipeline开始调用 但我们使用ctx.pipeline().fireChannelRead(
- 2.82 ByteBufhistorical
数据结构 有两个指针,一个标记读的位置,一个标记写的位置。 0 < 读 < 写 < capacity 其中0到读之间的数据是无效的,读到写之间的数据是可读的,写到capacity之间是可写的 Api readXXX表示读数据,读指针往后移动 writeXXX表示写数据,写指针往后移动 set不移动指
- 2.86 2.初始化channelhistorical
1. 要分析的代码 2. 获取channel pipeline并加入一个ChannelInitializer 如上的代码最关键的在于获取当前channel对应的pipeline,并加入了一个ChannelInitializer。 而在这个ChannelInitializer中,把我们自己在 Serv
- 2.87 NioEventLoop的run方法historical
1. 要分析的代码 如上代码主要分为三块逻辑 - 死循环 - 检测是否有IO事件 select - 处理IO事件 processSelectedKeys - 处理异步任务队列 runAllTasks 处理IO事件和处理外部线程的异步任务两者的时间由ioRatio平衡,默认情况下50,代表的意思是一半
- 2.88 Outbound事件historical
1. 添加handler以便实验 - OutboundHandlerA、OutboundHandlerC - OutboundHandlerB - NettyServer 1.1. 使用nc连接 1.2. 输出结果 1.3. 解释 可以看出是从尾巴往头部调用我们的handler 2. 从pipeli
- 2.89 ByteBufAllocatorhistorical
类体系 分配内存的工具类 ByteBufAllocator 这里的api只能区分heap还是direct,另外两个维度由AbstractByteBufAllocator的buffer方法实现 AbstractByteBufAllocator buffer方法 我们看看他的buffer方法 分配直接内
- 2.91 3.注册channelhistorical
1. 要分析的代码 2. 选择一个NioEventLoop - config()返回ServerBootstrap - Serverbootstrap的group()返回EventLoopGroup,EventLoopGroup继承了MultithreadEventLoopGroup,所以调用的是M
- 2.92 异常事件historical
1. 准备实验数据 - NettyServer - InboundHandlerA - InboundHandlerB - OutboundHandlerA - OutboundHandlerB 2. 开始debug 在 com.zsk.server.handler.InboundHandlerA#
- 2.95 Channel类体系historical
1. Channel类体系 1.1. Channel 用于网络IO 1.2. AbstractChannel Channel的骨架实现 1.3. AbstractNioChannel 使用Selector实现的Channel 1.4. AbstractNioByteChannel 操作字节流、对RE
- 2.97 PooledByteBufAllocatorhistorical
newDirectBuffer 主要分为两步,第一步时获取PoolThreadCache,进而获取PoolArena,第二步是通过PoolArena分配内存 通过PoolThreadLocalCache获取PoolThreadCache PoolThreadLocalCache其实是一个FastTh