NIO&EPOLL&多路复用

非阻塞IO(NIO)

socket通信底层流程:server端开启一个对外暴露的端口,并生成对应的文件描述符(fd3),通过系统调用listen(fd3)监听该文件描述符。当client与server端建立socket通信之后,在对应进程文件(/proc/3209)下的fd文件夹中生产对应的文件描述符fd5(通信通过文件描述符进行),该进程生产的子线程在task文件夹。
socket连接之后产生对应的文件描述符(fd5),通信建立,之后系统调用recvfrom(fd5)开始监听文件描述符5,如果这时listen,accept,recvfrom会阻塞就是BIO,如果使用非阻塞的listen,accept,recvfrom就是NIO。但使用非阻塞的,cpu要一直遍历所有的fd,消耗性能。所有之后使用了多路复用器,可以选取出可用的文件描述符(既需要处理消息的客户端);所以服务端就不用每次都遍历全部客户端了,直接使用多路复用找出需要处理的客户端,提高了性能。
IO多路复用既多个socket连接复用一个线程。
在这里插入图片描述在这里插入图片描述poll&epoll:多路复用
poll可以监听多个文件描述符,每次调用poll都需要从用户态向内核态传递所以的fd(文件描述符),当fd比较大的时候比较消耗资源,返回可用的文件描述符。内核会主动遍历全部的文件描述符,返回可用的文件描述符。
epoll可以监听多个文件描述符(fd只在epoll_ctl调用的时候传递一次),事件驱动,内核不会主动遍历全部的文件描述符。当文件描述符对于端口有数据来到网卡的时候,网卡会产生中断,生产对应中断号。cpu中断,将对应的文件描述符加入到可用的集合中。
在这里插入图片描述

redis中的epoll和IOthreads

redis使用epoll多路复用选择需要处理的客户端,然后使用多个io线程读取客户端的请求(io读取需要系统调用read,write方法,多以多线程可以充分发挥多核cpu的优势),一个线程进行计算(计算任然是串行的)。
在这里插入图片描述

kafka中的mmap和零拷贝

kafka写数据(mmap)
生产者发送数据到kafka时,先与操作系统内核kernel建立连接,kafka通过epoll找到需要处理的客户端,通过系统调用recvfrom(每一次数据读取都需要系统调用recvfrom)将数据从kernel将读取到用户态,再将数据加上一些额外的头信息,然后将数据写到内核中。虽然读取数据每次都需要系统调用recvfrom,但是写数据的时候kafka不会来一条数据就系统调用write写数据到kernel,而是使用了mmap(用户态和内核态公用的内存空间,用户态写数据不用系统调用,直接put到mmap就可以写到磁盘中)写数据到内核,减少了write系统调用。每次kafka开辟一个1g大小的内存空间与磁盘中的segment对于,每次写数据的时候向mmap,就顺序写到了磁盘的segment的中,一个segment写满之后,清空mmap空间,磁盘上再开辟一个新的segment顺序写。
在这里插入图片描述

kafka读取数据(零拷贝sendfile)
当客户端要消费数据的时候,先找到数据所在的segment,然后系统调用read方法将数据从磁盘读取到内核,然后再从内核读取到程序中(用户态),程序再通过系统调用write,把数据写到内核,再从socket发送出去。
但是消息的读取并不需要程序对数据进行加工处理,所以将数据读取到程序是没有必要的。
所以kafka采取的方式是通过系统调用sendfile方法,将对于的输入和输出的文件描述符传入,就将数据从磁盘拷贝到内核,然后通过对应的socket发送出去。(数据不需要返回到用户空间,直接发送出去
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值