Syntax Error.

[Sy] nginx(リバースプロキシ)+node.jsでconnect() failedが頻発する場合の対処

2015/07/16

nginxをリバースプロキシとして、node.jsのアプリを動かしてる環境で、nginxのエラーログ(/var/log/nginx/error.log)にconnect() failed (111:Connection refused)ってのが結構出てたので、その時の対処の手順です。

エラーの内容は以下。(URL等は適当に書き換えてます)

2015/07/16 15:04:40 [error] 2186#0: *44163 connect() failed (111: Connection refused) while connecting to upstream, client: xxx.xxx.xxx.xxx, server: host-a.example.com, request: "GET /index.html HTTP/1.1", upstream: "http://[::1]:3002/index.html", host: "host-a.example.com", referrer: "http://example.com"

このあたりの記事を見ると、IPv6絡みっぽいということがわかりました。

自分の環境の/etc/nginx/nginx.confには、upstreamディレクティブはなく、バーチャルホストで複数のnode.jsアプリが同居している状態だったので、各serverディレクティブの設定がこうなってました。

server {
    listen 80;
    server_name host-a.example.com;
    location / {
        proxy_pass http://localhost:3002;
        proxy_set_header Host $host;
    }
}
(↑これのポートが違うものがいくつか)

ちょっと参考記事とは違うけど、試しにここのproxy_passlocalhostの部分を127.0.0.1に変更してみます。

server {
    listen 80;
    server_name host-a.example.com;
    location / {
        proxy_pass http://127.0.0.1:3002;
        proxy_set_header Host $host;
    }
}

そしてnginx再起動。

$ sudo /etc/init.d/nginx restart
nginx を停止中:                                            [  OK  ]
nginx を起動中:                                            [  OK  ]

しばらく様子を見てみると、毎秒ごとに出てたエラーが止まりました!

そもそもアクセスは捌けてるのか心配になったので、念のため/var/log/nginx/access.logの方も確認すると、こっちにはちゃんとログがたまってて問題なさそうでした。

(おまけ)エラー発生時のaccess.logはどうなっていたのか?

エラーが起きていた時に、そのエラーが起きたリクエストの処理はどうなっていたのか気になったのでエラーが起きた時間の/var/log/nginx/access.logを見てみます。

すると時間、同じIP、リクエスト内容が一致するものがありました。

xxx.xxx.xxx.xxx - - [16/Jul/2015:15:04:40 +0900] "GET /index.html HTTP/1.1" 200 54 "http://example.com" "Mozilla/5.0 (Linux; U; Android 4.2.2; ja-jp; SonySO-04E Build/10.3.1.B.0.256) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30" "-"

なのでエラーは起きてたけど、漏れてはいない様子。

ということは、クライアント側がおそらくIPv4とIPv6両方でアクセスを試みたんだけどIPv4の方は成功して、IPv6の方は失敗した・・・みたいなことなのでしょうか?

ちょっとこの辺りはお勉強が必要そうです。