私はnginxを使用してプロキシを作成し、遠くのサーバーへの永続的な接続を保持しています。
この例のように約15ブロックを構成しました。
upstream rinu-test {
server test.rinu.test:443;
keepalive 20;
}
server {
listen 80;
server_name test.rinu.test;
location / {
proxy_pass https://rinu-test;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $http_Host;
}
}
問題は、1つ以上のupstream
ブロックでホスト名を解決できない場合、nginxは(再)起動しません。静的IPも使用できません。これらのホストの一部は、IPが変更されるため、そうしないと明示的に述べています。このエラーメッセージに対して私が見た他のすべての解決策は、upstream
を取り除き、location
ブロックですべてを実行するように言っています。 keepalive
はupstream
でのみ使用できるため、ここでは不可能です。
一時的に1台のサーバーを失う余裕はありますが、15台すべてを失うわけではありません。
編集:nginxはこのユースケースには適さないことが判明しました。代替バックエンド(アップストリーム)キープアライブプロキシを使用する必要があります。カスタムNode.jsの代替は my answer にあります。これまでのところ、実際に機能する他の選択肢は見つかりませんでした。
世界で最も訪問された膨大な数のウェブサイトをすでに動かしていた(1.1.4より前の)nginxの以前のバージョンは(そしてサーバーヘッダーが信じられれば今日でもなおそうです)、 keepalive
upstream
側。さまざまなホスト間で非自明な待機時間がない限り、datacentre設定でこれを行うメリットはほとんどないため。 https://serverfault.com/a/883019/11002 を参照してください。
基本的に、アップストリームとフロントエンドの間でキープアライブが特に必要であることがわかっていない限り、アーキテクチャの回復力を低下させ、悪化させるだけの可能性があります。
(現在のソリューションも間違っていることに注意してください。IPアドレスの変更も同様に検出されないためです。configreloadでのみホスト名解決を行うため、nginxが起動しても、IPアドレスがいったん動作しなくなると基本的に停止します。アップストリームサーバーの変更はありません。)
潜在的なソリューションは、1つを選んでください:
最良の解決策は、データセンター環境ではおそらく不要であるとしてupstream
keepalive
を取り除き、各リクエストの最新のDNS解決に proxy_pass
を使用して変数を使用することです(nginxはまだ十分にスマートです)そのような解像度のキャッシュを引き続き行うため)
別のオプションは、resolve
コンテキスト内のserver
ディレクティブの upstream
パラメーターを持つ商用サブスクリプションを通じてnginxの有料バージョンを取得することです。
最後に、 set
変数 および/または map
を使用してupstream
内のサーバーを指定することもできます。これは実装されたことが確認も拒否もされません。たとえば、機能する場合と機能しない場合があります。
別の方法は、必要なことだけを行う新しいサービスを作成することです。 Node.jsを使用してhttps接続をプロキシするためのnginxを次のように置き換えます
const http = require('http');
const https = require('https');
const httpsKeepAliveAgent = new https.Agent({ keepAlive: true });
http.createServer(onRequest).listen(3000);
function onRequest(client_req, client_res) {
https.pipe(
protocol.request({
Host: client_req.headers.Host,
port: 443,
path: client_req.url,
method: client_req.method,
headers: client_req.headers,
agent: httpsKeepAliveAgent
}, (res) => {
res.pipe(client_res);
}).on('error', (e) => {
client_res.end();
})
);
}
使用例:curl http://localhost:3000/request_uri -H "Host: test.rinu.test"
これはcurl https://test.rinu.test/request_uri
と同等です
1つの解決策は、ローカルDNSキャッシュを使用することです。 BindやDnsmasqのようなローカルDNSサーバー(巧妙な構成で、nginxはシステムデフォルトの代わりに 指定されたdnsサーバー を使用できることに注意してください)、または単にhosts
ファイル。
一部のスクリプトでhosts
ファイルを使用するのは非常に簡単な方法のようです。ホストファイルは、静的部分と動的部分(つまりcat hosts.static hosts.dynamic > hosts
)に分割され、動的部分はスクリプトによって自動的に生成(および更新)される必要があります。
おそらく、IPを変更するためにホスト名を時々チェックし、ホストファイルを更新し、変更時にnginxの設定をリロードすることが理にかなっています。一部のホスト名を解決できない場合は、古いIPまたはデフォルトのIP(127.0.1.9など)を使用する必要があります。
Nginx構成ファイルにホスト名が必要ない場合(つまり、IPで十分な場合)、IP(解決されたホスト名)を含むupstream
セクションをスクリプトと included intoで生成できます。 nginx config —この場合、hostsファイルに触れる必要はありません。
サーバーに解決パラメーターを設定し、nginx.confでNginx Resolverを以下のように設定する必要があります。
/etc/nginx/nginx.conf:
http {
resolver 192.168.0.2 ipv6=off valid=40s; # The DNS IP server
}
Site.conf:
upstream rinu-test {
server test.rinu.test:443;
keepalive 20;
}