胜,不妄喜;败,不遑馁;胸有激雷而面如平湖者,可拜上将军。 —— 春秋战国·孙武 《孙子兵法》
一、基础
Swoole就是披着PHP外衣的C程序,类似于Java等语言里面的高阶功能,如持久连接、异步通信、Websocket、多线程等。
Swoole是由C语言开发的PHP扩展类,由于有着C语言的优势,Swoole在内存管理、数据结构、通信协议解析等方面优势明显。它是一个面向生产环境的PHP异步网络通信引擎,使PHP开发人员可以编写高性能的异步并发TCP、UDP、Unix Socket、HTTP、WebSocket等服务。Swoole可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等领域。
二、实战
安装
- 下载源码包至
/usr/local/src目录下 - 解压
sudo tar -zxvf swoole-4.4.3.tgz - 切换目录
cd swoole-4.4.3 - 运行
sudo /usr/local/php/7.3/bin/phpize命令,生成configure可执行文件 - 运行配置
sudo ./configure --with-php-config=/usr/local/php/7.3/bin/php-config - 安装扩展
sudo make && sudo make install- 报错:
configure: error: C compiler cannot create executables,解决sudo xcodebuild -license accept
- 报错:
- 修改php.ini文件,增加
extension=/path/swoole.so - 重启php-fpm
- 查看是否安装成功
php7.3 -m,显示swoole则成功
- 下载源码包至
方法列表
/your_path/swoole-4.4.3/ext-src/stubs/php_swoole_server.stub.php
1 | <?php |
实战一:简易聊天室(面向过程)
- server.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36<?php
use Swoole\WebSocket\Server;
// old version, unsupported
// $ws_server = new swoole_websocket_server('192.168.1.169', 9502);
$ws_server = new Server("0.0.0.0", 9501, SWOOLE_BASE);
$ws_server->set([
'daemonize' => true
]);
$ws_server->on('open', function ($ws, $request) {
// file_put_contents( __DIR__ .'/log.txt' , $request->fd);
$ws->push($request->fd, "From Server!\n");
});
$ws_server->on('message', function ($ws, $frame) {
pushMessage($ws, $frame);
});
$ws_server->on('close', function ($ws, $fd) {
echo "client-{$fd} is closed\n";
});
$ws_server->start();
function pushMessage($ws, $frame){
// $data = $frame->data;
// $msg = file_get_contents( __DIR__ .'/log.txt');
// for ($i=1; $i<= $msg ; $i++) {
// $ws->push($fd, $frame->fd . ':' . $data);
// }
foreach ($ws->connections as $fd) {
$ws->push($fd, $frame->fd . ':' . $frame->data);
}
}- client.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36<html>
<head>
<title></title>
<meta charset="UTF-8">
<script type="text/javascript">
if(window.WebSocket){
var webSocket = new WebSocket("ws://localhost:9501");
webSocket.onopen = function (event) {
webSocket.send("From Client!");
};
webSocket.onmessage = function (event) {
var content = document.getElementById('content');
content.innerHTML = content.innerHTML.concat(
'<p style="margin-left:20px;height:20px;line-height:20px;">uid:'+event.data+'</p>'
);
}
var sendMessage = function(){
var data = document.getElementById('message').value;
webSocket.send(data);
}
}else{
console.log("您的浏览器不支持WebSocket");
}
</script>
</head>
<body>
<div style="width:600px;margin:0 auto;border:1px solid #ccc;">
<div id="content" style="overflow-y:auto;height:300px;"></div>
<hr/>
<div style="height:40px">
<input type="text" id="message" style="margin-left:10px;height:25px;width:450px;">
<button onclick="sendMessage()" style="height:28px;width:75px;">发送</button>
</div>
</div>
</body>
</html>实战二:简易聊天室(面向对象)
- server.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46<?php
use Swoole\WebSocket\Server;
class Chat
{
const HOST = '0.0.0.0';
const PART = 9052;
private $server = null;
public function __construct() {
// old version, unsupported
// $this->server = new swoole_websocket_server(self::HOST, self::PART);
$this->server = new Server("0.0.0.0", 9502, SWOOLE_BASE);
// $ref = new ReflectionClass($this->server);
// $data =$ref->getMethods();
// file_put_contents("a.json", json_encode($data));
// $data = $ref->getProperties();
// file_put_contents("b.json", json_encode($data));
$this->server->on('open', [$this, 'onOpen']);
$this->server->on('message', [$this, 'onMessage']);
$this->server->on('close', [$this, 'onClose']);
$this->server->start();
}
public function onOpen($server, $request) {
print_r($server->connection_info($request->fd));
echo $request->fd . '连接了' . PHP_EOL;//打印到我们终端
}
public function onMessage($server, $frame) {
echo $frame->fd . '来了,说:' . $frame->data . PHP_EOL;
foreach ($server->connections as $fd) {
$server->push($fd, json_encode(['no' => $frame->fd, 'msg' => $frame->data]));
}
echo "当前服务器共有".count($server->connections). "个连接\n";
}
public function onClose($server, $fd) {
echo $fd . '走了' . PHP_EOL;//打印到我们终端
}
}
$obj = new Chat();- client.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>聊天室</title>
<script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<textarea class="log" style="width: 300px; height: 300px;">
===聊天室===
</textarea><br/>
<input type="button" value="连接" onClick="connect()">
<input type="button" value="断开" onClick="disconnect()">
<input type="input" id="text">
<input type="button" value="发送" onClick="send()">
<script>
function connect() {
var url = 'ws://localhost:9502';
socket = new WebSocket(url);
socket.onopen = function () {
log1('连接成功')
}
socket.onmessage = function (msg) {
log(msg.data);
}
socket.onclose = function () {
log1('断开连接')
}
}
function disconnect() {
socket.close();
socket = null;
}
function log1(var1) {
$('.log').append(var1 + '\r\n');
}
function log(var1) {
var v = $.parseJSON(var1)
$('.log').append('uid:'+v['no']+',msg:'+v['msg']+ '\r\n');
}
function send() {
// var json = $('#text').val();
var json = JSON.stringify({
'type': 'php',
'msg': $('#text').val()
})
console.log(json)
socket.send(json);
}
</script>
</body>
</html>
三、参考
Swoole版本对比
一、版本总览表
| 版本 | 最低 PHP | 核心定位 | 重大特性 | 破坏性变更 | 适用场景 |
|---|---|---|---|---|---|
| Swoole 1.x | PHP5.3~7.0 | 异步回调时代 | 基础 Server(TCP/HTTP/WebSocket)、异步回调、Task、Timer、Table | 无协程,全回调编程 | 老项目、传统异步服务,现已淘汰 |
| Swoole 2.x | PHP7.0+ | 协程诞生 | 引入 C 栈协程,go() 关键字,协程 TCP 客户端 |
协程仅客户端,Server 还是回调;API 不稳定 | 早期协程尝鲜,不推荐生产 |
| Swoole 4.x | PHP7.1~8.1 | 协程黄金版(生产最广泛) | 1. 全协程 Server:Http/Http2/WebSocket/TCP 都支持协程 2. 一键协程化 Swoole\Runtime::enableCoroutine()3. 协程 MySQL/Redis/PostgreSQL 客户端、协程文件、协程 DNS 4. ProcessPool、多 Reactor 线程、max_concurrency、协程取消 Co::cancel 5. Swoole\Table 增强 |
4.0 起不再支持 PHP5;4.7 Table 不再支持数组式访问 $table[$key] |
Hyperf、EasySwoole 等主流框架;绝大多数线上业务,存量主力 |
| Swoole 5.x | PHP8.1+ | 精简重构版 | 1. 强类型声明,全 API 参数返回值类型 2. swoole-cli 独立二进制(无需系统 PHP) 3. 协程性能优化、内存优化 4. 支持 io_uring |
重大移除:删除内置协程 MySQL/Redis/PostgreSQL 客户端,不再维护;废弃大量旧 API;移除旧异步回调客户端;不再支持 PHP7 | 新项目,愿意使用原生 PDO/Redis 扩展 + Runtime 协程化;需要独立 swoole-cli |
| Swoole 6.x | PHP8.2~8.4 | 现代化新版本 | 1. 原生 Fiber 支持(PHP8.1+ zend fiber) 2. io_uring 成熟、多线程池重构 3. 完善协程调试、异常链路优化 4. 更好 PHP8 新特性兼容 |
继续清理遗留旧 API,逐步弱化 C 栈协程,主推 PHP Fiber | 新项目、追求 PHP 原生特性、io_uring 高性能场景 |
二、分版本详细核心升级 & 区别
✅ Swoole 1.x(回调时代,古董)
- 编程模型:事件回调,没有协程,写代码是
onReceive/onRequest回调,遇到 IO 必须异步非阻塞。 - 能力:TCP/UDP/HTTP/WebSocket 服务器、Task 异步任务、毫秒定时器、Swoole\Table 共享内存。
- 痛点:回调地狱,代码难维护;阻塞 IO 直接卡死 Reactor;PHP 版本老旧。
一句话:没有协程的 Swoole,现在几乎没人用。
✅ Swoole 2.x:协程初试
- 里程碑:首次引入协程(ucontext C 栈协程),
go(function(){})。 - 限制:Server 本身仍然是回调模式,协程只可以在回调内部创建,只能用协程 TCP 客户端;没有一键协程化。
- 坑:协程生态不全,不稳定,很多阻塞函数无法挂起。
一句话:协程客户端可用,Server 不能全协程,属于过渡版本。
✅ Swoole 4.x(最重要,生产首选)
分水岭版本,PHP 协程生态成熟,Hyperf、EasySwoole、Mix 所有主流 Swoole 框架基于 4.4~4.8
- 全协程服务器:HttpServer 可以直接在
onRequest里写同步风格代码,底层自动协程调度,告别回调地狱。 - Runtime 一键协程化
Swoole\Runtime::enableCoroutine():原生file_get_contents、PDO、mysqli、stream 全部自动变成协程非阻塞,不用改业务代码。 - 内置全套协程客户端:
Swoole\Coroutine\MySQL / Redis / PostgreSQL,高性能。 - 新组件:ProcessPool、连接池配套能力、Http2、WebSocket 协程、协程 DNS、协程文件读写。
- 4.7 关键变更:Swoole\Table 不能再用数组写法
$table['key'],只能用get/set;新增Co::cancel()协程取消。 - 4.8:SSL 握手协程化,解决 TLS 握手阻塞 Reactor 问题。
4.x 内部小版本差异
- 4.0:协程 HttpServer 正式稳定
- 4.4:Runtime 一键协程化稳定,Hyperf 起点版本
- 4.6:支持 PHP8
- 4.7:Table 数组访问废弃、协程取消
- 4.8:TLS 协程化、大量稳定性修复,4.8 是 4.x 系列最终稳定推荐版
一句话:4.x = 协程能力最强、生态最完善、文档/案例最多;缺点:内置协程客户端在 5.0 被砍掉。
✅ Swoole 5.x:破坏性精简重构
设计理念:不再维护自研数据库协程客户端,交给 PHP 原生扩展 + Runtime 协程化
- 移除:
Swoole\Coroutine\MySQL、Redis、PostgreSQL内置协程客户端(重大 break change!)业务改用原生 pdo/redis 扩展 + Runtime 自动协程化
- 强类型:所有 API 增加严格参数/返回值类型,PHP8 强类型体系对齐
- swoole-cli:独立静态二进制,打包 PHP+Swoole,不依赖宿主机 PHP 环境,部署很方便
- 内核优化:内存泄漏修复、协程栈优化、支持 io_uring
- 最低 PHP 8.1,彻底砍掉 PHP7 支持
升级大坑:4.x 业务如果大量直接使用
Coroutine\Redis/MySQL,迁移 5.x 必须改代码,重写连接池。
✅ Swoole 6.x:Fiber 时代
- 支持 PHP 原生
Zend Fiber作为协程后端(替代老的 ucontext C 栈协程),可以自由切换协程实现。 - io_uring 成熟,提升高并发 IO 性能。
- 协程调试、异常栈、Xdebug 支持大幅改善。
- 持续清理遗留废弃 API,进一步简化内核。
三、重要分支说明:OpenSwoole(原 Swoole fork)
很多人会搞混:OpenSwoole 是社区 fork,版本号独立(22/24/26),不是 swoole-src 原版。
- 原版 Swoole:
swoole/swoole-src,版本 1/2/4/5/6,swoole PECL 包 - OpenSwoole:
openswoole/openswoole,版本 22+,pecl 包名叫openswoole,命名空间OpenSwoole\ - 两者 API 大体相似,但内核、废弃策略、PHP 支持不一样,不要混用。
四、选型建议(生产环境)
- 老项目 / Hyperf、EasySwoole 存量:Swoole 4.8,生态成熟稳定,不轻易升 5
- 新项目,PHP8.1+,不想依赖 swoole 内置数据库客户端:Swoole 5.x
- 追求 PHP 原生 Fiber、io_uring、最新 PHP8.3/8.4:Swoole 6.x
- 新项目尽量不要用 OpenSwoole,除非明确需要它的特殊特性,生态资料少
五、核心差异一句话总结
- 1.x:只有异步回调,无协程
- 2.x:协程来了,但只有客户端协程,Server 还是回调
- 4.x:协程黄金时代,全协程 Server + 内置全套协程数据库客户端 + Runtime 一键协程化,框架生态爆发
- 5.x:砍掉内置数据库协程客户端,拥抱原生 PHP 扩展,强类型,swoole-cli
- 6.x:支持 PHP 原生 Fiber,io_uring,逐步淘汰旧 C 栈协程
Windows11 + PHP + Go + Node开发环境

PHP之Swoole和Go对比

学习路径
- 从 PHP → Swoole:你的业务代码、Composer 生态、Laravel 经验全部复用,两周能开始产出。
- 从 PHP → Go:3–6 个月沉没成本,而且你得同时重学类型系统、错误处理(Go 没有异常,只有 error 返回值,这个思维转换对 PHP 程序员是最难的一关)、构建工具链。你沉淀了多年的中控系统业务知识(代理账号、余额划拨、快手平台对接)全部无法迁移。
- 从 Swoole → Go:一周。因为 Reactor、协程调度器、Channel、多进程模型这套东西是共享的,Swoole 6.x 的协程 API 和 Go 的 goroutine + channel 在心智模型上是同一套,只是语法糖不同。
Swoole有而Go给不了的东西:Swoole\Process多进程模型+Swoole\Table跨进程共享内存。
- Go 的 goroutine 是单线程内的协程,要跨线程共享状态你得自己用 sync.Map 加锁,或者引入 etcd / Redis 做外部状态。
- Swoole 的 Table 是零锁、跨进程、内核内存映射的,用起来就是像操作数组一样简单。
Swoole学习(Windows+WSL)
一、流程
- 安装wsl
- wsl –install
- wsl –set-default-version 2
- 安装Ubuntu24:wsl –install -d Ubuntu-24.04
- 进入Ubuntu24
- 同步代码
1 | mkdir -p ~/dev |
- 安装运行环境:bash setup-swoole.sh
- 验证版本
1 | php -v | head -1 # 应显示 PHP 8.4.x |
- 验证:php week1/01-sync-vs-co.php
1 | 【同步】20 个请求各等 1 秒 |