この記事はKUSANAGI Advent Calendar 2016 14日目のエントリーです。
KUSANAGIの開発元である、プライム・ストラテジー株式会社でエンジニアをしておりました。@tajima_tasoと申します。
※2017年9月に戻ってきており、KUSANAGIの開発をしております。
私からはKUSANAGI環境上で、近年人気が高まっているPHPフレームワーク、Laravelを構築する方法について、ご紹介いたします。
どのくらい爆速なのか?
まずはKUSANAGIの速さを数字で確認して頂きます。KUSANAGIを載せた結果、大して性能が出てないという結果であれば、この記事を読んだ時間が無駄になってしまいますので、最初に持ってきました。
断っておきますと、今回、キャッシュやロードバランシングといった類の話は__一切関与しません__。単純に載る土台(OS、ミドルウェア)によって同一のアプリケーションがどれだけ速く動くか?ということに焦点をあてたお話です。
通常のLAMP環境と KUSANAGI環境のベンチマークの結果で、その速さを確認して頂きます。両方とも下記の__同一のパブリッククラウドの同一のリージョンの同一のサーバリソース__のもとで動作しています。端的に言うと、異なるのはソフトウェアをチューニングしているかしていないかの違いのみです。
パブリックプラウド | リージョン | サーバプラン | ディスクプラン |
---|---|---|---|
さくらのクラウド | 石狩第2ゾーン | 2 GB / 2 仮想コア | 20 GB SSDプラン |
abを叩くクライアントとなるサーバはさくらのVPS(石狩)です。
まずは通常のLAMP環境のベンチマークです。
LAMP環境でのベンチマーク
$ ab -n 1000 -c 100 http://kusanagi-lamp.jp/
Completed 1000 requests
Finished 1000 requests
Server Software: Apache/2.4.6
Server Hostname: kusanagi-lamp.jp
Server Port: 80
Document Path: /
Document Length: 1023 bytes
Concurrency Level: 100
Time taken for tests: 26.929 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 2045156 bytes
HTML transferred: 1023000 bytes
Requests per second: 37.13 [#/sec] (mean)
Time per request: 2692.880 [ms] (mean)
Time per request: 26.929 [ms] (mean, across all concurrent requests)
Transfer rate: 74.17 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.3 0 19
Processing: 479 2647 708.4 2690 4582
Waiting: 473 2618 701.1 2664 4582
Total: 484 2648 707.9 2690 4582
Percentage of the requests served within a certain time (ms)
50% 2690
66% 2892
75% 3065
80% 3218
90% 3561
95% 3886
98% 4063
99% 4157
100% 4582 (longest request)
Requests per second(1秒間に処理されたリクエスト数)が__37.13__となっています。
続いてKUSANAGI環境で比べてみましょう。
KUSANAGI環境でのベンチマーク
$ ab -n 1000 -c 100 http://kusanagi-laravel.jp/
Server Software: nginx
Server Hostname: kusanagi-laravel.jp
Server Port: 80
Document Path: /
Document Length: 1023 bytes
Concurrency Level: 100
Time taken for tests: 2.474 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 2011992 bytes
HTML transferred: 1023000 bytes
Requests per second: 404.25 [#/sec] (mean)
Time per request: 247.371 [ms] (mean)
Time per request: 2.474 [ms] (mean, across all concurrent requests)
Transfer rate: 794.29 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.3 0 9
Processing: 61 236 54.1 230 662
Waiting: 61 236 54.3 230 662
Total: 66 237 53.8 230 663
Percentage of the requests served within a certain time (ms)
50% 230
66% 238
75% 244
80% 249
90% 267
95% 283
98% 322
99% 591
100% 663 (longest request)
Requests per secondが__404.25__となっています。
なんと単純比較で__約11倍__の性能が出ることになりました。くどいようですが、キャッシュは一切使っておりません。
両者の違いは__ソフトウェア(ミドルウェア)的なチューニングの有無の違いのみで、ハードウェアやサーバ構成__などその他外的な要因はまったく同じです。
KUSANAGIのことをご存知だった方も、そうでない方も、記事を読む前よりも興味を抱いて頂けていたら幸いです。
ではKUSANAGIとは一体何なのでしょうか?
KUSANAGIとは
プライム・ストラテジー社が開発した超高速WordPressマシンです。
その実体は徹底的にチューニングされたLEMP、LAMPのサーバ環境に他なりません。
CentOS7をベースとして、PHP、Apache、nginx、MySQL(MariaDB)上で動作するアプリケーションに超高速な実行環境を提供します。
それはつまり、KUSANAGIはWordPressだけを高速に動作させる環境ではないということを意味します。
実際、私はプライム・ストラテジー株式会社在籍時、WordPress以外のアプリケーションをKUSANAGI環境へ移行する案件を多数行いましたが、例外なく移行前よりパフォーマンスの向上を確認しておりました。
そこで今回はKUSANAGI上で、近年のPHPフレームワークの主流となりつつあるLaravelを動作させてみました。
Laravelはとても便利なフレームワークで、開発者が幸せになれる機能が満載ですが、一点動作が遅いというデメリットがあります。これをKUSANAGIでカバーできないか?という試みでしたが、結果は冒頭の通りです。
つきましては、皆さんにも是非その性能を確認して頂きたいので、続いて導入方法について紹介していきます。
どうやって利用するのか?
最初に申し上げておくと、KUSANAGI自体は__例外なく無料__で使えます。
国内外の主要なパブリッククラウドで展開していて、AWS、Microsoft Azure、さくらのクラウドなど皆さんが利用しているパブリッククラウドにはまず間違いなく導入されておりますので、使用するパブリッククラウドの選定が終わってコンパネにログインしたらポチポチと選んで、KUSANAGIのサーバを立てるという流れになります。
また、最近ではDockerやさくらのVPSでも利用可能です。
どういった環境で使えるのかは、公式サイトで紹介されています。今後も続々と増えていくでしょう。
面倒なサーバのプロビジョニングやミドルウェアの変更が、kusanagiコマンドとそのサブコマンド群で簡単に管理できることも大きな特徴の1つです。詳しくは公式ドキュメントをご覧下さい。
KUSANAGIの導入
では、KUSANAGIを実際に導入します。
といっても何も難しいことはありません。先程申し上げた通り、任意のパブリッククラウドでサーバを立てる時にKUSANAGIを選ぶだけです。
今回私は、KUSANAGI for さくらのクラウドを利用しました。
導入手順は公式サイトの通りです。サーバを立ててログインするところまで、サクッとできると思います。
KUSANAGIの初期設定
続いて、初期設定です。こちらも基本公式ドキュメントの通りのコピペでいけます。本当にこの通りなので迷わないと思います。
Laravelの為のプロビジョニング
初期設定が終わりましたら、Laravelを導入する為のKUSANAGIのプロビジョニングを行っていきます。公式ドキュメントでは、WordPressの導入にそって進めていくものの、WordPress以外のアプリケーションのプロビジョニングについてもちゃんと書かれています。
2.プロビジョンタイプの選択の選択のところを参考にしてみると
オプション --WordPress を指定すると、WordPress をプロビジョニングします。
オプション --concrete5 を指定すると、Concrete5 をプロビジョニングします。
オプション --drupal8 を指定すると、Drupal8 をプロビジョニングします。
オプション --lamp を指定すると、LAMP(Linux+Apache+MySQL+PHP) もしくは LEMP(Linux+NGINX+MySQL+PHP)で使用するための設定のみをプロビジョニングします。
とありますので、 --lamp
オプションを指定してプロビジョニングを進めていきます。
$ kusanagi provision --lamp kusanagi_html
その後、データベースの設定、Webサーバソフトウェアは? PHPのバージョンは? などの指定をインタラクティブに行っていきます。聞かれるままに入力していけばいいので、迷わないと思います。
私はPHP7とnginxを選択しました。なお、この指定はプロビジョニング後も任意のタイミングで、変更することができるので、後からPHP7とApacheの構成にすることも簡単にできます。
プロビジョニングが終了すると、適切にミドルウェアの設定が行われた後に、ソフトウェアが起動します。
これでLaraveが載るべき土台となる準備はできました。
Laravelの導入
いよいよ、Laravelを導入していきます。
今回はLTS(長期間サポート)であるLaravel5.1を導入します。5.2や5.3でもKUSANAGI上で十分導入可能なので、そちらを入れて頂いても問題ありません。
まずはLaravelの公式サイトを確認して、必要な要件を確認します。
PHP >= 5.5.9 PDO PHP拡張 Tokenizer PHP拡張
OpenSSL PHP拡張 Mbstring PHP拡張
上記が必要な要件なので、確認してみます。
KUSANAGIはPHP5.6と7系、HHVMの3つを選べます。
PHPのバージョンを確認
$ php -v
PHP 5.6.28 (cli) (built: Nov 9 2016 07:14:50)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
$ php7 -v
PHP 7.0.13 (cli) (built: Nov 11 2016 10:16:41) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
$ hhvm --version
HipHop VM 3.15.0 (rel)
Compiler: 1473300163_047790084
Repo schema: 2df110c6a6400fbcf88ff266f2b6f345e7d1b6a8
PHP5.6と7は問題ないとして、hhvmも3.11.0からはPHP7の機能をサポートしだしたのでどれを選んでも基本的には問題ないでしょう。
今回はPHP7を選択しています。
必要なPHPのモジュールを確認してみましょう。
$ php7 -i | grep enabled | grep -iE '(openssl|pdo|tokenizer|mbstring)'
OpenSSL support => enabled
PDO support => enabled
PDO Driver for MySQL => enabled
PDO Driver for SQLite 3.x => enabled
Native OpenSSL support => enabled
Tokenizer Support => enabled
こちらもKUSANAGIをインストール時に最初から有効化されているので、問題なさそうです。楽ですね。
PHPのバージョンや必要なモジュールは揃ってしましたが、KUSANAGIは現状、PHPの事実上のパッケージ管理ツールであるComposerが初期設定時には導入されていません。 kusanagi-8.3.1以降はcomposerが導入ずみですので、それ以前の環境では下記手順で導入します。
Laravelを導入するにはComposerが必要なので、インストールを行います。下記の操作はsudoなどでrootユーザーの権限で行うと良いでしょう。
$ curl -sS https://getcomposer.org/installer | sudo php
$ sudo mv composer.phar /usr/local/bin/composer
tokenizer
/usr/local/bin/にパスが通っていることを確認して、必要に応じて環境変数PATHを変更しましょう。
$ echo $PATH
## OK!
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/kusanagi/.local/bin:/home/kusanagi/bin
composerコマンドが利用できるか確認します。
$ composer -V
Composer version 1.2.3 2016-12-01 14:33:53
composerコマンドが使えるようになったので、Laravelのプロジェクトを作ります。
まずはkusanagi_htmlへ移動します。このディレクトリ名はプロビジョニングの時に指定したディレクトリ名です。
$ cd /home/kusanagi/kusanagi_html
$ ll
drwxrwxrwx 5 kusanagi kusanagi 4096 11月 23 16:50 DocumentRoot
drwxr-xr-x 4 kusanagi kusanagi 4096 11月 23 16:50 log
kusanagi_htmlに移動すると初期では上記のようなディレクトリ構成になっていることが確認できると思います。
kusanagiではデフォルトでDocumentRootというディレクトリをWebサーバソフトウェアの公開領域に割り当てているのですが、Laravelの場合はLaravelのプロジェクトディレクトリ/public
というディレクトリが公開領域として想定されていますので、ここを少し変更します。
まずは、DocumentRootを削除します。
$ rmdir DocumentRoot
$ ll
drwxr-xr-x 4 kusanagi kusanagi 4096 11月 23 16:50 log
Laravelのプロジェクトをlaravelというディレクトリの直下に作成します。プロジェクトをDocumentRoot直下に作っても良かったんですが名前的に紛らわしいので今回はそれは避けることにします。
$ composer create-project laravel/laravel laravel "5.1.*"
無事インストールが終了すると下記のようなディレクトリ構成になります。場合によってはPHPモジュールが足りないと怒られることがありますが、KUSANAGIの場合はLaravelに必要なモジュールが揃っているのでまず失敗することはないでしょう。
$ ll
drwxr-xr-x 11 kusanagi kusanagi 4096 12月 11 16:49 laravel
drwxr-xr-x 4 kusanagi kusanagi 4096 11月 23 16:50 log
$ cd laravel
$ ll
drwxrwxr-x 10 kusanagi kusanagi 4096 4月 5 2016 app
-rwxr-xr-x 1 kusanagi kusanagi 1646 4月 5 2016 artisan
drwxrwxr-x 3 kusanagi kusanagi 4096 4月 5 2016 bootstrap
-rw-rw-r-- 1 kusanagi kusanagi 1214 4月 5 2016 composer.json
-rw-rw-r-- 1 kusanagi kusanagi 119369 12月 2 16:51 composer.lock
drwxrwxr-x 2 kusanagi kusanagi 4096 4月 5 2016 config
drwxrwxr-x 5 kusanagi kusanagi 4096 4月 5 2016 database
-rw-rw-r-- 1 kusanagi kusanagi 503 4月 5 2016 gulpfile.js
-rw-rw-r-- 1 kusanagi kusanagi 159 4月 5 2016 package.json
-rw-rw-r-- 1 kusanagi kusanagi 87 4月 5 2016 phpspec.yml
-rw-rw-r-- 1 kusanagi kusanagi 1026 4月 5 2016 phpunit.xml
drwxrwxr-x 2 kusanagi kusanagi 4096 12月 2 17:16 public
-rw-rw-r-- 1 kusanagi kusanagi 1928 4月 5 2016 readme.md
drwxrwxr-x 5 kusanagi kusanagi 4096 4月 5 2016 resources
-rw-rw-r-- 1 kusanagi kusanagi 567 4月 5 2016 server.php
drwxrwxr-x 5 kusanagi kusanagi 4096 4月 5 2016 storage
drwxrwxr-x 2 kusanagi kusanagi 4096 4月 5 2016 tests
drwxrwxr-x 30 kusanagi kusanagi 4096 12月 2 16:51 vendor
Webサーバソフトウェア(nginx)のドキュメントルート指定を変更します。
書き換えるのはrootの箇所です。
$ sudo vim /etc/nginx/conf.d/kusanagi_html_http.conf
# 該当の箇所を下記のように書き換える。
root /home/kusanagi/kusanagi_html/laravel/public;
nginxを再起動します。せっかくなのでkusanagiのnginxサブコマンドで再起動します。
$ sudo kusanagi nginx
Nginxを使用します。
完了しました。
切り替わりました。簡単ですね。
これでほぼやるべきことをやりましたが、Laravel5.1の場合あとすこしだけやるべきことがあります。
公式ドキュメントのディレクトリーパーミッションの項を見ると、storageディレクトリとbootstrap/cacheをWebサーバから書き込み可能にして下さいとあります。
$ ll -d storage/
drwxrwxr-x 2 kusanagi kusanagi 4096 4月 5 2016 app
drwxrwxr-x 5 kusanagi kusanagi 4096 4月 5 2016 framework
drwxrwxr-x 2 kusanagi kusanagi 4096 12月 11 16:51 logs
$ ll -d bootstrap/cache/
drwxrwxr-x 2 kusanagi kusanagi 4096 12月 2 16:51 bootstrap/cache/
ユーザーとグループに書き込み権限があるようですが、kusanagiとなっていてWebサーバの権限からは書き込めないようになっています。かといって安易に777なんてパーミッションにするにはセキュリティ的な観点から好ましくありません。
そんな時のためのKUSANAGIではWebサーバのプロセスに対してhttpdユーザー、wwwグループが割り当てられているので、Webサーバが書き込まなければならないディレクトリに対しては、所有者をhttpd、グループをwwwにします。
なお、デフォルトではkusanagiユーザーはwwwグループにも属しているので、Webサーバが作成したディレクトリやファイルにkusanagiユーザーが書き込むことができないというようなことにはなっていません。まあ、このあたりは要件によってパーミッションを制限してもよいでしょう。
$ id kusanagi
uid=1001(kusanagi) gid=1001(kusanagi) groups=1001(kusanagi),1000(www)
$ id httpd
uid=1000(httpd) gid=1000(www) groups=1000(www)
$ sudo chown -R httpd.www storage/
$ sudo chown -R httpd.www bootstrap/cache/
$ ll -d storage/
drwxrwxr-x 5 httpd www 4096 4月 5 2016 storage/
$ ll -d bootstrap/cache/
drwxrwxr-x 2 httpd www 4096 12月 2 16:51 bootstrap/cache/
これで、Webサーバからstorage/、bootstrap/cache/を書き込めるようになったので、Laravelが動作する準備が完全に整いました。
ブラウザからアクセスしてみます。
LaravelデフォルトのTOPページが表示されました。白すぎてわかりにくいですが😅
LAMP環境とのベンチマークは冒頭に述べたとおりです。
LAMPに関してもさくらのクラウドの画面で、KUSANAGIを立てたスペックと全く同じプランでサーバを立て、Laravelをインストールしました。Laravelの導入はともかく、ミドルウェアの導入、ファイルウォールの設定などを1からやるのが結構めんどくさかったです。。
さて、ここで最後にもう1パターンのベンチマークを検証しましょう。
先程のKUSANAGIはLAMP環境と比較したものの、実はミドルウェアの観点からみると、LEMP環境で動作していました。Webサーバソフトウェアがnginxだったんですね。
個人的にはKUSANAGIはnginxで使うことをオススメしているのですが、もちろんApacheでの使用も可能です。
Apacheを使えば本当の意味でKUSANAGIはLAMP環境同士の比較になり、厳密な比較になるのでやってみましょう。
ミドルウェアの構成変更についてはkusanagiのhttpdサブコマンドで一瞬で環境をApacheに切り替えることができますが、nginxの時にご説明したとおり、KUSANAGIでは現状公開ディレクトリがDocumentRootという名前のディレクトリになっているので、ここを編集しておきます。
このへんは正式にKUSANAGI for Laravelの為に自動化のコントリビュートをしたいところです😄
$ sudo vim /etc/httpd/conf.d/kusanagi_html_http.conf
# 該当の箇所を下記のように書き換える。
DocumentRoot /home/kusanagi/kusanagi_html/laravel/public
<Directory "/home/kusanagi/kusanagi_html/laravel/public">
この状態でkusanagiのhttpdサブコマンドを打つとApacheに切り替わります。
$ sudo kusanagi httpd
httpd を使用します
完了しました
$ sudo kusanagi status
*** nginx ***
● nginx.service - The NGINX HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: inactive (dead)
*** Apache2 ***
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since 火 2016-12-13 09:28:00 JST; 10min ago
*** HHVM ***
● hhvm.service - HHVM virtual machine, runtime, and JIT for the PHP language
Loaded: loaded (/etc/systemd/system/hhvm.service; disabled; vendor preset: disabled)
Active: inactive (dead)
*** php-fpm ***
● php-fpm.service - The PHP FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; disabled; vendor preset: disabled)
Active: inactive (dead)
*** php7-fpm ***
● php7-fpm.service - The PHP FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/php7-fpm.service; enabled; vendor preset: disabled)
Active: active (running) since 火 2016-12-13 00:20:28 JST; 9h ago
Active: activeとなっているミドルウェアが動作しているので、PHP7とApacheで動いていることがわかります。
$ ab -n 1000 -c 100 http://kusanagi-laravel.jp/
Server Software: Apache
Server Hostname: kusanagi-laravel.jp
Server Port: 80
Document Path: /
Document Length: 1023 bytes
Concurrency Level: 100
Time taken for tests: 2.881 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 2017120 bytes
HTML transferred: 1023000 bytes
Requests per second: 347.07 [#/sec] (mean)
Time per request: 288.124 [ms] (mean)
Time per request: 2.881 [ms] (mean, across all concurrent requests)
Transfer rate: 683.68 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.5 0 7
Processing: 16 273 59.6 280 687
Waiting: 16 273 59.6 280 687
Total: 20 274 58.7 281 688
Percentage of the requests served within a certain time (ms)
50% 281
66% 285
75% 288
80% 290
90% 303
95% 325
98% 397
99% 481
100% 688 (longest request)
Requests per secondが__347.07__となっています。
nginxよりは劣るものの、通常のLAMP環境が__37.13__でしたので、同じLAMP環境でも10倍弱のパフォーマンスを出すことができました👏
まとめ
このようにKUSANAGIは超高速WordPress仮想マシンと謳っているものの、その他のLAMP、LEMPベースのアプリケーションでも高いパフォーマンスを発揮することを確認することができました。
今回のようにLaravelの実行環境としてはもちろん、まだ誰も試していない他のアプリケーションでもKUSANAGIの力を試してみて下さい👍
明日は@makoto1899さんです。