最近在 AWS 上遇到了 TinyProxy 的問題,因為雲的特性是好伸縮,所以基本上所有的 EC2 都會套上 ELB + Autoscaling 才能發揮他的好處,所以在 Proxy 上我也這樣做,但不同的地方在於 TinyProxy 是走 TCP,ELB 本身有支援 TCP 是 OK 的
但用 TinyProxy 在 AWS ELB 的後面會造成無法取得 Client IP 的窘境,因為 ELB 支援 x-forwarded-for,但 TinyProxy 支援的是 X-Tinyproxy (不和世界一樣很帥嗎?) header 所以根本取不到 Client IP …
然後 ELB 提供的 ProxyProtocol,TinyProxy 也沒有支援 (因為輕量簡單所以什麼都沒有),所以在 MaxClients 就不能以 end user 來評估,因為 TinyProxy 認到的是 ELB 的 IP
在 TinyProxy 的參數調校就變得非常重要:
MaxClients 512 StartServers 32 MaxSpareServers 1024 MinSpareServers 64 Timeout 60
這幾個參數是必須特別注意的:
- MaxClients 就跟上述提到的一樣,改成判斷 ELB instance connection 的最大值。
- StartServers 這邊我抓在平時會產生的平均 connection 的數量,也不要開太大,這樣每次 restart 都會需要立即產生該數量的 threads,然後也有可能造成你 StartServers 開太大服務直接 OutOfmemory 爆掉 XDD。
- MinSpareServers 和 StartServers 有點像,但 StartServers 像是你啟動服務要準備好的資源,而 MinSpareServers 則是你希望的最小值
- 舉上面的數值來說,會啟動 32 個 threads 後服務正常運作,然後 TinyProxy 會邊提供 Proxy 服務也持續一直產生 threads 直到 128。
- Timeout 這個值在 ELB 後面的話超級關鍵 XDD …
- 不能設太長:ELB 會一直 Health check 你的 instance,如果你的 timeout 設太長,就會有大半的 connection 其實是被 ELB health check 佔用了,真正的 Proxy connection 被擋在門外。
- 也不能設太短:如果你有用來給 CodeDeploy 作為 Proxy 出去,在使用 CodeDeploy 跑 BlockTraffic/AllowTraffic 時會有關係。
為什麼 Timeout 和 CodeDeploy 有關係 !?
假設 ELB health check 總共要 120 秒才能完成確認 (算法參考),TinyProxy 的 Timeout 設為 60。
CodeDeploy 會等待 ELB health check 來做 BlockTraffic/AllowTraffic 的判斷,當等待的過程中超過 TinyProxy 的 timeout 值就會被 TinyProxy 強制中斷連線,在 TinyProxy 的 Log 你會看到:
CONNECT Jul 10 04:08:24 [9306]: Connect (file descriptor 6): 10.152.0.160 [10.1.0.160]
CONNECT Jul 10 04:08:24 [9306]: Request (file descriptor 6): CONNECT codedeploy-commands.ap-northeast-1.amazonaws.com:443 HTTP/1.1
INFO Jul 10 04:08:24 [9306]: No upstream proxy for codedeploy-commands.ap-northeast-1.amazonaws.com
CONNECT Jul 10 04:08:24 [9306]: Established connection to host “codedeploy-commands.ap-northeast-1.amazonaws.com” using file descriptor 7.
INFO Jul 10 04:08:24 [9306]: Not sending client headers to remote machine
INFO Jul 10 04:08:45 [9306]: Idle Timeout (after select) as 60 > 61.
當發生這樣的狀況,你的 CodeDeploy 就會 pending,然後一直被 TinyProxy 截斷 connection,最後出現這樣的錯誤訊息:
(1) Multiple deployments are attempting to run at the same time on an instance; (2) The AWS CodeDeploy agent has stopped. Restart the agent. Learn more
錯誤訊息告訴你 CodeDeploy agent 死掉了,但實際你登入到 instance 查看 CodeDeploy agent 卻又是正常的,因為你的連線一直被中斷而造成 CodeDeploy 的錯誤訊息誤判為 “CodeDeploy agent has stopped.”。
也因為一開始沒有把這些參數很仔細的調整導致線上 Proxy 異常,這也算是學個教訓啦 …
然後下一篇應該會寫怎麼做 TinyProxy 的 Autoscaling and Monitor。