程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> Nginx 動態 upstreams 實現,nginxupstreams

Nginx 動態 upstreams 實現,nginxupstreams

編輯:關於PHP編程

Nginx 動態 upstreams 實現,nginxupstreams


我最近在工作中做一個設置,我有一個面向用戶的 Nginx 服務,它將訪問轉發到運行在AWS Elastic Load Balancer (如你所知. ELB)上的一個服務。這本身似乎不是一個困難的任務,你只需要找到 ELB 的主機名,將 ngin x指向它,這樣不就搞定了,對吧?

location / {
    proxy_pass http://service-1234567890.us-east-1.elb.amazonaws.com;
}

測試沒有問題,再正確設置一下防火牆/安全組配置,它就應該可以很好的工作了。幾個小時之後,你可能會發現,服務不再工作了,盡管沒有做任何改變。直接訪問 ELB 端點是可以工作的,但訪問 Nginx 卻總是超時提醒。

ELB端啟蒙

為了弄清楚為什麼服務突然中止,需要先了解一下 ELB 是如何工作的:

當你創建一個彈性負載均衡(Elastic Load Balancer),你將會得到 DNS 的返回記錄,AWS 會告訴你所有在使用的訪問服務。DNS 記錄是一個輪詢 DNS(round robin DNS)記錄,它指向兩個或更多的 IP 地址——這取決於你有多少可用的區域。DNS 記錄被設置成 60 秒的存活時間(time to live),這意味幾乎不會有記錄緩存。

短 TTL 可以讓 AWS 快速改變機器的運行負載,在不中斷服務的情況下,不會有任何復雜的虛擬 IP 問題。這也是他們特別告訴你不要查找主機名和發送流量到其中某個 IP 地址的原因,那樣的話,你的服務可能會在未來某個未定義的時間,IP 地址可能會停止為負載均衡工作。

回到 Nginx

問題在於,對於 Nginx 來說,當它讀取到一個配置時,它就會立刻向 DNS 請求主機名,然後使用其結果,直到下次重新加載配置。在這段時間到來之前,ELB 可能改變 IP 地址,讓你的 Nginx 把請求轉發到一些不為你服務的地址。

Nginx Plus

解決這個問題的方式是為 Nginx Plus 付費,它添加 resolve 標記對在 upstream 分組上的服務器進行指示。那就是讓 Nginx 驕傲的 DNS 對 TTL 的記錄,偶爾按順序重新處理記錄,並取得服務器使用的更新列表。

為這個功能花費每年每服務器 $1.500,看起來花費很多。當然這是你希望得到 Nginx Plus 帶來的其他功能,如果你不需要它們,這將會是一個昂貴的升級。

免費的選擇

一個更加實惠的選擇是寫這樣一個配置:

resolver 172.16.0.23;
set $upstream_endpoint http://service-1234567890.us-east-1.elb.amazonaws.com;
location / {
    proxy_pass $upstream_endpoint;
}

它將會生效並且 Nginx 會遵循記錄 DNS 記錄的 TTL,萬一一個請求進來,會重新解釋它而且緩存的記錄會過期。為什麼會這樣?

答案可以在 proxy_pass 指令文檔結尾找到,它聲明了:

服務器名,端口以及傳遞的URI也可以使用變量被指定:

proxy_pass http://$host$uri;

甚至像這樣:

proxy_pass $request;

在這個案例中,服務器名會在所描述的 server groups 中被查找,如果沒找到,會使用 resolver 來決定.

當我們給 proxy_pass 提供一個變量的時候,我們基本上是利用其改變行為,但這樣確實需要我們在配置中指定一個 DNS resolver。例子裡邊用到的 DNS resolver應該能夠在 AWS 上面跑在默認 VPC或者 EC2 中的所有服務器工作(適用)。你也可以隨時查看 /etc/resolv.conf 找出哪些 AWS 為你的服務器提供並使用了哪些 DNS 服務器。

關於轉發 URI 的 Caveat(警告)

如果你在 Nginx 中設置的 Location 不只是 /,那麼你需要注意到當給定一個變量作為參數時,proxy_pass 細微的改變行為。

先說重要的,快速概括 proxy_pass 如何在正常在操作中工作:

正常的表現行為

設想我們有一個 Nginx 配置包括這些:

location /foo/ {
    proxy_pass http://127.0.0.1:8080;
}

當我們發送一個 /foo/bar/baz 的請求到這個站點,Nginx 會轉發請求到 http://127.0.0.1:8000/foo/bar/baz。

location /foo/ {
    # Note the trailing slash       ↓
    proxy_pass http://127.0.0.1:8080/;
}

Nginx 會在 Location 記錄裡邊去掉部分指定的 URI,然後把剩下的部分傳給 upstream 服務器。所以請求 /foo/bar/baz 會被轉發到 http://127.0.0.1:8080/bar/baz。

改變行為

當我們使用一個變量作為 proxy_pass 的參數的時候,上面帶有尾部斜槓的行為會改變。例如我們有這樣的配置。

resolver 172.16.0.23;
set $upstream_endpoint http://service-1234567890.us-east-1.elb.amazonaws.com/;
location /foo/ {
    proxy_pass $upstream_endpoint;
}

當我們向那個配置發送請求 /foo/bar/baz,轉發請求將不會去到/並且不是預想中的 /bar/baz。

為此解決方案就是從 upstream 的 endpoint 去掉尾部斜槓,然後像這樣手動重寫:

resolver 172.16.0.23;
set $upstream_endpoint http://service-1234567890.us-east-1.elb.amazonaws.com;
location /foo/ {
    rewrite ^/foo/(.*) /$1 break;
    proxy_pass $upstream_endpoint;
}

然後當你發送請求 /foo/bar/baz,upstream 會接受到我們想要的請求 /bar/baz。

結束語

要知道這不單單只適用於設置用 elb 做 upstream 服務器,它適用於配置所有在 nginx 做 upstream 服務器的修改 DNS 配置的情況。

希望這對你有用,如果你有任何建議或者只是想單純聯系我,用 twitter 聯系吧 Tenzer。

 

  碼農必須要加班?NO!

  知道碼農們都想擺脫加班狗、外賣臉的稱號,所以我們來了!

  我們做了一個能讓程序員之間共享知識技能的APP,覺得可以顛覆程序員的工作方
式!

  有人說我們癡心妄想,但我們不那麼認為。

  為了能煽爛說我們癡心妄想的人的臉,現在我們急需程序員業內的牛哔-人物來給
我們“號脈”!“診斷費”豐厚!畢竟我們不差錢兒,只是想做到最好!

  圈圈字典中講到,牛哔-人物是指群成員數高於1000人的QQ群主或關注人數高於
2000人的貼吧吧主或粉絲人數高於10000人的微博博主或成員數高於2000主題貼的版主
或單帖閱讀量高於2000博客主或人脈超級廣的圈內紅人。

  對於未能達標的未來大神們,我們只能含淚表示:蜀黍,咱們來日方長,這次暫
時不約好嗎?待他日你立地成神,我必生死相依!

  來?還是不來?

  圈圈互動 接頭暗號:1955246408 (QQ)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved