✨ New Feature:
Swoole
supports multi-threading mode. WhenPHP
is inZTS
mode andSwoole
is compiled with--enable-swoole-thread
, the multi-threading mode can be utilized.- Added a new thread management class
Swoole\Thread
. @matyhtf - Introduced thread lock
Swoole\Thread\Lock
. @matyhtf - Added thread atomic counter
Swoole\Thread\Atomic
,Swoole\Thread\Atomic\Long
. @matyhtf - Added safe concurrent containers
Swoole\Thread\Map
,Swoole\Thread\ArrayList
,Swoole\Thread\Queue
. @matyhtf - File asynchronous operations support
iouring
as the underlying engine. Installingliburing
and compilingSwoole
with--enable-iouring
enables asynchronous operations for functions likefile_get_contents
,file_put_contents
,fopen
,fclose
,fread
,fwrite
,mkdir
,unlink
,fsync
,fdatasync
,rename
,fstat
,lstat
,filesize
throughiouring
. @matyhtf @NathanFreeman - Upgraded
Boost Context
to version 1.84. Now, Loongson CPUs can also support coroutines. @NathanFreeman
📖 example:
- How to create threads
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";
while (1) {
sleep(1);
file_get_contents('https://www.baidu.com/');
}
}
- Thread + Server (Asynchronous Style)
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__,
// sharing data between threads through `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) {
// Retrieve shared data passed by `init_arguments` in the configuration using `Swoole\Thread::getArguments()`.
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/');
});
}
});
}
🐛 Bug Fixed:
- Fixed the issue where installation via
pecl
was not possible. @remicollet - Fixed the bug where setting
keepalive
was not possible forSwoole\Coroutine\FastCGI\Client
. @NathanFreeman - Fixed the issue where exceeding the
max_input_vars
would throw an error, causing the process to restart repeatedly. @NathanFreeman - Fixed unknown issues caused by using
Swoole\Event::wait()
within a coroutine. @matyhtf - Fixed the problem where
proc_open
does not support pty in coroutine mode. @matyhtf - Fixed segmentation fault issues with
pdo_sqlite
on PHP 8.3. @NathanFreeman - Fixed unnecessary warnings during the compilation of
Swoole
. @Appla @NathanFreeward - Fixed the error thrown by zend_fetch_resource2_ex when
STDOUT/STDERR
are already closed. @Appla @matyhtf - Fixed ineffective
set_tcp_nodelay
configuration. @matyhtf - Fixed the occasional unreachable branch issue during file upload. @NathanFreeman
- Fixed the problem where setting
dispatch_func
would cause PHP's internals to throw errors. @NathanFreeman - Fixed the deprecation of AC_PROG_CC_C99 in autoconf >= 2.70. @petk
- Capture exceptions when thread creation fails. @matyhtf
- Fixed the undefined problem with
_tsrm_ls_cache
. @jingjingxyk - Fixed the fatal compile error with
GCC 14
. @remicollet
⭐️ Kernel optimization:
- Removed unnecessary checks for
socket structs
. @petk - Upgraded Swoole Library. @deminy
- Added support for status code 451 in
Swoole\Http\Response
. @abnegate - Synchronized
file
operation code across different PHP versions. @NathanFreeman - Synchronized
pdo
operation code across different PHP versions. @NathanFreeman - Optimized the code for
Socket::ssl_recv()
. @matyhtf - Improved config.m4; some configurations can now set library locations via
pkg-config
. @NathanFreeman - Optimized the use of dynamic arrays during
request header parsing
. @NathanFreeman - Optimized file descriptor
fd
lifecycle issues in multi-threading mode. @matyhtf - Optimized some fundamental coroutine logic. @matyhtf
❌ Deprecated:
- No longer supports
PHP 8.0
. - No longer supports
Swoole\Coroutine\MySQL
coroutine client. - No longer supports
Swoole\Coroutine\Redis
coroutine client. - No longer supports
Swoole\Coroutine\PostgreSQL
coroutine client.
⚠ Warning:
Swoole-v6.0.0-alpha
is a test version and cannot be used in any production environment; it is for testing purposes only.
😊 Thank you
- Thank you for your contribution to Swoole v6.0.0. Wish you good health, all the best, and smooth work.
✨ 新特性:
Swoole
支持多线程模式,当php
是zts
模式,编译Swoole
时开启--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
作为底层引擎,安装了liburing
和编译Swoole
时开启--enable-iouring
,file_get_contents
,file_put_contents
,fopen
,fclose
,fread
,fwrite
,mkdir
,unlink
,fsync
,fdatasync
,rename
,fstat
,lstat
,filesize
这些函数的异步操作将会由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/');
});
}
});
}
🐛 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 - 修复编译
Swoole
时的无用警告。 @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
协程客户端。
⚠ 注意:
Swoole-v6.0.0-alpha
是测试版本,不能用于任何生产环境,只能用于测试。
😊 致谢
- 感谢你们为Swoole v6.0.0做出的贡献,祝愿大家身体健康,万事如意,工作顺利。