开源项目C++ Workflow学习
📅 2026/7/5 2:33:35
👁️ 阅读次数
📝 编程学习
Workflow是一个面向高并发网络服务的异步编程框架。它最核心的思想是:
把所有异步操作抽象成任务(Task),再把任务组织成工作流(Workflow)。
很多传统 C++ 网络库只负责网络 I/O,而 Workflow 希望把网络、文件、计算、定时器等全部统一到同一种任务模型中。
一、Workflow 的主要特点
1. 全异步、非阻塞
Workflow 中几乎所有 I/O 都是异步的:
- HTTP
- HTTPS
- Redis
- MySQL
- DNS
- 文件 I/O
例如:
WFHttpTask *task = WFTaskFactory::create_http_task( "http://www.baidu.com", 0, 0, callback); task->start();调用start()后立即返回。
真正的数据收发在后台线程中完成。
当任务结束时:
callback(task);才会被自动调用。
因此:
- 不会阻塞线程
- 不需要手动管理 epoll
- 不需要自己写事件循环
2. 串行任务流(Series)
Workflow 最大特色之一。
多个异步任务可以写成:
HTTP请求 ↓ 解析数据 ↓ MySQL查询 ↓ Redis缓存 ↓ 返回客户端代码:
WFHttpTask *t1 = ... WFMySQLTask *t2 = ... series_of(t1)->push_back(t2);框架保证:
t1完成 ↓ 执行回调 ↓ 自动执行t2开发者不需要自己维护状态机。
传统异步编程:
回调嵌套地狱Workflow:
任务链3. 并行任务(ParallelWork)
多个任务可同时执行:
ParallelWork *pw = Workflow::create_parallel_work(cb); pw->add_series(s1); pw->add_series(s2); pw->add_series(s3); pw->start();框架自动等待:
所有任务完成 ↓ 执行最终回调非常适合:
- 多数据库查询
- 聚合服务
- 微服务调用
例如:
用户信息 订单信息 推荐信息同时请求。
4. 高性能
Workflow 底层采用:
- epoll(Linux)
- kqueue(BSD/macOS)
实现单机百万连接。
特点:
Reactor + 线程池并且:
- 无锁设计较多
- 连接池
- 内存池
- 零拷贝
都做了优化。
5. 内置协议丰富
支持:
| 协议 | 支持 |
|---|---|
| HTTP/HTTPS | √ |
| Redis | √ |
| MySQL | √ |
| Kafka | √ |
| DNS | √ |
| 文件IO | √ |
开发者不需要再找第三方客户端。
6. 统一任务模型
所有任务都继承自:
SubTask包括:
网络任务 文件任务 定时器任务 计算任务统一接口:
task->start();二、Workflow 的总体架构
框架大致如下:
用户代码 │ WFTaskFactory │ 创建各种Task │ +-------------+ | SubTask | +-------------+ │ +------------+------------+ │ │ SeriesWork ParallelWork │ │ +------------+------------+ │ Scheduler │ +---------+---------+ │ │ Reactor线程 Executor线程 │ │ epoll 计算/回调三、核心实现机制
1. Reactor 模型
Workflow 使用经典:
Reactor + epoll架构。
每个 Reactor 线程:
while (true) { epoll_wait(); 处理可读事件; 处理可写事件; 超时处理; }流程:
socket可读 ↓ epoll通知 ↓ Reactor线程处理 ↓ 数据读入缓冲区 ↓ 任务状态推进Reactor 线程只做:
网络IO 状态切换不会执行耗时业务逻辑。
2. 状态机驱动
每个网络任务实际上都是一个状态机。
例如 HTTP:
INIT ↓ DNS ↓ CONNECT ↓ SEND ↓ RECV ↓ PARSE ↓ DONE源码中大量存在:
switch(state) { case ST_CONNECT: ... case ST_RECV: ... }网络事件不断推动状态机向前运行。
3. SeriesWork
源码中:
SeriesWork内部维护:
std::queue<SubTask *>执行流程:
当前任务完成 ↓ done() ↓ SeriesWork::pop() ↓ 启动下一个任务所以:
series_of(task)->push_back(next);只是把任务加入队列。
4. ParallelWork
内部维护:
剩余任务计数器每个 Series 完成:
counter--当:
counter == 0触发最终回调。
类似:
CountDownLatch5. Executor 线程池
网络线程不能执行:
数据库解析 JSON解析 压缩 业务逻辑否则会阻塞整个 Reactor。
因此:
IO线程 ↓ 任务完成 ↓ 投递到Executor线程池 ↓ 执行回调实现:
生产者消费者模型大致:
while (true) { task = queue.pop(); task->dispatch(); }6. 连接池
对于:
HTTP KeepAlive MySQL RedisWorkflow 内置连接池。
连接不会每次:
connect() close()而是:
获取空闲连接 ↓ 使用 ↓ 归还池中极大减少系统调用开销。
四、为什么 Workflow 性能高?
原因主要有:
- 全异步非阻塞
- epoll 事件驱动
- Reactor 与业务线程分离
- 连接复用
- 减少线程切换
- 大量无锁/低锁设计
- 统一任务调度模型
- 状态机驱动而不是阻塞等待
编程学习
技术分享
实战经验