netty线程模型
Netty是一个高性能、高可扩展性异步事件驱动的网络应用程序框架,它极大简化了TCP和UDP客户端和服务器开发等网络编程
结构:
Netty四个重要内容:
1、Reactor线程模型:一种高性能的多线程程序设计思路
2、Netty中自己定义的Channel概念:增强版的通道概念
3、ChannelPipeline职责联设计模式:时间处理机制
4、内存管理:增强的ByteBuf缓冲区
Tony源码中文分析注释:https://github.com/crazyFeng/netty/tree/netty-4.1.32.final-remark
优秀博客:https://www.cnblogs.com/lighten/p/8909254.html
整体结构 三大块
1、支持Socket等多种传输方式
2、提供了多种协议的编码实现
3、核心设计包含:
事件处理模型
API的使用
ByteBuffer的增强
netty线程模型
1、Resources资源(请求/任务)
2、Synchronius Event Demultiplexer同步事件复用器
3、Dispatch分配器
4、Request Handler请求处理器
EvenLoopGroup初始化过程
构造函数 -> 确定线程数量(默认cpus的两倍)-> new Executor构建线程执行器 -> for--newChild()构建ExentLoop -> new EventExecutorChooser
EventLoopGroup:
Main EventLoopGroup:轮询通过事件分配执行任务(任务队列、事件选择器)
sub EventLoopGroup:处理请求(IO)
netty中ServerSocketChannel用的是NioMessageUnsafe,socketChannel用的是NioByteUnsafe
责任链模式 chins
为请求创建了一个处理对象的链。发起请求个具体处理请求的过程进行解耦:责任链上的处理者扶着处理请求,客户只需要将请求发送到
职责链上即可,无须关心请求的处理细节和请求的传递
4个要素:
处理器抽象类、具体处理器实现类、保存处理器信息、处理执行
零拷贝复制机制 https://blog.csdn.net/linsongbin1/article/details/77650105
传统读操作:
当应用发起一个从磁盘读取文件的操作时,请求会先经过内核,由内核与磁盘进行交互。数据会从磁盘拷贝到内核的缓存区中。
这个copy动作由DMA(硬件和软件的信息传输、直接存储器访问)完成,整个过程中基本上不消耗CPU。如果应用想拿到信息,
还得从内核缓冲区获取,这里又存在一个cpu copy的动作,将数据从内核缓冲区中拷贝到应用缓冲区中。这个copy动作是需要消耗CPU的。
所以应用想拿到数据需要2次copy动作。
传统读操作流程:
传统写操作:
应用想将数据传递给客户端,必须经过内核,将数据先从应用缓冲区中copy(cpu copy)到内核的缓冲区中,对于写操作而言,通常这个内核缓
冲区叫kernel socket buffer,接着DMA会从kernel socket buffer中将数据拷贝(DMA copy)到protocol engine,最终将数据发送给客户端。
这里又发生2次copy动作,一次是cpu copy,另外一次是DMA copy。
传统写操作流程:
ByteBuf:
JDK ByteBuffer的缺点:
无法动态扩容:
JDK的ByteBuffer长单独是固定的,不能动态扩展和收缩,当数据大于ByteBuffer容量时,会发生索引越界异常
API使用复杂:
读写时需手动调用flip()和rewind()等方法,需谨慎使用这些API,容易出现错误
ByteBuf做了增强:
1、API操作便捷性
2、动态扩容
3、多种ByteBuf实现
4、零拷贝机制
属性:
1、capacity 容量
2、readerIndex 读取位置
3、writerIndex 写入位置
网络编程(推送)
短链接:请求/响应之后,关闭已建立的TCP链接,下次请求重新建立请求
长链接:请求/响应之后,不关闭TCP链接,多次请求,复用同一个链接
粘包:Nagle算法-客户端累积一定量或者缓冲一段时间紧再传输。服务端缓冲区堆积,导致多个请求粘贴在一起
拆包:发送的数据大于发送缓冲区,及逆行分片 传输。服务端缓冲区堆积,导致服务端读取的数据不完整
TCP链接四元组:
服务器IP+服务器PORT+客户端IP+客户端PORT
邮箱
海量用户的情况如下:
1、知道哪些接受者需要接受这条消息
2、确定哪些服务器需要接受推送这个消息
4、消息存到MQ
代更新。。