Closed9

Laravel Octane を動かしてみた

やまゆやまゆ

まずリポジトリの用意

Installation - Laravel - The PHP Framework For Web Artisans

$ curl -s https://laravel.build/example-app | bash
...

Laravel Sail を用いて docker-compose を起動

$ ./vendor/bin/sail up
...

http://localhost に Welcome ページが出るのを確認

$ curl http://localhost
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
...

デフォルトでは php artisan serve 、つまり PHP ビルトインサーバで動いています。

現状 laravel.build を用いて環境を用意すると、自動で pecl install swoole してくれるみたいです。

$ ./vendor/bin/sail exec laravel.test php -m | grep swoole
swoole

ここに負荷をかけてみます。

負荷かけは wg/wrk

$ cd ..
$ git clone --depth 1 https://github.com/wg/wrk
$ cd wrk
$ make
...
$ cp wrk ../example-app/wrk

とりあえず PHP ビルトインサーバさんにテスト

$ ./wrk -t12 -d10s -c400 http://localhost
Running 10s test @ http://localhost
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   445.94ms  141.95ms   1.82s    75.60%
    Req/Sec    45.88     36.40   161.00     75.27%
  2006 requests in 10.02s, 35.57MB read
  Socket errors: connect 0, read 2006, write 0, timeout 14
Requests/sec:    200.19
Transfer/sec:      3.55MB

何やら read socket error が出ている様子。

眠いので続きは明日...。

やまゆやまゆ

原因がいまいち不明ですが、 wrk だとエラーになってしまうみたいなので、みんな大好き ab を使うことにしました。

$ sudo apt install apache2-utils
$ ab -n1000 -c20 http://localhost/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:
Server Hostname:        localhost
Server Port:            80

Document Path:          /
Document Length:        17490 bytes

Concurrency Level:      20
Time taken for tests:   4.130 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      18631000 bytes
HTML transferred:       17490000 bytes
Requests per second:    242.11 [#/sec] (mean)
Time per request:       82.607 [ms] (mean)
Time per request:       4.130 [ms] (mean, across all concurrent requests)
Transfer rate:          4405.02 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     7   82   7.9     81     103
Waiting:        6   81   7.9     80     103
Total:          7   82   7.8     81     103

Percentage of the requests served within a certain time (ms)
  50%     81
  66%     83
  75%     85
  80%     86
  90%     87
  95%     91
  98%     97
  99%     98
 100%    103 (longest request)

242 rps くらいということで良いでしょう。

やまゆやまゆ

それでは Octane 試してみましょう。まずは RoadRunner から。

ドキュメント通りに実行していきます。

$ ./vendor/bin/sail composer require spiral/roadrunner
...
$ ./vendor/bin/sail shell

# Within the Sail shell...
$ ./vendor/bin/rr get-binary
$ exit
$ ./vendor/bin/sail artisan sail:publish
$ vi docker/8.0/supervisor.d.conf
$ ./vendor/bin/sail build
$ ./vendor/bin/sail stop laravel.test
$ ./vendor/bin/sail up -d laravel.test
$ curl -v http://localhost/
*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
>
* Recv failure: Connection reset by peer
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer

あれー、サーバがうまく立ち上がっていない。

laravel.test_1  |   There are no commands defined in the "octane" namespace.

octane を require するのを忘れていた。

$ vendor/bin/sail composer require laravel/octane
$ vendor/bin/sail artisan octane:install

 Which application server you would like to use?:
  [0] roadrunner
  [1] swoole
 > 0


   INFO  Octane installed successfully.
laravel.test_1  | 2021-05-13 13:02:37,952 INFO spawned: 'php' with pid 889
laravel.test_1  |
laravel.test_1  |    INFO  Server running…
laravel.test_1  |
laravel.test_1  |   Local: http://0.0.0.0:80
laravel.test_1  |
laravel.test_1  |   Press Ctrl+C to stop the server
laravel.test_1  |
laravel.test_1  | 2021-05-13 13:02:39,058 INFO success: php entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
laravel.test_1  |
laravel.test_1  |    ERROR  handle_serve_command: Serve error:
laravel.test_1  |
laravel.test_1  |    ERROR      endure_start:
laravel.test_1  |
laravel.test_1  |    ERROR      endure_serve_internal: Function call error:
laravel.test_1  |
laravel.test_1  |    ERROR      endure_call_serve_fn: got initial serve error from the Vertex rpc.Plugin, stopping execution, error: rpc_plugin_serve: address -1919: invalid port
laravel.test_1  | 2021-05-13 13:02:39,063 INFO exited: php (exit status 1; not expected)

謎のエラーがでて動かない。

supervisord.conf に --port=80 を入れていたのを、代わりに --port=8000 にしたらエラーなく起動した。どうやら 80 番ポートは RoadRunner と相性が悪そう?

これで、先ほどと同じ条件で ab ベンチかけてみます。

sail:/var/www/html$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   3980  3120 ?        Ss   13:37   0:00 bash /usr/local/bin/start-container
root        16  0.0  0.1  27836 23144 ?        S    13:37   0:00 /usr/bin/python3 /usr/bin/supervisord -c /etc/superviso
sail        18  0.0  0.4 123812 56284 ?        S    13:37   0:00 /usr/bin/php -d variables_order=EGPCS /var/www/html/art
sail        34  0.6  0.2 732504 38792 ?        Sl   13:37   0:00 /var/www/html/rr -c /var/www/html/.rr.yaml -o http.addr
sail        44  0.0  0.4 121764 54420 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        46  0.0  0.3 109128 41232 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        47  0.0  0.3 109128 41352 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        48  0.0  0.3 109128 41372 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        49  0.0  0.3 109128 41308 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        50  0.0  0.3 109128 41436 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        51  0.0  0.3 109128 41168 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        52  0.0  0.3 109128 41216 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        53  0.0  0.3 109128 41224 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        54  0.0  0.3 109128 41348 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        55  0.0  0.3 109128 41212 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        56  0.0  0.3 109128 41344 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        57  0.0  0.3 109128 41428 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        58  0.0  0.3 109128 41376 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        59  0.0  0.3 109128 41316 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker
sail        60  0.0  0.3 109128 41356 ?        S    13:37   0:00 /usr/bin/php8.0 ./vendor/bin/roadrunner-worker

こんな感じでデフォルトではCPUコア数分のプロセスが立ち上がっています。

$ ab -n1000 -c20 http://localhost:8000/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:
Server Hostname:        localhost
Server Port:            8000

Document Path:          /
Document Length:        17490 bytes

Concurrency Level:      20
Time taken for tests:   0.518 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      18495000 bytes
HTML transferred:       17490000 bytes
Requests per second:    1929.27 [#/sec] (mean)
Time per request:       10.367 [ms] (mean)
Time per request:       0.518 [ms] (mean, across all concurrent requests)
Transfer rate:          34845.54 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       0
Processing:     2    8  15.6      5     111
Waiting:        2    8  15.6      5     110
Total:          2    8  15.6      5     111

Percentage of the requests served within a certain time (ms)
  50%      5
  66%      6
  75%      7
  80%      7
  90%      9
  95%     15
  98%     95
  99%    101
 100%    111 (longest request)

ハッ!?

中々な早さを出してきますね。

やまゆやまゆ

約 2,000 rps 。 AMD Ryzen 7 3700X で論理コアが 16 個あるので、 1 コアあたり 125 rps くらい出してる計算になります。

やまゆやまゆ
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 10960644 251052 1044992    0    0    16    86   21   71  0  0 99  0  0
 0  0      0 10962468 251052 1045032    0    0     0     0   85  389  0  0 100  0  0
 0  1      0 10963520 251060 1045024    0    0     0    12  387 1552  0  0 100  0  0
21  0      0 10948496 251152 1044952    0    0    72  1128 2406 7425  6  3 92  0  0
17  0      0 10941980 251480 1049312    0    0    64  4120 10783 39470 33 61  6  0  0
17  0      0 10936416 251776 1054892    0    0     0  3536 8828 33422 31 65  3  0  0
16  0      0 10961420 252036 1060256    0    0     0  3356 8810 32581 32 65  4  0  0
17  0      0 10920768 252388 1064772    0    0     0  4476 11906 45336 34 61  5  0  0
16  0      0 10914736 252624 1069688    0    0     0  6320 7022 26362 29 69  2  0  0
17  0      0 10907804 252940 1075588    0    0     0  4232 11517 41444 34 63  4  0  0
19  0      0 10901780 253120 1078872    0    0     0  2892 8453 32012 31 66  2  0  0
17  0      0 10896360 253432 1084888    0    0     4  3680 9310 35453 34 62  4  0  0
17  0      0 10892016 253628 1087508    0    0     0  2324 5803 23516 29 70  2  0  0
17  0      0 10886552 253892 1091680    0    0     0  7016 8682 32436 30 67  3  0  0
16  0      0 10881876 254100 1096864    0    0     0  2748 7133 28151 30 67  2  0  0
 0  0      0 10879440 254228 1099368    0    0     0  1528 4182 16189 24 46 30  0  0
 1  0      0 10879440 254228 1099680    0    0     0     0   82  332  0  0 100  0  0
 1  0      0 10879252 254228 1099680    0    0     0   152   92  290  0  0 100  0  0
 0  0      0 10879252 254228 1099680    0    0     0     0   82  238  0  0 100  0  0
 0  0      0 10879408 254244 1099668    0    0     0  2592   82  229  0  0 100  0  0

負荷かけ中は大体こんな程度CPUを食っています。 user 30 system 70 くらいですね。

やまゆやまゆ

docker on WSL2 でこのスコアはかなり良いのではないでしょうか。ただの Welcome ページなので現実的な測定ではありませんが、スケール感は感じれたと思います。

やまゆやまゆ

ではこの調子で Swoole の方も試してみましょう。

sail@:/var/www/html$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   3980  3020 ?        Ss   13:54   0:00 bash /usr/local/bin/start-container
root        16  0.4  0.1  27836 23100 ?        S    13:54   0:00 /usr/bin/python3 /usr/bin/supervisord -c /etc/superviso
sail        18  0.4  0.4 123812 56324 ?        S    13:54   0:00 /usr/bin/php -d variables_order=EGPCS /var/www/html/art
sail        25  0.2  0.3 1351048 50064 ?       Sl   13:54   0:00 swoole_http_server: master process for Laravel
sail        26  0.2  0.1 173352 18900 ?        S    13:54   0:00 swoole_http_server: manager process for Laravel
sail        43  0.4  0.2 179872 30812 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        44  0.5  0.2 179872 30836 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        45  0.5  0.2 179872 30836 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        46  0.5  0.2 179872 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        47  0.4  0.2 179876 30828 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        48  0.4  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        49  0.4  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        50  0.4  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        51  0.5  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        52  0.5  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        53  0.5  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        54  0.5  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        55  0.5  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        56  0.4  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        57  0.4  0.2 179876 30840 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        58  0.4  0.2 179876 30688 ?        S    13:54   0:00 swoole_http_server: task worker process for Laravel
sail        59  0.5  0.2 179924 31240 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        60  0.4  0.2 179924 31176 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        61  0.4  0.2 179924 31092 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        62  0.5  0.2 179924 31188 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        63  0.5  0.2 179924 31132 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        64  0.4  0.2 179924 31192 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        65  0.6  0.2 179924 31308 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        66  0.5  0.2 179924 31204 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        67  0.4  0.2 179924 31100 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        68  0.5  0.2 179924 31196 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        69  0.5  0.2 179924 31344 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        70  0.5  0.2 179924 31344 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        71  0.5  0.2 179924 31344 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        72  0.5  0.2 179924 31336 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        73  0.5  0.2 179924 31084 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        74  0.4  0.2 179924 31344 ?        S    13:54   0:00 swoole_http_server: worker process for Laravel
sail        75  2.0  0.0   4244  3472 pts/0    Ss   13:54   0:00 bash
sail        87  0.0  0.0   5900  2880 pts/0    R+   13:54   0:00 ps aux

ワーカーが論理コア数、タスクワーカーも論理コア数だけプロセス生成されています。

$ ab -n1000 -c20 http://localhost:8000/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        swoole-http-server
Server Hostname:        localhost
Server Port:            8000

Document Path:          /
Document Length:        17503 bytes

Concurrency Level:      20
Time taken for tests:   1.174 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      18565000 bytes
HTML transferred:       17503000 bytes
Requests per second:    851.64 [#/sec] (mean)
Time per request:       23.484 [ms] (mean)
Time per request:       1.174 [ms] (mean, across all concurrent requests)
Transfer rate:          15440.07 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       1
Processing:     2   19  98.0      4     821
Waiting:        1   19  98.0      4     821
Total:          2   19  98.0      4     821

Percentage of the requests served within a certain time (ms)
  50%      4
  66%      5
  75%      6
  80%      7
  90%     10
  95%     15
  98%    127
  99%    777
 100%    821 (longest request)

あら、こちらはどうも怪しい感じ。後半になると急に遅くなったように見えました。

リクエスト数を 1,000 から 10,000 に変えてみましょう。

$ ab -n10000 -c20 http://localhost:8000/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        swoole-http-server
Server Hostname:        localhost
Server Port:            8000

Document Path:          /
Document Length:        17503 bytes

Concurrency Level:      20
Time taken for tests:   15.533 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      185650000 bytes
HTML transferred:       175030000 bytes
Requests per second:    643.79 [#/sec] (mean)
Time per request:       31.066 [ms] (mean)
Time per request:       1.553 [ms] (mean, across all concurrent requests)
Transfer rate:          11671.93 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       1
Processing:     1   30 162.2      3    2118
Waiting:        1   30 162.2      3    2117
Total:          1   30 162.2      3    2118

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      4
  75%      4
  80%      4
  90%      6
  95%     10
  98%    940
  99%   1039
 100%   2118 (longest request)

うーん、ほとんどの処理は10ms以内に終わっていますが、5%のリクエストが非常に遅くなっているようです。 5% が Welcome ページ表示で 1~2 秒かかっていると考えると、ちょっとつらいですね。 ab との相性か、 WSL2 との相性かわかりませんが、ちょっと不安な数値でした。

やまゆやまゆ

docker on WSL2 でテストしたので、 ECS や GKE などに載せた際はまた違った結果になる可能性もありますが、とにかく どちらを選んでもかなり高速なレスポンスが得られる ことがわかりました。

RoadRunner は難しい設定なしで手軽に高速な HTTP をサーブしてくれるのがわかります。 HTTP/2 を受け入れることも出来るのは強みですね。

Swoole であれば、アプリケーションロジックで並列化可能な部分を並列処理してより高速にさばくことも出来るでしょう。

ということで Laravel Octane 動かしてみた、でした。

やまゆやまゆ

初めて Laravel Sail を使ってみましたが、これは楽で良いですね。好き。

このスクラップは2021/05/19にクローズされました