連接到上游時 nginx 連接被拒絕
我有一台伺服器,在其上部署了 API(Sinatra)。我在埠 9292 上執行該 API 並向其代理請求。
我還需要部署一個靜態 javascript 文件及其支持資源。我在同一台伺服器上這樣做。
以下所有資訊均已匿名化。
API 訪問端點是這樣的:
server { listen 80; server_name api.myapp.com; location / { proxy_pass http://localhost:9292; } }
我為 JS 提供服務的端點是:
server { listen 80; server_name xsa.myapp.com; location / { root /data/mydir/xsa; } }
您在下面的錯誤中看到的“localhost:3003”伺服器是我引用 JS 的地方。
2018/11/23 23:31:27 [error] 18720#0: *32 connect() failed (111: Connection refused) while connecting to upstream, client: 255.255.255.7, server: api.myapp.com, request: "GET /api/v1/sub/sub_ABCXYZ/info?token%3D56f51132- 406b-4e06-a600-7379876446ed HTTP/1.1", upstream: "http://[::1]:9292/api/v1/sub/sub_ABCXYZ/info?token%3D56f51132 -406b-4e06-a600-7379876446ed", host: "api.myapp.com", referrer: "http://xsa.myapp.com/src/selector.html? mfid=sub_ABCXYZ&location=http://localhost:3003/"
回顧一下:
- 帶有埠 9292 的 VM“x”上的 Sinatra API
- VM“x”上的 nginx 伺服器在埠 80 上為 API 提供代理,以處理進入“api.myapp.com”的請求
- 同一個 nginx 伺服器還在埠 80 上為進入“xsa.myapp.com”的請求提供一個 javascript 文件
我可以在瀏覽器中很好地查看 JS,所以它確實被提供了。正是它在實例化時執行的動態內容導致了錯誤。
我還可以看到 9292 上的 Sinatra 伺服器確實收到了請求並返回了 200。看來問題出在此之後。所以它甚至看起來不像上游連接實際上被拒絕了。我已經仔細檢查了這個回復與 JS 在本地提供(並且有效)時的回复完全相同。
*** 更新 ***
即使 JS 在本地提供並正常工作,“連接被拒絕”錯誤實際上也會發生,因此看起來該錯誤是一個紅鯡魚。
您收到此錯誤消息是因為您的 Sinatra 應用程序沒有偵聽 localhost 的預設 IPv6 地址,
::1
而是偵聽舊版 IPv4 地址127.0.0.1
.因為您指定您的 nginx 上游是
localhost
,所以 nginx 首先嘗試 IPv6 地址,但是由於您的應用伺服器沒有偵聽此地址,所以 nginx 會收到拒絕連接。然後它在 IPv4 上重試連接,連接成功,並為您的應用程序提供服務。因為這引入了性能問題,並且由於 IPv6 比已棄用的 IPv4 更受青睞,所以您應該重新配置您的 Sinatra 應用程序以偵聽 IPv6。例如,
set :bind, '::1'
特別是,您不應綁定到 127.0.0.1。
您也可以只刪除綁定主機,因為預設情況下,如果您使用的是瘦(就像您應該在產品中一樣)或 WEBrick(在開發中,如果您忘記 gem install thin),它將在 IPv6 localhost 上偵聽。
(並且在相關說明中,您已明確配置 nginx不偵聽 IPv6,這將在以後或什至現在給您帶來類似的問題。您也應該修復它,而您正在使用它。)