Node.jsのアプリケーションで、数回に一回程度、CSSやJQueryのアクセス時にHTTP500 Internal Server Error が発生して、ウェブ画面の表示や動作が壊れる障害があり、対策についての備忘録です。
Expressフレームワークの express-generator でテンプレート・アプリケーションを生成すると、次のディレクトリ構造が作られる。そして、public ディレクトの stylesheets に CSSファイルを置いて、また、javascriptsの下にjquery.js 等を置いて、利用したところ、本問題に直面した。
.
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.pug
├── index.pug
└── layout.pug
問題判別
調べた結果では、Node.jsのHTTP500の発生原因は解りませんでしたが、CSSファイルやJQueryなどスタティックなコンテンツの要求の応答の課程でHTTP500が発生していることが解ってきました。 また、この障害は3種類 (FireFox, Chrome, Safari)で同様に発生してました。
また、Node.js のバージョンを 6.11 から 8.6へ、バージョンを上げてみましたが、改善しませんでした。
対策
回避策として、次の図の様に、public コンテンツ以下は、Nginxのコンテナで応答して、それ以外のNode.jsの処理は、Node.jsのコンテナへ転送する対策を試みました。
この結果、CSSやJQuery等の静的ファイルのロードで、HTTP500が発生する事が無くなり、ウェブ画面が壊れる障害が事が無くなりました。
nginxリバースプロキシ設定ファイル
Nginxの設定ファイルは次の2つです。 最初、キャッシュ・プロキシーの設定だけを試しましたが改善が見られず、locationの設定を追加してところ、動作が改善して安定しました。
proxy_cache_path /var/cache/nginx keys_zone=zone1:1m max_size=1g inactive=24h;
proxy_temp_path /var/cache/nginx_tmp;
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache zone1;
location / {
proxy_pass http://node_app:3000/;
}
location /javascripts/ {
alias /usr/share/nginx/html/javascripts/;
}
location /stylesheets/ {
alias /usr/share/nginx/html/stylesheets/;
}
location /images/ {
alias /usr/share/nginx/html/images/;
}
}
Dockerコンテナのファイル
次の2つが、コンテナを作るためのDockerfileです。
FROM nginx:latest
ADD ./nginx_conf/default.conf /etc/nginx/conf.d/default.conf
ADD ./nginx_conf/nginx.conf /etc/nginx/conf.d/nginx.conf
COPY ./webapp1/public /usr/share/nginx/html
FROM ubuntu:latest
RUN apt-get update && apt-get install curl -y
RUN curl -sL https://deb.nodesource.com/setup_6.x | /bin/bash -
RUN apt-get install nodejs -y
ADD /webapp1 /webapp1
ENV NODE_ENV development
EXPOSE 3000
CMD ["node", "/webapp1/bin/www"]
docker-composeのYAMLファイル
NginxコンテナとNode.jsコンテナを連携して起動するためのファイルです。
version: '3'
services:
proxy_cache:
build:
context: .
dockerfile: Dockerfile.nginx
ports:
- "4040:80"
depends_on:
- node_app
node_app:
build:
context: .
dockerfile: Dockerfile.nodejs
ports:
- "3000:3000"
まとめ
Node.js の Express フレームワークで、publicの下に静的コンテンツを置くのは、要注意である。 そして、時々、スタイルシートやJQueryがロードされずウェブ画面の表示や動作が安定しない場合、静的コンテンツの処理をNginxでオフロードすると効果的である。 Dockerコンテナを適用することで、サーバーを増やさず効率良く対処できた。 さらに、この方法は、Kubernetesの利用時にも適用できると見込まれる。