1. ホーム
  2. nginx

[解決済み] バックグラウンドでリクエストするようにnginxを設定する

2022-02-16 10:52:02

質問

私は、APIとデータの組み合わせの使用に関するいくつかの分析を行う必要があるアプリケーションを構築しています。 以下は私のnginxの設定です。

location /r/ {
    rewrite /r/(.*)$ http://localhost:3000/sample/route1/$1 redirect;
    post_action /aftersampleroute1/$1;
}
location /aftersampleroute1/ {
    rewrite /aftersampleroute1/(.*) /stats/$1;
    proxy_pass http://127.0.0.1:3000;
}

場所 /r/ は、ブラウザのリクエストをリダイレクトするために使用されます。 http://localhost:80/r/quwjDP4us からAPIへ /sample/route1/quwjDP4us を使用し、id quwjDP4us を実行しています。 今度はバックグラウンドで quwjDP4us をstatsのapiに送る。 /stats/quwjDP4us で、そのIDのDBレコードを更新します。

nginxを起動し、リクエストを行うと http://localhost:80/r/quwjDP4us nginxは私のリクエストを私のアプリケーションにうまくリダイレクトしますが、バックグラウンドでstats apiに2回目のリクエストを行いません。何が足りないのでしょうか?

注 - post_action は nginx のドキュメントに含まれていません。代わりに使えるモジュールやディレクティブはありますか?

解決方法を教えてください。

ご指摘の通りです。 post_action は文書化されておらず、常に非公式なディレクティブと見なされてきました。

Nginx はバージョン 1.13.4 以降、新しい "mirror" モジュールを提供しており、その内容は以下のとおりです。 こちら をご覧ください。というわけで、試してみることをお勧めします。あなたの場合、次のようになります。

location /r/ {
    rewrite /r/(.*)$ http://localhost:3000/sample/route1/$1 redirect;
    mirror /stats;
}

location = /stats {
    internal;
    rewrite /sample/route1/(.*) /stats/$1;
    proxy_pass http://127.0.0.1:3000;
}

これはうまくいきません!

テスト用コンフィギュレーションを構築してみましたが、残念ながらこれは動作しません。 以下のいずれでも動作します。 rewrite また return . しかし、それは proxy_pass .

なぜ

以下に説明します。HTTPリクエストは、Nginxでの処理中にいくつかのフェーズを順次通過します。というものです。 mirror がトリガーされます。 PRECONNECT よりも後に発生するフェーズ REWRITE ここで rewrite / return リクエスト処理を終了します。そこで mirror はトリガーされません。

ロケーションからファイルを提供する場合や、プロキシを経由して proxy_pass (または fastcgi_pass など)に到達すると、処理は最終的に REWRITE フェーズと mirror が実行されます。

フェーズはNginxのドキュメントに記載されています。 こちら .

回避策

トレードオフのない良い解決策は見当たりません。余分なロケーションを作成して (リダイレクトを返す)、リクエストのプロキシを /r/ というように mirror がトリガーされます。残りの設定によりますが、このような感じです。

location /r/ {
  # you may need setting Host to match `server_name` to make sure the
  # request will be caught by this `server`.
  # proxy_set_header Host $server_name;
  proxy_pass http://<ip from listen>:<port from listen>/redirect/;
  mirror /stats;
}

location = /redirect {
  rewrite /redirect(.*)$ http://localhost:3000/sample/route1$1 redirect;
}

確かにこれは最適とは言えず、余計な定型文がある。