土法炼钢兴趣小组的算法知识备份

并发模型架构

目录

学会了 API 只是第一步,如何将 Libevent 组织成一个高并发、高吞吐的服务器架构才是关键。本篇将介绍几种主流的并发模型。

1. One Loop Per Thread (推荐)

One Loop Per Thread

这是目前最流行、性能最好的模型(Nginx, Memcached, Netty 都在用)。

1.1. 架构设计

1.2. 连接分发

如何将客户端连接分配给这些线程?

方案 A: SO_REUSEPORT (内核分发)

Linux 3.9+ 支持多个线程绑定到同一个端口(bind 时设置 SO_REUSEPORT)。 * 优点: 极其简单。所有线程都监听同一个端口,内核负责负载均衡(哈希分发)。 * 缺点: 某些老旧系统不支持。

方案 B: 主从 Reactor (应用层分发)

  1. Master 线程: 只负责 accept 新连接。
  2. 分发: Master 拿到新 socket fd 后,通过 Round-Robin 算法选择一个 Worker 线程。
  3. 通知: Master 通过管道(Pipe)或 SocketPair 将 fd 传递给 Worker。
  4. Worker 线程: 从管道读到 fd,将其注册到自己的 event_base 中,开始处理业务。

2. 单线程 Reactor + Worker 线程池

如果你的业务逻辑包含大量计算(CPU 密集型)或阻塞操作(如数据库查询),One Loop Per Thread 会导致 Event Loop 阻塞,影响其他连接。

2.1. 架构设计

  1. IO 线程: 单个(或少量)Libevent 线程只负责网络收发。
  2. Worker 线程池: 一个标准的线程池(如 Java 的 ThreadPoolExecutor)。
  3. 流程:
    • IO 线程收到数据 -> 封装成 Task -> 投递给 Worker 线程池。
    • Worker 线程处理业务 -> 产生结果 -> 通知 IO 线程发送。

2.2. 适用场景

3. Leader/Follower 模型

这是一种更古老的模型。 * 线程池: 一组线程共享同一个 event_base。 * 竞争: 所有线程都尝试获取 event_base 的锁来运行 epoll_wait。 * Leader: 抢到锁的线程成为 Leader,等待事件。 * Follower: 其他线程休眠。 * 缺点: 锁竞争激烈,且惊群效应(Thundering Herd)难以避免。Libevent 虽然支持多线程共享 base,但并不推荐这种用法。

4. 总结

模型 适用场景 复杂度 性能
One Loop Per Thread IO 密集型,短业务逻辑 (Redis, Nginx) 极高
Reactor + Thread Pool CPU 密集型,长业务逻辑 (Tomcat 模式)
Leader/Follower 特殊场景

对于大多数基于 Libevent 的 C/C++ 服务,One Loop Per Thread (配合 SO_REUSEPORT) 是首选方案。


上一篇: 04-architecture/threading.md - 线程安全与锁 下一篇: 04-architecture/process-pitfalls.md - 进程模型陷阱

返回 Libevent 专题索引


By .