Closed tmuehlschlegel closed 7 years ago
ps -ef | grep php
to see how much worker process you have, each process should handle your request.
I mean swoole isn't atomic. In a normal php environment, the code above should return 1000, because the url was executed 1000 times. With swoole it's executed 1000 times too, but the result is only 200 (vary).
Replace the code above with the code below.
$server = new Swoole\Http\Server('127.0.0.1', 9500);
$file = '/tmp/debug.log';
$i = 0;
@unlink($file);
$server->on('Request', function ($request, $response) use (&$i, $file) {
file_put_contents($file, '1' . PHP_EOL, FILE_APPEND);
$response->end((++$i) . ' vs ' . count(file($file)));
});
$server->start();
Then benchmark the server again
ab -c10 -n1000 http://localhost:9500/
Then check the result
curl http://localhost:9500 // output: "215 vs 1001"
See https://en.wikipedia.org/wiki/Race_condition for more background information.
@rottenrice your not understand how swoole is working
It's hard to understand something when it's not documented in a language which you understand.
I can only read the code examples, e.g. https://github.com/swoole/swoole-src/blob/master/examples/coroutine/redis_pool.php is very similar to my example above.
Under highload:
I'm not sure if such a behaviour is expected. For me it's a critical bug. For instance that's the reason why you should build php with "thread saftey = On" when you are using pthreads. But here it does not have any positive effect
By default, multiple worker processes are started.
The $i is a local variable, Memory is quarantined in a multi-process environment.
$i++
is only in one work process.
Try this program
<?php
$server = new Swoole\Http\Server('127.0.0.1', 9500);
$atomic = new Swoole\Atomic(0);
$server->on('Request', function ($request, $response) use ($atomic) {
$response->end($atomic->add(1));
});
$server->start();
We are writing an English document now. Thanks for your question.
"By default, multiple worker processes are started"
How to control how many processes are started and possibly limit to just one process? And with one process then would the original script posted by rottenrice work as expected?
I managed to cut the php processes down from 10 to 3 by configuring work_num to 1 as follows:
$ cat server.php
<?php
$server = new Swoole\Http\Server('127.0.0.1', 9500);
$server->set([
'open_tcp_nodelay' => true,
'worker_num' => 1,
]);
$i = 0;
$server->on('Request', function ($request, $response) use (&$i) {
$response->end(++$i);
});
$server->start();
After running this script then only 3 php processes are started:
$ ps auxwww | egrep "[p]hp"
simon 32113 0.0 0.7 257424 28856 pts/10 Sl+ 14:34 0:00 php server.php
simon 32114 0.0 0.1 183068 5548 pts/10 S+ 14:34 0:00 php server.php
simon 32116 0.0 0.2 185580 8156 pts/10 S+ 14:34 0:00 php server.php
And when running it then $i ends up at 1,001 as expected:
$ ab -c10 -n1000 http://localhost:9500/ ; echo "single curl request:" ; curl http://localhost:9500 ; echo
...
single curl request:
1001
So this explains how to get the code from @rottenrice working without complicated atomic code etc :-)
However, @matyhtf, obviously with worker_num set to 1 then all the HTTP processing is happening in a single worker process as originally wanted by @rottenrice, but what are the other 2 processes (of the total 3 processes started) for? And is it possible to collapse them into a single process somehow, or to configure them not to start up? For example, with nginx then it's possible to run a single nginx process as a tiny http server. Is it possible to run a swoole HTTP server as a single process too?
Reading the docs then I'm guessing the other 2 processes are the 'master' process and the 'manager' process. How can I tell which process is which type of process in the swoole process model? Is there any documentation on what the swoole master and manager processes do?
I noticed that while running ab then 2 out of the 3 swoole php processes use CPU:
$ ab -c10 -n10000 http://localhost:9500/ ; echo "single curl request:" ; curl http://localhost:9500 ; echo
...
single curl request:
10001
$ top -d 1 -b | egrep --line-buffered php | perl -lane '$|++; printf qq[%s %s\n], scalar localtime, $_;'
Fri Dec 8 15:13:09 2017 32299 simon 20 0 257424 28728 23156 S 1.0 0.7 0:00.02 php
Fri Dec 8 15:13:09 2017 32300 simon 20 0 183068 5548 0 S 0.0 0.1 0:00.00 php
Fri Dec 8 15:13:09 2017 32302 simon 20 0 185460 9736 4156 S 0.0 0.2 0:00.00 php
Fri Dec 8 15:13:10 2017 32299 simon 20 0 257424 28728 23156 S 15.8 0.7 0:00.18 php
Fri Dec 8 15:13:10 2017 32302 simon 20 0 185460 9736 4156 S 9.9 0.2 0:00.10 php
Fri Dec 8 15:13:10 2017 32300 simon 20 0 183068 5548 0 S 0.0 0.1 0:00.00 php
Fri Dec 8 15:13:11 2017 32299 simon 20 0 257424 28728 23156 S 16.8 0.7 0:00.35 php
Fri Dec 8 15:13:11 2017 32302 simon 20 0 185460 9736 4156 S 10.9 0.2 0:00.21 php
Fri Dec 8 15:13:11 2017 32300 simon 20 0 183068 5548 0 S 0.0 0.1 0:00.00 php
Fri Dec 8 15:13:12 2017 32299 simon 20 0 257424 28728 23156 S 13.9 0.7 0:00.49 php
Fri Dec 8 15:13:12 2017 32302 simon 20 0 185460 9736 4156 S 8.9 0.2 0:00.30 php
Fri Dec 8 15:13:12 2017 32300 simon 20 0 183068 5548 0 S 0.0 0.1 0:00.00 php
Fri Dec 8 15:13:13 2017 32299 simon 20 0 257424 28728 23156 S 13.9 0.7 0:00.63 php
Fri Dec 8 15:13:13 2017 32302 simon 20 0 185460 9736 4156 R 8.9 0.2 0:00.39 php
Fri Dec 8 15:13:13 2017 32300 simon 20 0 183068 5548 0 S 0.0 0.1 0:00.00 php
Fri Dec 8 15:13:14 2017 32299 simon 20 0 257424 28728 23156 S 14.9 0.7 0:00.78 php
Fri Dec 8 15:13:14 2017 32302 simon 20 0 185460 9736 4156 S 9.9 0.2 0:00.49 php
Fri Dec 8 15:13:14 2017 32300 simon 20 0 183068 5548 0 S 0.0 0.1 0:00.00 php
Fri Dec 8 15:13:15 2017 32299 simon 20 0 257424 28728 23156 S 9.9 0.7 0:00.88 php
Fri Dec 8 15:13:15 2017 32302 simon 20 0 185460 9736 4156 S 6.9 0.2 0:00.56 php
Fri Dec 8 15:13:15 2017 32300 simon 20 0 183068 5548 0 S 0.0 0.1 0:00.00 php
Fri Dec 8 15:13:16 2017 32299 simon 20 0 257424 28728 23156 S 0.0 0.7 0:00.88 php
Fri Dec 8 15:13:16 2017 32300 simon 20 0 183068 5548 0 S 0.0 0.1 0:00.00 php
Fri Dec 8 15:13:16 2017 32302 simon 20 0 185460 9736 4156 S 0.0 0.2 0:00.56 php
So this means the listener and receiver is running in one process and the worker is running in another (swoole 'worker'?) process? But how to merge them into a single process?
Interesting... if I change the following line in the above server.php script then the number of PHP processes drops from 3 to 1:
$server = new Swoole\Http\Server('127.0.0.1', 9500, SWOOLE_BASE);
Note: I believe the default is SWOOLE_PROCESS.
amazing work, but swoole is not concurrency aware:
benchmark the code:
all requests were processed successfully, so the expected result is 1000. But it's much lower:
test environment: