このページでは主に Nginx のモジュールや設定関連のメモを書いています。
Modules
構築
- CentOS 6.4 (x86_64)
- Nginx 1.4.1
- gcc 4.4.7
Nginx 1.4からはSPDYに対応しているので --with-http_spdy_module 付けてコンパイルすれば有効になります。
設定
ここではNginxの設定に関することを載せます。
基本
Nginxの設定ファイルはApacheのものと比べると簡潔で読みやすくなっています。ここでは基本設定項目をいくつかピックアップして紹介します。
- ''URI毎の処理 (location)''
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... } Context: server, location
リクエストURI毎の処理を記述するディレクティブになっています。 uri には正規表現を適用できますが、付与するプレフィックスによって適用順序に違いがあります。また、uri の代わりに @{任意の名前} で設定することもできます。この記法は後述の try_files ディレクティブと併せて内部リダイレクトを行うときによく使われます。プレフィックス 説明 なし 前方一致 ''='' 完全一致 見つかったら検索終了 ''^~'' 前方一致 見つかったら検索終了 ''~'' 正規表現 (大文字・小文字を区別する) ''~*'' 正規表現 (大文字・小文字を区別しない) - ''URIの書き換え (try_files)''
Syntax: try_files file ... uri try_files file ... = code Context: server, location
file が存在しなかったときに uri にリダイレクトします。uri はいくつも指定できます。## 例 location /path/to { try_files $uri $uri/ @foo; } location @foo { ... }
- ''ログファイルの設定 (access_log, log_format)''
ログフォーマットに利用できる主な変数を以下に挙げます。これ以外の変数については公式サイトなどを参照してください。変数 概要 $remote_addr クライアントのIPアドレス $time_local アクセス日時 $request リクエストURL $request_length リクエストボディの長さ $status HTTPステータスコード $body_bytes_sent 送信バイト数(レスポンスヘッダのバイト数を引いた値) $http_referer リファラーURL(遷移元URL) $http_user_agent ユーザエージェント(ブラウザ名・バージョン等) ## ログフォーマットの指定例 (mainという名前で設定) log_format main '$remote_addr [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent"'; ## ログファイルのパス access_log /var/log/nginx/access.log main;
上記の設定例だと以下のようなログが出力されます。203.216.243.240 [02/May/2013:00:14:57 +0900] "GET /archives/1826/ HTTP/1.1" 200 8080 "http://rest-term.com/archives/1777/" "Mozilla/5.0 (Windows NT 6.1; rv:20.0) Gecko/20100101 Firefox/20.0"
- ''Keep Alive時間の設定 (keepalive_timeout)''
接続を維持する時間を設定します。同時接続数の多いサイトでは問題が起こるので適切に設定する必要があります。この設定はNginxに限らず他のHTTPサーバでも同様です。keepalive_timeout 65; ## 65秒コネクションを維持 keepalive_timeout 0; ## 0 にするとKeep Alive無効
- ''Expiresヘッダの付与 (expires, log_not_found)''
画像ファイルやJavaScript/CSSファイルなどに Expires ヘッダを付与してブラウザにコンテンツをキャッシュさせることでHTTPリクエスト数を削減します。また、これらのファイルへのアクセスログは基本的に不要なので出力しないようにします。location ~* \.(gif|jpg|png|ico|js|css|woff)$ { expires 30d; ## Expiresヘッダの有効期限を30日に指定 access_log off; log_not_found off; }
- ''リクエストサイズ制限 (client_max_body_size)''
HTTPリクエストのエンティティサイズ制限を設定します。ここで設定したサイズを超えたリクエストを受けると、"413 Request Entity Too Large" エラーをクライアントに返します。大きなサイズのファイルをアップロードしたいときはこの項目を設定します。デフォルトは1MBです。client_max_body_size 10M; ## 10MBに制限
ただし多くの場合、PHPなどのサーバサイド処理系毎の設定も必要となります。PHPの場合は、upload_max_filesize などの設定も併せて行ってサイズ制限を設定します。 - ''その他雑多設定''
以下の設定は特に行わなくてもHTTP配信機能的には問題ありません。- バージョン表示を隠す (server_tokens)
セキュリティ等の観点でServerヘッダにNginxのバージョンを付けたくない場合は以下のディレクティブを指定します。server_tokens off;
- pidファイルの場所を変える (pid)
デフォルトだと logs/nginx.pid になっていて気持ち悪いので /var/run 以下に作成するように変更します。pid /var/run/nginx.pid;
- バージョン表示を隠す (server_tokens)
モジュール機能
コンテンツの圧縮転送
- HttpGzipModule (core module)
gzipによるファイル圧縮転送を行うことができます(Apacheの場合は mod_deflate の機能)。設定ファイルには以下のように記述します。ディレクティブ数が多めなので別ファイルにして nginx.conf 内で include しても良いかもしれません。gzip on; ## gzip圧縮を有効化 gzip_http_version 1.0; ## 圧縮転送を行うHTTPのバージョン, 1.0にしておけば1.1でも有効化される gzip_types text/plain ## 圧縮対象ファイルのMIME Type text/xml text/css application/xml application/xhtml+xml application/rss+xml application/atom_xml application/javascript application/x-javascript application/x-httpd-php; gzip_disable "MSIE [1-6]\."; ## 圧縮転送を無効にするUser-Agent (IE) gzip_disable "Mozilla/4"; ## (Firefox) gzip_comp_level 1; ## gzip圧縮レベル(0-9), 0だと圧縮なし, 1以上にしても圧縮率の変化は少ない gzip_proxied any; ## プロキシ経由でも圧縮転送 gzip_vary on; ## Vary ヘッダを付与 gzip_buffers 4 8k; ## gzip圧縮処理で利用するバッファサイズ, 4*8kb=32kb gzip_min_length 1024; ## gzip対象とするファイルの最小サイズ, 1024bytes以下のファイルは圧縮対象外 gzip_static on; ## 静的圧縮ファイルの転送を有効化
- HttpGzipStaticModule
cssやjsファイル等が予めgzip圧縮されて置いてある場合にその圧縮ファイル(.gz)を代わりに転送してくれます。この機能により、リクエスト毎のgzip圧縮処理が省略されるためCPUリソースを節約することができます。HttpGzipStaticModule はコアモジュールではないのでコンパイル時に別途組み込む必要があります。$ ./configure --with-http_gzip_static_module
サーバステータスの取得
- HttpStubStatusModule
サーバステータスの取得を行いたい場合は HttpStubStatusModule の機能を利用します(Apacheの場合は mod_status の機能)。Muninなどでリソースモニタリングする際に必要となります。location = /nginx_status { ## /nginx_status がエンドポイント stub_status on; ## ステータス取得機能を有効化 access_log off; ## アクセスログを出力しない allow 127.0.0.1; ## 127.0.0.1 ホストのみアクセス可能 deny all; ## それ以外のホストはアクセス拒否 }
- 動作確認
$ curl -v http://127.0.0.1/nginx_status * About to connect() to 127.0.0.1 port 80 (#0) * Trying 127.0.0.1... connected * Connected to 127.0.0.1 (127.0.0.1) port 80 (#0) > GET /nginx_status HTTP/1.1 > User-Agent: curl/7.21.7 (x86_64-unknown-linux-gnu) libcurl/7.21.7 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 libssh2/1.2.8 > Host: 127.0.0.1 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx < Date: Wed, 13 Jun 2012 13:51:12 GMT < Content-Type: text/plain < Content-Length: 109 < Connection: close < Active connections: 1 server accepts handled requests 10991 10991 10985 Reading: 0 Writing: 1 Waiting: 0 * Closing connection #0
- 動作確認
HttpStubStatusModule もコアモジュールではないのでコンパイル時に別途組み込む必要がます。
$ ./configure --with-http_stub_status_module
キャッシュコンテンツの配信 (memcached連携)
- HttpMemcachedModule (core module)
memcachedにキャッシュされたコンテンツを配信したい場合は HttpMemcachedModule の機能を利用します。キャッシュミスした場合はバックエンドサーバにプロキシする構成を採ることが多いので、併せて HttpUpstreamModule の機能も利用します。upstream backend { ip_hash; ## IPハッシュによる分散 server foo.co.jp; server bar.co.jp; } server { location / { ## その他設定項目は省略 ## POSTリクエストはバックエンドへ if($request_method = POST) { proxy_pass http://backend; break; } set $memcached_key $request_uri; ## キャッシュキーはリクエストURI memcached_pass 127.0.0.1:11211; ## memcachedのhost:portを指定 default_type text/html; error_page 404 502 = @fallback; ## キーが見つからないあるいはmemcachedに接続できなければバックエンドへ } location @fallback { ## バックエンドサーバ(アプリケーションサーバ)にプロキシ proxy_pass http://backend; } }
また、Nginx 1.1.4からはupstreamで設定したバックエンドサーバにもKeep-Alive接続可能になっています。
MP4ファイルのHTTP Pseudo-Streaming配信
- HttpMp4Module
MP4(H.264/AAC)ファイルのHTTP Pseudo-Streaming(HTTPによる疑似ストリーミング)機能をサポートしています。
ブログの方でもまとめているので参考までに(NginxのHTTP Pseudo-Streamingを試す)。## /video 以下にアクセスされたらMP4ファイルのPseudo-Streaming配信機能を有効にする location /video { mp4; mp4_buffer_size 1m; ## バッファサイズ(デフォルト512KB) mp4_max_buffer_size 5m; ## 最大バッファサイズ(デフォルト10MB) }
拡張子でマッチさせる設定を入れなくても .mp4/.m4v/.m4a は判別してくれるようです。atomデータ処理する時にバッファが足りなくなった場合はHTTP 500エラーが返るので適宜調整してください。- アクセス
HTTPでMP4ファイルのあるパスにアクセスするだけです。その際にクエリパラメータ(start)として再生開始位置(秒)を指定します。動画の尺を超える値を入れるとHTTP 500エラーが返ります。http://example.com/video/sample.mp4?start=123
- アクセス
HttpMp4Module はコアモジュールではないのでコンパイル時に別途組み込む必要があります。
$ ./configure --with-http_mp4_module
アプリケーションコンテナ
NginxではApacheにおける mod_php や mod_wsgi などのようにHTTPサーバに言語処理系自体を組み込むのではなく、アプリケーションコンテナを単独のプロセスとして稼働させ、リクエストを適宜対応するコンテナにプロキシする構成を採ることが多いです。
PHP-FPM
PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites.
公式サイト: PHP-FPM
PHPアプリケーションコンテナの実装の一つ。このWikiも Nginx + PHP-FPM 上で動作している。
導入
RedHad系なら yum でインストールできます。
$ sudo yum install php-fpm.x86_64
設定
パラメータチューニング関連の設定項目を整理します。
pm | 子プロセスをどのように生成するか。(static/ondemand/dynamic) |
pm.max_children | 子プロセスの最大数。Apacheでいうところの MaxClients に該当。 |
pm.max_requests | 子プロセスが再起動するまでに受け付けるリクエスト数。Apacheでいうところの MaxRequestsPerChild に該当。 |
pm.start_servers | 起動時に作成される子プロセスの数。(pm が dynamic の時のみ) |
pm.max_spare_servers | アイドル状態のサーバープロセスの最大値。(pm が dynamic の時のみ) |
pm.min_spare_servers | アイドル状態のサーバープロセスの最大値。(pm が dynamic の時のみ) |
slowlog | 処理に時間のかかったリクエストを記録するログファイル。(デフォルト $INSTALL_PREFIX/log/php-fpm.log.slow) |
次に nginx.conf を編集します。Nginxと同じホストで稼働させる場合はUNIXドメインソケットで通信すると効率的です。
# pass the PHP scripts to FastCGI server listening on unix domain socket location ~ \.php$ { include fastcgi.conf; fastcgi_pass unix:/var/run/php-fpm/www.sock; fastcgi_index index.php; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name; fastcgi_intercept_errors on; }
- fastcgi.conf
fastcgi.confファイルは以下のようになっています。fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200;
uWSGI
uWSGI is a fast, self-healing and developer/sysadmin-friendly application container server coded in pure C.
公式サイト: uWSGI (WSGI: Web Server Gateway Interface)
WSGIアプリケーションコンテナの実装の一つ。
- 対応プラットフォーム
Portability (tested on Linux 2.6/3.x, Solaris/OpenSolaris/OpenIndiana, OpenBSD, NetBSD, DragonflyBSD, FreeBSD >= 8.0, MacOSX, Nexenta, and Haiku)
FreeBSDでは8.0以降が対象らしい。2012年現在、7.x系を現役で使っている人はまだそこそこいるような気はします。 - 対応言語
もともとuWSGIはPythonアプリケーションを対象としていましたが、現在ではPerl, Ruby, PHP, Luaなど多くの言語に対応しています。ここではPythonアプリケーションの動作確認までを行います。
導入
- pipを利用する場合
現在ではpipで簡単にインストールできます。Linuxへのpipの導入は割愛。FreeBSD8.0以降の場合は {PORTS_DIR}/devel/py-pip へ異動後、make install すればpipが利用可能になります。$ sudo pip install uwsgi
- ソースからインストールする場合
$ wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz ## 最新版を取得 $ tar zxf uwsgi-latest.tar.gz $ make
後は出来上がったuwsgiバイナリをPATHの通った任意の場所に置きます。
設定
nginx.conf を編集します。ここではuWSGIサーバを 127.0.0.1:8000 で稼働させている場合(TCPソケット)の設定になっています。
## pass the Python scripts to uWSGI server listening on 127.0.0.1:8000 location ~ ¥.py$ { uwsgi_pass 127.0.0.1:8000; include uwsgi_params; }
- uwsgi_param
uwsgi_paramファイルは以下のような内容になっています。uwsgi_param QUERY_STRING $query_string; uwsgi_param REQUEST_METHOD $request_method; uwsgi_param CONTENT_TYPE $content_type; uwsgi_param CONTENT_LENGTH $content_length; uwsgi_param REQUEST_URI $request_uri; uwsgi_param PATH_INFO $document_uri; uwsgi_param DOCUMENT_ROOT $document_root; uwsgi_param SERVER_PROTOCOL $server_protocol; uwsgi_param HTTPS $https if_not_empty; uwsgi_param REMOTE_ADDR $remote_addr; uwsgi_param REMOTE_PORT $remote_port; uwsgi_param SERVER_PORT $server_port; uwsgi_param SERVER_NAME $server_name
アプリケーション
動作確認用のWSGIアプリケーションを準備します。
- hello.py
起動
アプリケーション毎にuWSGIサーバを立ち上げます。
$ uwsgi --socket 127.0.0.1:8000 --file hello.py ## シングルプロセスモードで起動
- YAMLファイルによる設定
uwsgiアプリケーションの各種設定はYAMLファイルで設定可能です。hello: master: 1 processes: 1 socket: 127.0.0.1:8000 wsgi-file: /var/www/html/labs/hello.py callable: app max-request: 1000 daemonize: /var/log/uwsgi/hello.log pidfile: /var/run/hello.pid
以下のように --yaml オプションの後に YAMLファイル名:アプリケーション名 と指定して起動します。$ uwsgi --yaml uwsgi.yaml:hello [uWSGI] getting YAML configuration from uwsgi.yaml
動作確認
ブラウザから /hello.py にアクセス(拡張子が.pyならなんでもいい)して hello, world と表示されたらOK。
モジュール開発
Nginxモジュールの開発手順についてメモしていきます。
atodekaku