C++ 服务端进阶(四)—— 多 Reactor + 协程:真正的高并发模型(融合版)
一、这一篇到底在做什么到目前为止你已经分别完成了✔ 第一篇Connection结构抽象✔ 第二篇多 Reactor并发模型✔ 第三篇单 Reactor 协程执行模型但这三者是分开的能力结构 ✔ 并发 ✔ 执行 ✔ 真正的高并发服务端还差最后一步把并发模型多 Reactor和执行模型协程融合本篇目标构建这样一套模型Main Reactoraccept ↓ Sub Reactor线程 协程执行一句话总结本篇多线程负责“并发”协程负责“执行”二、最终架构图必须理解Main Reactor主线程 ↓ accept ┌──────────────┬──────────────┬──────────────┐ ↓ ↓ ↓ Sub Reactor1 Sub Reactor2 Sub Reactor3 (线程1) (线程2) (线程3) ↓ ↓ ↓ coroutine coroutine coroutine三、和第三篇的本质区别第三篇单线程一个 Reactor 多协程 特点✔ 无锁❌ 只能用一个 CPU第四篇本篇多 Reactor多线程 每个 Reactor 内部用协程 特点✔ 多核利用✔ 无锁连接不跨线程✔ 高并发四、核心设计原则非常重要原则 1连接只属于一个 Reactorfd → 固定 Reactor 不跨线程 → 不需要锁原则 2每个线程独立事件循环线程1 → epoll1线程2 → epoll2原则 3协程只在所属 Reactor 线程执行 不跨线程恢复原则 4Main Reactor 只做 accept 不处理业务五、项目结构最终版. ├── Task.h ├── Reactor.h / Reactor.cpp ├── ReactorThread.h / ReactorThread.cpp ├── ReactorThreadPool.h / ReactorThreadPool.cpp ├── SocketUtil.h / SocketUtil.cpp ├── Server.h / Server.cpp └── main.cpp六、核心代码实现1️⃣ ReactorThread线程 ReactorReactorThread.h#ifndef REACTOR_THREAD_H #define REACTOR_THREAD_H #include Reactor.h #include thread #include memory class ReactorThread { public: ReactorThread(); ~ReactorThread(); Reactor* getReactor(); void start(); private: std::unique_ptrReactor reactor_; std::thread thread_; }; #endifReactorThread.cpp#include ReactorThread.h ReactorThread::ReactorThread() { reactor_ std::make_uniqueReactor(); } ReactorThread::~ReactorThread() { if (thread_.joinable()) { thread_.join(); } } Reactor* ReactorThread::getReactor() { return reactor_.get(); } void ReactorThread::start() { thread_ std::thread([this]() { reactor_-loop(); }); }2️⃣ ReactorThreadPoolReactorThreadPool.h#ifndef REACTOR_THREAD_POOL_H #define REACTOR_THREAD_POOL_H #include ReactorThread.h #include vector #include memory class ReactorThreadPool { public: explicit ReactorThreadPool(int size); void start(); Reactor* getNextReactor(); private: std::vectorstd::unique_ptrReactorThread threads_; int index_; }; #endifReactorThreadPool.cpp#include ReactorThreadPool.h ReactorThreadPool::ReactorThreadPool(int size) : index_(0) { for (int i 0; i size; i) { threads_.emplace_back(std::make_uniqueReactorThread()); } } void ReactorThreadPool::start() { for (auto t : threads_) { t-start(); } } Reactor* ReactorThreadPool::getNextReactor() { Reactor* reactor threads_[index_]-getReactor(); index_ (index_ 1) % threads_.size(); return reactor; }3️⃣ Server协程版本Server.h#ifndef SERVER_H #define SERVER_H #include Task.h class Reactor; DetachedTask handleConnection(int fd, Reactor reactor); #endifServer.cpp#include Server.h #include Reactor.h #include unistd.h #include errno.h #include iostream #include string DetachedTask handleConnection(int fd, Reactor reactor) { std::string writeBuffer; char buffer[1024]; while (true) { co_await reactor.readable(fd); while (true) { ssize_t n read(fd, buffer, sizeof(buffer)); if (n 0) { writeBuffer.append(buffer, n); } else if (n 0) { reactor.removeFd(fd); close(fd); co_return; } else { if (errno EAGAIN) break; reactor.removeFd(fd); close(fd); co_return; } } while (!writeBuffer.empty()) { co_await reactor.writable(fd); ssize_t wn write(fd, writeBuffer.data(), writeBuffer.size()); if (wn 0) { writeBuffer.erase(0, wn); } else if (errno ! EAGAIN) { reactor.removeFd(fd); close(fd); co_return; } } } }4️⃣ 主线程 accept 分发main.cpp#include Reactor.h #include ReactorThreadPool.h #include SocketUtil.h #include Server.h #include sys/socket.h #include iostream int main() { int listenFd createListenFd(8080); ReactorThreadPool pool(4); pool.start(); Reactor mainReactor; std::cout server running :8080 std::endl; while (true) { int clientFd accept4(listenFd, nullptr, nullptr, SOCK_NONBLOCK); if (clientFd 0) { Reactor* subReactor pool.getNextReactor(); handleConnection(clientFd, *subReactor); } } return 0; }七、最核心执行流程必须理解客户端连接 ↓ Main Reactor accept ↓ 选择 Sub Reactor ↓ 启动协程 handleConnection ↓ co_await readable → 挂起 ↓ epoll_wait ↓ fd ready ↓ Reactor 恢复协程 ↓ 继续执行 read/write八、这一篇真正的价值你现在掌握的是epoll事件 Reactor调度 多线程并发 协程执行 组合起来就是现代高并发服务端模型九、总结如果说前三篇是在分别建立结构、并发和执行模型那么本篇完成的是这三者的真正融合。在这个模型中多 Reactor 提供并发能力Reactor 提供事件调度能力协程提供执行模型三者结合构成了现代高性能服务端的核心运行方式。十、下一篇第五篇 《Connection 协程面向对象的异步模型》Connection 协程工程级写法你会把Connection coroutine彻底融合成class Connection { coroutine run(); };单 Reactor 协程是“执行模型”多 Reactor 协程才是“架构模型”
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2488413.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!