经过数月的开发和测试工作,Swoole v6 的第一个版本终于发布了。
Swoole v6 将为 PHP 带来稳定可靠、生产可用的多线程方案。欢迎各位进行试用,为我们提交测试报告和问题反馈。
新特性:
- 支持多线程模式,当
php
是zts
模式,开启--enable-swoole-thread
即可使用 - 新增线程管理类
Swoole\Thread
@matyhtf - 新增线程锁
Swoole\Thread\Lock
@matyhtf - 新增线程原子计数
Swoole\Thread\Atomic
,Swoole\Thread\Atomic\Long
@matyhtf - 新增安全并发容器
Swoole\Thread\Map
,Swoole\Thread\ArrayList
,Swoole\Thread\Queue
@matyhtf - 文件异步操作支持
iouring
作为底层引擎 @matyhtf @NathanFreeman - 升级
Boost Context
版本到1.84
,现在,龙芯CPU
也能够支持协程了 @NathanFreeman
示例:
创建线程:
use Swoole\Thread;
$args = Thread::getArguments(); // 如果是主线程,$args 为空,如果是子线程,$args 不为空
$c = 4;
if (empty($args)) {
# 主线程
for ($i = 0; $i < $c; $i++) {
$threads[] = new Thread(__FILE__, $i);
}
for ($i = 0; $i < $c; $i++) {
$threads[$i]->join();
}
} else {
# 子线程
echo "Thread #" . $args[0] . "\n";
while (1) {
sleep(1);
file_get_contents('https://www.baidu.com/');
}
}
线程 + 服务端(异步风格)
use Swoole\Process;
use Swoole\Thread;
use Swoole\Http\Server;
$http = new Server("0.0.0.0", 9503, SWOOLE_THREAD);
$http->set([
'worker_num' => 2,
'task_worker_num' => 3,
'bootstrap' => __FILE__,
// 通过init_arguments实现线程间的数据共享。
'init_arguments' => function () use ($http) {
$map = new Swoole\Thread\Map;
return [$map];
}
]);
$http->on('Request', function ($req, $resp) use ($http) {
$resp->end('hello world');
});
$http->on('pipeMessage', function ($http, $srcWorkerId, $msg) {
echo "[worker#" . $http->getWorkerId() . "]\treceived pipe message[$msg] from " . $srcWorkerId . "\n";
});
$http->addProcess(new Process(function () {
echo "user process, id=" . Thread::getId();
sleep(2000);
}));
$http->on('Task', function ($server, $taskId, $srcWorkerId, $data) {
var_dump($taskId, $srcWorkerId, $data);
return ['result' => uniqid()];
});
$http->on('Finish', function ($server, $taskId, $data) {
var_dump($taskId, $data);
});
$http->on('WorkerStart', function ($serv, $wid) {
// 通过Swoole\Thread::getArguments()获取配置中的init_arguments传递的共享数据
var_dump(Thread::getArguments(), $wid);
});
$http->on('WorkerStop', function ($serv, $wid) {
var_dump('stop: T' . Thread::getId());
});
$http->start();
Thread + Coroutine 在线程中使用协程
use Swoole\Thread;
$args = Thread::getArguments(); // If it is main thread, the $args is empty; if it is a child thread, the $args is not empty.
$c = 4;
if (empty($args)) {
# main thread
for ($i = 0; $i < $c; $i++) {
$threads[] = new Thread(__FILE__, $i);
}
for ($i = 0; $i < $c; $i++) {
$threads[$i]->join();
}
} else {
# child thread x 4
echo "Thread #" . $args[0] . "\n";
Co\run(function() {
while (1) {
sleep(1);
Co\go(function () {
file_get_contents('https://www.baidu.com/');
});
}
});
}
并发 Map
use Swoole\Thread;
$args = Thread::getArguments();
if (empty($args)) {
$array = [
'a' => random_int(1, 999999999999999999),
'b' => random_bytes(128),
'c' => uniqid(),
'd' => time(),
];
$map = new Thread\Map($array);
$thread = new Thread(__FILE__, $map);
} else {
$map = $args[0];
var_dump($map->toArray());
}
Bug修复:
- 修复无法通过
pecl
安装的问题 @remicollet - 修复
Swoole\Coroutine\FastCGI\Client
客户端无法设置keepalive
@NathanFreeman - 修复请求参数超过
max_input_vars
时会抛出错误导致进程不断重启的问题 @NathanFreeman - 修复在协程中使用
Swoole\Event::wait()
导致的未知问题 @matyhtf - 修复
proc_open
在协程化的时候不支持pty
的问题 @matyhtf - 修复
pdo_sqlite
在PHP8.3
会出现段错误的问题 @NathanFreeman - 修复编译时的无用警告 @Appla @NathanFreeman
- 修复如果
STDOUT/STDERR
已经关闭时,底层调用zend_fetch_resource2_ex
会抛出错误 @Appla @matyhtf - 修复无效的
set_tcp_nodelay
配置 @matyhtf - 修复文件上传的时候偶尔会触发不可达的分支问题 @NathanFreeman
- 修复设置了
dispatch_func
导致php
底层抛出错误的问题 @NathanFreeman - 修复
AC_PROG_CC_C99
在autoconf >= 2.70
版本中已过时 @petk - 当线程创建失败时,捕获其抛出的异常 @matyhtf
- 修复
_tsrm_ls_cache
未定义问题 @jingjingxyk - 修复在
GCC 14
编译会导致致命错误 @remicollet
内核优化:
- 移除对
socket structs
的无用检查 @petk - 升级
swoole Library
@deminy Swoole\Http\Response
增加对451
状态码的支持 @abnegate- 同步
PHP
不同版本的文件操作代码 @NathanFreeman - 同步
PHP
不同版本的pdo
操作代码 @NathanFreeman - 优化
Socket::ssl_recv()
的代码 @matyhtf - 优化了
config.m4
,一些配置可以通过pkg-config
设置依赖库位置 @NathanFreeman - 优化解析请求头的时候使用动态数组的问题 @NathanFreeman
- 优化在多线程模式下,文件描述符
fd
的生命周期问题 @matyhtf - 优化协程一些基本逻辑 @matyhtf
废弃:
- 不再支持PHP 8.0
- 不再支持Swoole\Coroutine\MySQL协程客户端
- 不再支持Swoole\Coroutine\Redis协程客户端
- 不再支持Swoole\Coroutine\PostgreSQL协程客户端
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。