学习内容
P1P43,P110P116,中间章节好枯燥啊,暂时用不到,先跳过了
IO模型参考:https://blog.csdn.net/lzb348110175/article/details/98941378
学习链接:https://www.bilibili.com/video/BV1DJ411m7NR?p=42&vd_source=510ec700814c4e5dc4c4fda8f06c10e8
系统优化:要么是分层处理,要么是叫缓存
先做一个铺垫吧,IO模型分为同步阻塞BIO、同步非阻塞NIO、多路复用IO、异步AIO。后面详细介绍
BIO(Blocking IO):同步阻塞IO。这种阻塞是针对内核空间而言的,内核空间需要准备数据 。适合连接数少的情况,实际用户请求一次就是开一个线程处理,虽然有线程池可以优化
NIO(Non-Blocking IO): 同步非阻塞IO。适合连接数多且时长短的,比如聊天连接器
Asynchronous IO。适合连接数多且时长长的
本质就是NIO框架,底层是jdk代码,更下层是TCP/IP协议。比如阿里的Dubbo的RPC框架就是用的Netty、Spark
三大组件Channel通道,Buffer缓冲区,Selector选择器
原本BIO是每有一个客户连接服务端就创建一个线程处理,现在NIO就创建一个线程进行选择处理,如果没有通道有数据,那就跳过不阻塞(和Kafka消费者与kafka-Broker关系类似)
总结就是一个Selector监听多个Channel,每个Channel又对应一个Buffer。Buffer是面向块(底层是个数组,BIO是面向字节流)
缓冲区,面向块编程,底层就是个数组,用各个标记控制数组长度与大小,由于可读也可写,所以实时都会改变
Channel本身是个接口,Buffer有源码,Channel也有。可用于读取文件、网络传输等等等等。之前的InputStream内部就包含了Channel
程序 <=> Buffer <=> Channel <=> 文件:所以不仅可以读取文件内容程序输出,也可以读取文件内容输出到另一个文件。除了单个Buffer,还可以定义Buffer数组(服务器网络交互中进行处理,一个Channel对应一个Buffer数组)
Channel.write(Buffer):表明Buffer往Channel写
Channel.read(Buffer):表明Channel从Buuffer读
在直接内存(堆外内存)操作数据,操作系统就不需要拷贝一次
就是将每个Channel注册到Selector中,然后当Channel有数据传入进来时,Selector非阻塞式读取,避免了每个请求都创建一个线程,减少了多线程上下文的切换。
具体注册流程就是客户端通过ServerSocketChannel注册到Selector中,Selector维护一个SelectionKey的集合返回
就是用Selector + Channel + Buffer实现局域网消息单聊与群聊,暂时感觉用不到,比较枯燥,先跳过,先了解理论知识即可。
DMA:direct memory access 直接内存拷贝,不使用CPU
参考链接:https://blog.csdn.net/shenchaohao12321/article/details/115464117
零拷贝:本质就是内核缓冲区中间没有重复数据,减少数据拷贝次数
传统IO:用户依次发起read、write请求,整个过程发送4次用户态和内核态上下文切换与数据拷贝
mmap内存映射:4次上下文切换,3次数据拷贝。write的时候减少了一次。适合小文件读取
sendFile(Linux中):3次上下文切换,最少2次数据拷贝,适合大文件读取
AIO两种模式:Reactor, Proactor。NIO本身也是一个Reactor。
Es,dubbo底层都用到了Netty, netty对nio各种api接口进行了封装
远程过程调用:计算机程序调用另一个计算机子程序。
常见RPC框架:dubbo, springcloud
实际开发中,使用Netty实现rpc调用,就是需要客户端和服务端都开发netty代码,然后调用返回相应的对象。