1. hirohero

    No comment

    hirohero
Changes in body
Source | HTML | Preview
@@ -1,91 +1,91 @@
かどうかは別として、こんな構成もできるよ。というネタと思っていただければ。(笑)
**ご注意: この構成は所属先の見解ではなく、また、実運用の実績があるものではありません。あくまでも情報の一つとしてお読みください。**
php-fpm(fastcgi)によるAPIサーバを建てるにあたって、LBをフロントエンドに置いて負荷分散。
というのは当たり前すぎる構成ですね。
図にするとこんな感じ。
![スクリーンショット 2017-03-26 14.31.39.png](https://qiita-image-store.s3.amazonaws.com/0/145575/1a5226b0-c4f8-3421-1a20-be111a91f1f1.png)
さて、ここからが本題。
APIサーバということは、全てのリクエストはフレームワークを経由することになります。
最近のフレームワークは`public/index.php`を単一のフロントコントローラとしているものがほとんどです。
LaravelやLumenなどがそうですね。
ということは、バックエンド側にはwebサーバは不要だと思いませんか? phpの処理系である`php-fpm`デーモンだけが立っていれば良いと思いませんか?
図にするとこんな感じ。
![スクリーンショット 2017-03-26 14.31.19.png](https://qiita-image-store.s3.amazonaws.com/0/145575/47d5496f-995f-212d-7dab-35642743042d.png)
`php-fpm`はTCP/IPをlistenできるので、元々こういう使い方も想定されているわけですね。
-この構成だとwebサーバが1つ減るのでオーバヘッドが減ります。CPU処理コスト、メモリ消費、アクセスログの書き出しアクセス、(webサーバ → php-fpmの)内部接続コストがなくなります。サーバ間の役割がはっきり分離できるのもポイントだと思いませんか?
+この構成だとwebサーバが1つ減るのでオーバヘッドが減ります。CPU処理コスト、メモリ消費、アクセスログのディスクI/O、(webサーバ → php-fpmの)内部接続コストがなくなります。サーバ間の役割がはっきり分離できるのもポイントだと思いませんか?
静的ファイルについてはフロントエンド側で対応するか、静的専用のwebサーバを建てるか、S3のwebホスティングを使うか、CDNを使えば十分ですね。
# 具体的な設定方法
nginxをフロントエンド(LB)にした場合の設定例です。
httpsでリクエストを受けてSSL terminationをした上で、複数のバックエンドにラウンドロビンでロードバランスする構成です。
## php-fpm(バックエンド側)
こちらは極めて単純。
listenアドレスに`0.0.0.0`を指定してデーモンを再起動するだけ。
```ini:/etc/php/fpm-php7.1/fpm.d/www.conf
listen = 0.0.0.0:9000
```
## nginx(フロントエンド側)
```nginx:/etc/nginx/conf.d/frontend.conf
upstream backends {
server [backend IP 1]:9000;
server [backend IP 2]:9000;
}
server {
listen 443 ssl http2;
server_name site.localdomain;
charset utf-8;
root /var/www/html;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# SSL terminationをする場合
ssl on;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
try_files $uri /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass backends;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME [php-fpm側のindex.phpがあるディレクトリのpath]$fastcgi_script_name;
include fastcgi_params;
}
}
```
ポイントは3つ。
- バックエンド側の`php-fpm`サーバを、upstreamとして登録する。
- **nginx側のrootディレクトリ(`/var/www/html`)に、ダミーのindex.phpファイルを作成しておく。(重用)**
- `SCRIPT_FILENAME` は php-fpm側のindex.phpがあるディレクトリを指定する。
ダミーのindex.phpが必要なのは、`try_files`でリクエストURLが`/index.php`に変換されて存在チェックが入るからです。
このチェックが通らないと、`location ~ \.php$`に制御が渡らず`404 NotFound`となってしまいます。
`index.php`ファイルは存在している事自体が重要なので、中身は空でもかまいません。
```bash
touch /var/www/html/index.php
```
このあたりがもう少しエレガントに設定できれば良いのですが、他の方法が思いつきませんでした。
一応手元で環境構築してテストしたところ、ちゃんとラウンドロビンされてることと、バックエンドサーバを停止したらそこへの振り分けが停止され、バックエンドサーバを再開したら再度振り分け対象になったことは確認できました。