リバースプロキシとして Apache httpd を立てて別のサーバにhttpでプロキシしているときに、upstreamに対するコネクションをKeep-Aliveしたかったのだが、よくわからない事象に遭遇して1日はまった。
発生した事象
ProxyPass
を使う ⇒Connection: Keep-Alive
ヘッダーがつき期待通りkeep-aliveされるProxyPassMatch
を使って正規表現でマッピングする ⇒Connection: close
ヘッダーがつきkeep-aliveされない
再現
compose.yaml
httpdの設定
my-httpd.conf
起動とProxyに必要な最小限の設定をいれている
appコンテナの設定
起動 & リクエスト
⇒ Connection:close
ヘッダーが送られている。
答え
https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxypassmatch
enablereuse=on
をつける、と書いてあった。日本語版ドキュメントにはまだ記載がない。
Since Apache HTTP Server 2.4.47, the
key=value
Parameters are no longer ignored in aProxyPassMatch
using an url with backreference(s). However to keep the existing behavior regarding reuse/keepalive of backend connections (which were never reused before for these URLs), the parameter enablereuse (or disablereuse) default tooff
(resp.on
) in this case. Settingenablereuse=on
explicitely allows to reuse connections unless some backreference(s) belong in theauthority
part (hostname and/or port) of the url (this condition is enforced since Apache HTTP Server 2.4.55, and produces a warning at startup because these URLs are not reusable per se).
とあり、2.4.47以降は正規表現の後方参照を使う場合でも key=value
パラメータを適用できるようになっている。
後方互換性のため、デフォルトではkeep-aliveに関してはoffになっているので、 enablereuse=on
または disablereuse=off
を明示する必要がある。
ただし後方参照によってauthority(hostnameやport)を書き換えようとするときには適用されない。
実際に試してみた。
confを上記のように変更して再起動して再度リクエストすると、期待通りKeep-Aliveとなった
これにたどり着くまでにいくつか試したので記録する。
試したこと
KeepAlive On
https://httpd.apache.org/docs/2.4/mod/core.html#keepalive
KeepAlive
Directive をOnにするとどうかと思ったが、これは httpdに接続するクライアントとの通信をKeepAliveするため のものなので、upstreamとの通信には関係がない。
keepalive=on
ProxyPassのパラメータ にkeepalive=on
というのがあり、これに違いないとセットしてみたが関係無かった
ProxyPassMatch /app/users/([0-9]{4}) /app/v2/users/$1 keepalive=on
This parameter should be used when you have a firewall between your Apache httpd and the backend server, which tends to drop inactive connections. This flag will tell the Operating System to send
KEEP_ALIVE
messages on inactive connections and thus prevent the firewall from dropping the connection. To enable keepalive, set this property value toOn
.
とあり、firewallを間に挟んでいてそれがin-activeなコネクションを切断するようなときに、切断されないようにOSがTCPレベルでKEEP_ALIVEを送信するためのパラメータ であって、HTTPのKeepAliveとは関係なさそう
SetEnv proxy-nokeepalive
upstreamとHTTP 1.0で通信したいときに、keep-aliveをOffにするパラメータがある
https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#envsettings
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
じゃあ逆にkeepaliveを強制できないかなと、やけくそで適当にセットしてみたがもちろんこんなパラメータはないので効かなかった
SetEnv proxy-keepalive 1