系列文章目录
第四章 网络设计与redis、memcached、nginx组件(一)
第五章 网络设计与redis、memcached、nginx组件(二)
### 文章目录
- [系列文章目录](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [@[TOC](文章目录)](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [前言](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [一、reactor模型?](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [二、Reactor 开发](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [1.建立连接](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [三、典型reactor 模型](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [单reactor 模型](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [典型 readis](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [radis 中优化](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [多reactor 模型 多线程(one eventloop per thread)](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [典型 memcached](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [为什么支持多线程 多reactor](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [多reactor 模型 多进程 (one eventloop per process)](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [典型引用 nginx](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [nginx流程](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
- [总结](#文章目录 系列文章目录 @TOC 前言 一、reactor模型? 二、Reactor 开发 1.建立连接 三、典型reactor 模型 单reactor 模型 典型 readis radis 中优化 多reactor 模型 多线程(one eventloop per thread) 典型 memcached 为什么支持多线程 多reactor 多reactor 模型 多进程 (one eventloop per process) 典型引用 nginx nginx流程 总结)
前言
此文章主要是是介绍一下reactor 模型和典型的reactor模型开源软件介绍分析。
一、reactor模型?
Reactor 模型的核心就是把对网络IO的处理转变成对事件的处理。 把网络IO检测功能交由IO多路复用(epoll select poll)实现检测fd 状态,针对时间的处理进行IO操作,不同职能事件通过不同的事件函数处理。
IO多路复用的主要功能是检测多条链路的状态(可读 可写 错误 断开等),但不具备具体IO操作的功能(比如读写数据)。IO多路复用都是同步网络IO ,常见的IO多路复用器有select、poll,epoll,他们是对IO的管理,检测接入的IO,触发IO事件;注意这三个都是同步IO。

之所以把IO就绪检测的功能交由IO多路复用器,是因为对于服务端而言,某一时刻只有少量的连接有数据交互,如果让IO函数自己检测,在阻塞IO时,每个连接都需要一个线程;非阻塞IO时,每个连接都需要通过while在应用层进行检测。
二、Reactor 开发
1.建立连接
代码如下(示例):
c
//1.服务端作为被动建立连接
// listenfd 注册监听listenfd 的事件
struct epoll_event ev;
ev.events = EPOLLIN;
ev.date.fd = listenfd;
epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);
// 触发listenfd 的读事件,调用accept 接受新的连接
clientfd = accept(listen_fd,(struct sockaddr *)&addr, sizeof(addr))
ev.events = EPOLLIN;
ev.date.fd = clientfd;
epoll_ctl(epfd, EPOLL_CTL_ADD,clientfd, &ev);
.//服务端主动
// 1. 创建 socket 建立连接
int connectfd = socket(AF_INET, SOCK_STREAM, 0);
connect(connectfd, (struct sockaddr *)&addr,
sizeof(addr));
// 2. 注册监听 connectfd 的写事件
struct epoll_event ev;
ev.events = EPOLLOUT;
ev.data.fd = connetfd
epoll_ctl(efd, EPOLL_CTL_ADD, connectfd, &ev);
// 3. 当 connectfd 写事件被触发,连接建立成功
if (status == e_connecting && e->events &
EPOLLOUT) {
status == e_connected;
// 这里需要把写事件关闭
epoll_ctl(epfd, EPOLL_CTL_DEL, connectfd,
NULL);
}
三、典型reactor 模型
单reactor 模型

典型 readis
redis命令行采用了单reactor 网络事件模型,在启动时会创建一个I/O多路复用的事件处理器(即reactor)用于监听链路的状态,然后将所有客户端请求都注册到该事件处理器中。当有新连接到达或者已有连接有数据可读写时,事件处理器就会触发相应的回调函数进行处理。
由于redis是单线程运行的,因此只需要一个reactor即可满足其并发处理需求。通过合理地利用CPU资源和异步非阻塞IO技术,redis可以实现高效地处理大量并发请求。
radis 中优化
需要注意的是,当Redis遇到某些长时间执行的命令时,可能会导致其他请求被阻塞而影响整个系统性能。比如三个客户端同时向服务端发送数据,服务端是按先后顺序接收处理。这种就会出现如果先到的数据处理比较耗时,会导致后续客户端出现饥饿现象。优化方式是:
1、如果IO耗时,把IO操作放到IO线程池处理,主线程处理computer。read 、write、encode 、decode等丢入线程池处理
2、如果computer耗时,采用分治思想或者不同时间复杂度的算法
多reactor 模型 多线程(one eventloop per thread)
模型图
典型 memcached
memcached是一个基于事件驱动的内存缓存服务器,它使用多个reactor来处理并发连接。开启多个线程,每个线程中都有一个独立的reactor 对象。
为什么支持多线程 多reactor
memcached 也是kv类型的数据库,但是value 支持数据结构比较单一不支持多种数据结构, 对于锁的处理比较简单。
具体来说,memcached使用一个主线程和多个工作线程。每个工作线程都有自己的reactor,用于处理客户端连接和请求。当有新连接到达时,主线程(master epoll )会将新的fd分配给某个工作线程,并且该工作线程的reactor会负责处理这个连接的所有事件。
多reactor 模型 多进程 (one eventloop per process)
模型
典型引用 nginx
nginx是一个基于事件驱动的服务器,它通过多个reactor处理并发连接,它采用多进程的方式(master、slave worker)模型
具体来说,Nginx使用一个主进程(master)和多个worker进程。每个worker进程都有自己的reactor队形,用于处理客户端连接和请求。当有新连接到达时,主进程会将其分配给某个worker进程,并且该worker进程的reactor会负责处理这个连接的所有事件。
在默认情况下,Nginx的worker进程数等于CPU核心数。
nginx流程
Master process 创建的时候会监听listenfd, 然后在fork 出work 进程, work 进程当中都会有一个listenfd 的备份。每个work 进程会创建自己的epoll 对象。并且把listenfd交割epoll 对象管理. 多个进程都监听了listenfd 的读事件,如果listenfd 的全链接队列当中,加入节点的时候,他就会给每一个epoll 对象发送信号,每个epoll 对象都会去触发读事件。这样就产生了惊群现象。在用户层解决这个问题,通过在work 进程当中添加共享锁的方式解决。
总结
单线程单reactor模型,典型是radis 可以把IO放入线程池,也可以把业务计算部分放入线程池。通过回调的方式处理
多线程多reactor模型 如果业务之间交互比较多,但加锁简单,可以用多线程memcached
多进程多reactor模型 如果业务之间交互比较少,可以用多进程ngnix