协程负载均衡是指在协程环境下对后端服务请求进行分发调度,而非协程自身负载均衡;swoole未内置该功能,需自行实现调度逻辑或借助组件,如用coroutine\pool+原子计数器实现协程安全的轮询调度,并确保连接复用与错误隔离。

协程负载均衡不是指“让协程自己去负载均衡”,而是指在协程环境下,**对后端服务(如 MySQL、Redis、HTTP API、自定义 TCP 服务等)的请求做分发调度**。Swoole 协程本身不提供内置的负载均衡器,你需要自己实现调度逻辑或借助已有组件。
为什么不能直接用 Swoole\Coroutine\Http\Client 做负载均衡
这个客户端只是单次请求工具,不维护连接池、不记录健康状态、也不支持策略切换。如果你硬写一堆 if-else 切地址,很快就会遇到:连接泄漏、超时未重试、故障节点还在被轮询、并发下计数器错乱等问题。
-
Swoole\Coroutine\Http\Client每次 new 都是新实例,connect()和send()是阻塞调用(协程内),但没自动重试或降级机制 - 手动管理连接复用(比如用
pool)需要自己控制生命周期,容易close()漏掉或重复 close - 没有内置心跳检测,挂掉的后端会持续被选中,直到你手动剔除
用 Swoole\Coroutine\Pool + 轮询策略实现基础调度
这是最轻量、可控性最强的方式,适合中小规模后端列表(比如 3–5 个 Redis 实例或 MySQL 从库)。核心是把连接池和调度逻辑解耦:
- 每个后端地址配一个独立的
Swoole\Coroutine\Pool,池内管理该地址的连接复用 - 调度器只负责返回下一个可用的
pool对象,不碰具体 I/O - 轮询计数器必须是协程安全的——用
atomic或Channel同步,别用全局变量$current
示例片段:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
$backends = [
['host' => '10.0.0.1', 'port' => 6379],
['host' => '10.0.0.2', 'port' => 6379],
['host' => '10.0.0.3', 'port' => 6379],
];
$counter = new Swoole\Atomic(0);
function getNextPool(): Swoole\Coroutine\Pool
{
global $backends, $counter;
$idx = $counter->add(1) % count($backends);
return getOrCreatePool($backends[$idx]);
}
function getOrCreatePool(array $addr): Swoole\Coroutine\Pool
{
static $pools = [];
$key = $addr['host'] . ':' . $addr['port'];
if (!isset($pools[$key])) {
$pools[$key] = new Swoole\Coroutine\Pool(function () use ($addr) {
$redis = new Swoole\Coroutine\Redis();
if (!$redis->connect($addr['host'], $addr['port'])) {
throw new RuntimeException("Connect failed: {$addr['host']}:{$addr['port']}");
}
return $redis;
}, 32, 10);
}
return $pools[$key];
}
调用时:$pool->get() → 执行操作 → $pool->put($redis)。注意:务必 put 回池,否则连接耗尽。
何时该换 swoole-proxy 或自研代理层
当你的场景出现以下任一情况,就别硬撑着在业务协程里做调度了:
- 后端节点动态增减(比如注册中心通知变更)
- 需要加权、最少连接数、响应时间加权等策略,而非简单轮询
- 要求健康检查(TCP 探活 / HTTP
/health)、自动摘除、恢复探测 - 多个业务模块共用同一套后端集群,希望统一治理
这时应该抽离为独立的代理服务,比如用 Swoole\ProxyServer(注意:它仅支持 TCP 层转发,不解析应用层协议),或者基于 Swoole\Server + 协程客户端自己写一层反向代理。关键点是:代理进程和业务进程分离,故障隔离,配置热更新才可行。
真正容易被忽略的不是算法,而是连接生命周期和错误传播——一个后端挂了,别让整个协程栈卡死;一次 recv() 超时,要能快速 failover 而不是等满所有重试。调度器永远只是骨架,健壮性藏在错误处理和资源回收里。










