Reactor反应堆模式

使用智能指针,一方面因为纯虚类不能构造对象,另一方面减少对象拷贝

检查连接过期

改成多进程版本

在创建套接字之后,设置选项SO_REUSEPORT选项

子进程继承父进程的Listener(子进程也可以重新创建),每个子进程都是一个Reactor,内核会做负载均衡,父进程只等待连接,连接到来,内核会回负载均衡地把到来的连接分给子进程,子进程只关心父进程给自己fd的事件

核心原理是首先调用eventfd,创建子进程,父子进程拿到同一个文件描述符,子进程调用read,父进程不写,子进程就阻塞,父进程写入,子进程就被唤醒,通过这种机制就可以实现父进程通知子进程,连接到来了,并且把到来连接fd的值写入,子进程读到自然就知道要处理哪个fd的读写事件

flags如果是EFD_CLOEXEC,表明,如果发生程序替换,fd会被关闭,不会被新程序继承

如果设置了EFD_SEMAPHORE,每次读返回1,计数器-1,直到为0;如果不设置,就会一次性把值读出来,计数器清0

智能指针的拓展

因为Reactor里的_conns使用shared_ptr指向每一个连接,连接类里有字段指回Reactor,这个回指指针不能直接用shared_ptr

Reactor模式是一种事件驱动的编程模式,用于高效地处理并发IO操作,通过一个或多个事件循环(Event Loop)来监听和处理各种请求(如网络请求,定时器事件等),从而实现高效的并发处理,而无需为每个连接创建一个线程或进程

单进程Reactor:Redis

多进程Reactor:Nginx

下面这种直接把inbuffer+sockfd交给线程池,也就是Reactor进行epoll_wait,收到一个就绪事件就把fd交给从线程,从线程读取缓冲区,这样会有同步问题,一个fd可能就绪多次,分给多个线程,但是拿到早的数据线程可能晚处理完,这样写到outbuffer就会出现时序错误

下面主进程等待新连接,新连接到来,负载均衡向管道写,slaver进程检测到管道就绪,读取之后丢弃(写的这个值只是为了通知),回调acceptor,获取连接,把fd添加到自己的epoller,处理连接的就绪事件

主进程就通过管道负载均衡地告诉子进程连接来了

下面是多线程版本,线程池的队列存储收到的fd,问题在于,如果回调函数设置为从管道读取fd,那么也就是说从线程会等管道的事件就绪,但是读取fd肯定要放到自己的epoll,要等文件描述符的事件就绪,而等待队列要使用条件变量,那到底是在条件变量下等还是在epoll_wait下等

下面这种情况使用eventfd,子线程会把eventfd添加到epoll_wait,主线程把收到的fd放到队列,通过向eventfd写来通知从线程,从线程被唤醒,执行回调,读取fd放到epoll_wait

相关推荐
骇客野人1 小时前
Linux 全套实操方案(含目录详解、文件传输、日志、文件规范、环境变量、Java 应用部署运维)
java·linux·运维
_菜鸟果果1 小时前
高德地图 JS API 2.0 在国产 Linux/ARM 电脑上渲染失败 的排查与解决
linux·开发语言·javascript
GeW1 小时前
飞行汽车交付阿联酋,真正先“起飞”的是低空数据基座——红帽Linux与数据库高可用为什么成了低空运营的隐形跑道
linux
0+1112 小时前
Linux --DNS与ICMP
linux·运维·服务器
bjxiaxueliang2 小时前
一文自建STUN:在Ubuntu上分步搭建STUN服务
linux·运维·ubuntu
高旭的旭2 小时前
图解 Android 系统架构:从 App、Framework、HAL 到 Linux 驱动
android·linux·系统架构
小小、码农3 小时前
[特殊字符]【C++11】类的新功能全面解析:移动构造、移动赋值、default、delete、final 与 override
linux·开发语言·网络·c++
陈让然3 小时前
Ubuntu Podman 容器镜像构建
linux·ubuntu
探索云原生4 小时前
Ascend vNPU 实战:从原生 Docker 到 Ascend Docker Runtime
linux·ai·云原生·kubernetes·gpu