nginxについてまとめ(Appサーバ編)


## 概要
前回:

- [nginxについてまとめ(導入編)](http://qiita.com/morrr/items/929e9cb35914a7f3a652)
- [nginxについてまとめ(設定編)](http://qiita.com/morrr/items/7c97f0d2e46f7a8ec967)

今回はnginxをアプリケーションサーバとして利用するため、その動作の仕組みと設定方法を調査した。


## nginxでアプリケーションが動く仕組み

### 内部/外部実行
ApacheをAppサーバとして動作させる場合、その方法は大きく2つあった。

- 1. 内部実行。`mod_*`を使って、Apache自身がアプリケーションを実行する
- 2. 外部実行。CGIなどのAPIを使って、別のAppサーバにアプリケーションを実行させる


nginxは、アプリケーションを__内部実行する仕組みを持たない__ため、2. 外部実行の形でアプリケーションを動かす。
つまり__nginx自体にAppサーバの機能は無く__、nginx(Webサーバ)とAppサーバを組み合わせることで、１台のWeb兼Appサーバとして動作する。


### APIの種類
WebサーバとAppサーバを接続するためのAPIには復数の仕様があり、nginxはそれらに対応している。

#### FastCGI
- 汎用のインタフェース。CGIの改良版
- 旧来のCGIと異なり、アプリケーションプロセスが常時起動しているため低負荷、高速
- TCP通信のほか、同じOS内の場合はIPCソケットでも通信可能

#### Python WSGI
- Python用のWeb API

#### Ruby Rack
- Ruby用のWeb API

などなど。


### Appサーバの種類
APIの実装であるAppサーバも、対応するAPIと言語の組み合わせにより様々ある。

#### php-fpm
- fpm =FastCGI Process Manager
- FastCGIのAppサーバ
- nginxでPHPを動かす場合はこれがメジャーな様子

#### Passenger
- 別名`mod_rails`。もともとはApacheでrails(ruby)を内部実行するためのモジュール
- スタンドアロンモードを備えており、これによってRackサーバとして動作する
- Ruby on Rails標準採用
- Python / WSGIも使える

#### uWSGI
- WSGIのAppサーバ
- WSGI準拠であればPythonにかぎらず復数言語で利用できる(っぽい)

などなど。


## 設定方法
設定の詳細は選択した言語やAppサーバによりけりだが、共通した手順としては以下:

### 1. Appサーバをたてる
利用したい言語環境により、適切なAppサーバを選択し構築する。
構築したAppサーバはサービス(デーモン)としてサーバOS上に常駐させる。

### 2. nginxからAppサーバを接続する

特定のアクセスがあった場合にAppサーバが呼び出されるよう、nginxの設定ファイルを変更する。

- 設定項目はAPI単位で別のモジュールとして構成されていて、`fastcgi_*`, `uwsgi_*`のように異なるディレクティブを使う。

- またPassengerのように、nginx標準ではなく、サードパーティのnginxモジュールが提供されていることもある。

以下は、php-fpm(FastCGI)で構築したサーバに接続する設定例:

```bash:nginx.conf
http{
    server{
        # .phpとつくURLにアクセスがあった場合の設定
        location ~ \.php${

            # FastCGIサーバのIPとポート番号
            # localhost(127.0.0.1)の9000ポートを指定
            # 外部サーバでもいい
            fastcgi_pass    127.0.0.1:9000;

            # FastCGIにおけるindexファイルの指定
            fastcgi_index  index.php;

            # ファイル名をFastCGIサーバに変数として渡す
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

            # nginx標準のFastCGI用設定ファイル(/etc/nginx/fastcgi_param)の読込み            
            include    fastcgi_params;
        }
    }
}
```


## 注意点

__nginxはAppサーバの冗長化ができないらしい__。

- [Stack Overflow - fastcgi multiplexing?](http://stackoverflow.com/questions/7912322/fastcgi-multiplexing)
- [Why Nginx Doesn't Implement FastCGI Multiplexing?](https://forum.nginx.org/read.php?2,237158,237158)


そもそもAppサーバが1台で間に合うような中小規模サイトであればApacheで間に合ってしまうわけなので、nginxを利用する状況においては、Appサーバをスケールさせたいケースが多いように思える。

nginxにAppサーバを直結するのではなく、webサーバ+Appサーバを1台のサーバとしてまとめておき、それをnginxでロードバランシングするやり方のほうが適切なのかもしれない。


なおRailsの設定例などを調べてみても、今回まとめたような

nginx(Webサーバ) → Passenger(Appサーバ) → Rails

の直結型ではなく、

nginx(ロードバランサ) → unicorn(Webサーバ) → Passenger(Appサーバ) → Rails

の構成例が多かった。



## 参考
### 仕組み
- [Why is FastCGI /w Nginx so much faster than Apache /w mod_php?](http://www.eschrade.com/page/why-is-fastcgi-w-nginx-so-much-faster-than-apache-w-mod_php/)
- [Qiita - Rails開発におけるwebサーバーとアプリケーションサーバーの違い（翻訳）](http://qiita.com/jnchito/items/3884f9a2ccc057f8f3a3)
- [Qiita - nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する](http://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc)
- [php-fpm](http://php-fpm.org/)
- [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/)
- [Wikipedia - Phusion Passenger](https://ja.wikipedia.org/wiki/Phusion_Passenger)

### 設定詳細
- [nginx - Module ngx_http_fastcgi_module](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html)
- [nginx - Module ngx_http_uwsgi_module](http://nginx.org/en/docs/http/ngx_http_uwsgi_module.html)
- [Passenger Library - Configuration reference](https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_root)

- [Qiita - Homebrewをインストール！ついでにNginx, PHP-FPM, MySQLも！](http://qiita.com/takeshi81/items/0f21a9469be296aea5bd)
- [Qiita - CentOSにてnginxでPHPを動かす](http://qiita.com/utano320/items/36b6eac2bbd5bb5657f6)
- [Qiita - macにnginx + php-fpmを導入する際の手順](http://qiita.com/makotok7/items/2ca1c50d37cb2f8f3972)