PHP异步编程新范式:Swoole协程实现高并发微服务架构
一、Swoole协程核心原理
基于IO多路复用的轻量级线程技术:
// 基础协程示例
Corun(function() {
go(function() {
echo "协程1开始n";
Co::sleep(1);
echo "协程1结束n";
});
go(function() {
echo "协程2开始n";
Co::sleep(0.5);
echo "协程2结束n";
});
});
// 输出顺序:
// 协程1开始
// 协程2开始
// 协程2结束
// 协程1结束
核心优势:同步编码、异步IO、零回调地狱、高并发
二、微服务架构实战
1. 协程HTTP客户端
// 并发请求多个API
Corun(function() {
$results = [];
$wg = new CoWaitGroup();
$apis = [
'/user/123',
'/orders/123',
'/products'
];
foreach ($apis as $api) {
$wg->add();
go(function() use ($api, &$results, $wg) {
$cli = new CoHttpClient('api.example.com', 443, true);
$cli->set(['timeout' => 3]);
$cli->get($api);
$results[$api] = $cli->body;
$wg->done();
});
}
$wg->wait();
print_r($results);
});
2. 协程MySQL连接池
// 协程安全连接池
class CoroutineMysqlPool {
private $pool;
private $config;
public function __construct($config, $size = 10) {
$this->config = $config;
$this->pool = new CoChannel($size);
for ($i = 0; $i connect($config);
$this->pool->push($mysql);
}
}
public function get(): SwooleCoroutineMySQL {
return $this->pool->pop();
}
public function put($mysql): void {
$this->pool->push($mysql);
}
}
// 使用示例
$pool = new CoroutineMysqlPool([
'host' => '127.0.0.1',
'user' => 'root',
'password' => '',
'database' => 'test'
]);
go(function() use ($pool) {
$mysql = $pool->get();
$result = $mysql->query('SELECT * FROM users');
$pool->put($mysql);
});
三、电商系统实战案例
1. 秒杀系统实现
// 协程版秒杀服务
class SeckillService {
private $redis;
private $mysqlPool;
public function __construct() {
$this->redis = new CoRedis();
$this->redis->connect('127.0.0.1', 6379);
$this->mysqlPool = new CoroutineMysqlPool([
'host' => '127.0.0.1',
'user' => 'root',
'password' => '',
'database' => 'shop'
]);
}
public function handleRequest($userId, $productId) {
// 1. 库存预减
$stockKey = "seckill:stock:{$productId}";
$stock = $this->redis->decr($stockKey);
if ($stock redis->incr($stockKey);
return false;
}
// 2. 去重检查
$orderKey = "seckill:orders:{$productId}";
if ($this->redis->sIsMember($orderKey, $userId)) {
$this->redis->incr($stockKey);
return false;
}
// 3. 创建订单
$mysql = $this->mysqlPool->get();
try {
$mysql->begin();
// 扣减真实库存
$mysql->query("UPDATE products SET stock = stock - 1 WHERE id = {$productId} AND stock > 0");
// 创建订单
$orderId = uniqid();
$mysql->query("INSERT INTO orders VALUES(...)");
// 记录用户购买
$this->redis->sAdd($orderKey, $userId);
$mysql->commit();
return $orderId;
} catch (Exception $e) {
$mysql->rollback();
$this->redis->incr($stockKey);
return false;
} finally {
$this->mysqlPool->put($mysql);
}
}
}
四、生产环境最佳实践
- 协程数量控制:使用set([‘max_coroutine’ => 10000])
- 连接池管理:为不同服务建立独立连接池
- 错误处理:为每个协程添加try-catch
- 性能监控:使用Swoole Dashboard观察协程状态
- 平滑重启:配置reload_async实现不停服更新