Open Swoole v4.10.0 is a major release with new Coroutine Selector API co::select(), HTTP2 SSE and bug fixes, sleep/usleep data type fixes and enhancements.
In the previous version, we have introduced Coroutine WaitGroup to wait until the finish of multiple channels. The basic $chan->push()
and $chan->pop()
are blocking.
You can implement non-blocking channel operations with co::select
since Open Swoole v4.10.0.
You will be able to wait for at least one channel to be closed, ready to read or write and implement non-blocking sends, receives, and even non-blocking multi-way selects.
<?php declare(strict_types = 1);
Co::set(['hook_flags' => SWOOLE_HOOK_ALL]);
function fetchUrl($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$response = curl_exec($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
curl_close($ch);
return $header;
}
Co\run(function () {
$chan1 = new chan(1);
$chan2 = new chan(1);
go(function() use ($chan1) {
$header = fetchUrl('https://openswoole.com/');
$chan1->push(['id' => 'chan1', 'header' => $header]);
});
go(function() use ($chan2) {
$header = fetchUrl('https://www.google.com/');
$chan2->push(['id' => 'chan2', 'header' => $header]);
});
go(function() use ($chan1, $chan2){
while(1) {
$ret = co::select([$chan1, $chan2], [], 3);
if(sizeof($ret['read']) === 0) break;
$ret = array_values($ret['read'])[0]->pop();
var_dump($ret);
}
});
});
To eliminate long-tail latency on a high concurrent system, you can use coroutines and co::select in multiple identical concurrent requests and the fastest response win.
You can find more about this API at /docs/modules/swoole-coroutine-select.
When not used over HTTP/2, SSE suffers from a limitation to the maximum number of open connections. HTTP2 SSE is supported since Open Swoole v4.10.0.
<?php
$http = new Swoole\HTTP\Server("0.0.0.0", 9501, SWOOLE_BASE, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$http->set([
'open_http2_protocol' => 1,
'enable_coroutine' => true,
'ssl_cert_file' => __DIR__ . '/example.com+4.pem',
'ssl_key_file' => __DIR__ . '/example.com+4-key.pem',
]);
$http->on('request', function (Swoole\HTTP\Request $request, Swoole\HTTP\Response $response) {
$response->header('Access-Control-Allow-Origin', '*');
$response->header('Content-Type', 'text/event-stream');
$response->header('Cache-Control', 'no-cache');
$response->header('X-Accel-Buffering', 'no');
while(1) {
$response->write("event: ping\n\n");
$r = $response->write("data: {\"time\": \"" . date(DATE_ISO8601) . "\"}\n\n");
if(!$r) return;
co::sleep(1);
}
// never reach
$response->end('DONE');
});
$http->start();
<script type="text/javascript">
const eventSrc = new EventSource("https://localhost:9501/");
eventSrc.addEventListener('open', function (event) {
console.log(event.type);
});
eventSrc.addEventListener('message', function (event) {
console.log(event.type);
console.log(event.data);
});
</script>
You can use curl or nghttp to debug HTTP2 applications:
nghttp --hexdump -nv https://localhost:9501/
# or
curl -vv https://localhost:9501/
sleep
and usleep
data type issues are fixed in this release.
PHP developers use sleep
or usleep
to pause the execution of the request for a while. They are also considered evil under PHP-FPM applications because sleep
holds up the memory resources of the process.
Open Swoole introduced coroutine sleep API and hooks for sleep and usleep, you can find more details at /docs/runtime-hooks/swoole-hook-sleep and /docs/modules/swoole-coroutine-sleep. Both these APIs are resources consuming friendly, you can use them without harming the performance of your application.
In the previous versions, you used to be able to pass float type $seconds
into co::sleep()
API or the hooked sleep
, while the argument data type of PHP sleep
is int
.
This inconsistency is fixed in Open Swoole v4.10.0. You will only be able to pass int
into co::sleep()
or use co::usleep()
inline with PHP language.
Since Open Swoole v4.10.0, channel stats include a new field id: /docs/modules/swoole-coroutine-channel-stats.
New method $chan->getId()
is added since Open Swoole v4.10.0.
You will also be able to look up a channel on your server or cluster in the future versions even the channel is not on the same machine.
In the previous version, there are multiple bugs related to the HTTP2 protocol and fixed in Open Swoole v4.10.0. Deprecated and removed TLS Next Protocol Negotiation. Fixed HTTP2 server-side TLS ALPN.
Now you can access Open Swoole HTTP2, HTTPS, WebSocket server with Chrome and Firefox with local testing SSL certificates generated with mkcert
. You can find more info at How to enable HTTPS/TLS at Open Swoole Server.
Thanks the community, you can install Open Swoole with port command in the future if you are a MacPorts user.
sudo port install php-openswoole
You will be able to use Open Swoole Metrics API and Open Swoole Dashboard in a popular PHP framework Laravel Octane with one line of code within Laravel Controllers:
<?php
app(WorkerState::class)->server->stats();
You can upgrade to Open Swoole v4.10.0 now:
pecl install openswoole
Or use Docker images:
docker pull openswoole/swoole:latest
If you need to install Open Swoole or look at other update methods, checkout the installation documentation and how to update Open Swoole.
Join 4,000+ others and never miss out on new tips, tutorials, and more.