10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CentOS7系 + nginx keep-aliveをoffにした話

Last updated at Posted at 2018-05-18

はじめに

環境

  • asianux7(※CentOS7.2相当)※ゲストOS(検証用)
  • Windows10 Professional ※ホストOS(検証用)
  • VirtualBox5.2.6
  • Vagrant2.0.1
  • nginx 10.12.2
  • Apache httpd 2.4.29(比較用)
  • Apache JMeter 4.0 (負荷ツール)

長文なのでひとことで(忙しい人向け)

APIサービス提供など軽量なデータを扱うwebサーバではkeep-aliveはoffにした方が良いと思うよ。

本記事の目的

本番で起きたリクエストエラーの対策としてkeep-aliveをoffにしました。その際の経緯などを備忘録として記載します。
事象が起きたのはnginxですがApache httpdでも同様の事象が起きるかどうか検証しました。

本番作業時におきたこと

nginxの設定ファイル変更を反映させたよ

nginxの設定ファイルを少し変更したのでnginxをリロードしました(合計4回実施)

$ sudo systemctl reload nginx

夜間作業でしたが、特にトラブルもなく(と思った)作業終了しました。

翌日クライアントサイドから連絡があったよ

クライアント側(お客様)からリクエストが数件エラーとなった旨のメール連絡がありました。
エラーのタイミングは計2回で発生時刻はnginxリロードの時刻と同じでした。やってもうたか!

nginxのaccessログを確認してみたよ

accessログをみましたがHTTPステータスは全て200で特にエラーはみつかりませんでした。
errorログも出ていません。

事象をまとめてみるよ

事象は以下です。

  • クライアント側には正常なレスポンスが返っていない。(クライアント側からは詳しいエラー情報を聞き出せなかった)
  • サーバ側はリクエストを受け取っていない。
  • 何度かリロード作業を行っているが必ず発生するわけではなく通信流量が多いときに発生する傾向があった。

再現試験実施

再現試験準備

事象から負荷が高い時にnginxをreloadすると起きると仮定しました。
※高いといっても秒間数件程度です
負荷をかけるツールは色々あると思いますが、昔から慣れ親しんだApache JMeterを使いました。
nginxとは別にApache httpdでも同じ条件で実施して比べてみました。

負荷設定

1TPSと10TPSの負荷設定で60秒間リクエストを投げる。その間に各webサーバのリロードを実施してみる。
①nginx 1TPS
②Apache httpd 1TPS
③nginx 10TPS
④Apache httpd 10TPS

再現試験結果

①nginx 1TPS ⇒ 再現せず
②Apache 1TPS ⇒ 再現せず
③nginx 10TPS ⇒ 再現!
④Apache httpd 10TPS ⇒再現せず

エラー内容

JMeterで発生しているエラーは org.apache.http.NoHttpResponseException でした。
3スレッド使ってリクエストしていますが3件エラーということは各スレッドのリクエストがリロードのタイミングでエラーとなっているということ。
nginx側のログに記録がないという事と合わせ、この結果はサーバ側からコネクションが一方的に切られている様にみえます。乱暴だなnginx君!

考察

HTTP1.1の場合、デフォルトでkeep-alive(持続的な接続)が有効となります。
この場合webサーバからのレスポンスヘッダでConnection:keep-aliveを返して同じコネクションを使う様にクライアントに指示をしていますが、上記の結果からクライアントはnginxに裏切られている(勝手にコネクションを閉じられる)形です。

対策

keep-aliveをオフにする

今回の対象のサーバは1リクエストあたり100バイトほどのデータのやり取りしかしてなく、スループットも最大100TPS程度なのでkeep-aliveで性能向上を求める必要もなく、運用重視で迷うことなくkeep-aliveをoffにすることにしました。
Apache JMeterでの試験でもエラーは起きなくなりました。
本番環境でその後何度もnginxのreloadを実施しましたが同様のエラーが再現することはなくなりました。

nginxの設定

nginxのkeep-aliveのON/OFFとkeep-aliveタイムアウトの設定は同じディレクティブで行います。0がOFFです。
該当ディレクティブ省略時のデフォルト値は75(75秒間同じ接続を使いまわす)です。

    keepalive_timeout  0;

Apache httpdの設定

Apacheのkeep-aliveの設定は素直にOn/Off。
ディレクティブ省略時のデフォルトはOnです。

    KeepAlive Off

keep-aliveタイムアウトの設定は別のディレクティブで設定します。
省略時のデフォルト値は5(秒)です。

    KeepAliveTimeout 65

おわりに

nginxは軽量で性能面ではApacheより優秀なwebサーバと思いますが、思わぬ罠が潜んでいることを思い知りました。
エラーになってもブラウザから再リクエストすれば良いサービスであれば問題ないですが、絶対エラーが許されないサービスの場合は安全サイドに倒して設定を見直す必要があると思います。

10
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?