鐵人賽倒數第二天,今天來討論錯誤代碼,以及可能的原因。
在開始採用 CloudFront 之後,只要發生錯誤,第一時間我們都很難直接排除 CloudFront 造成問題的可能。
本文中將列出一些常見的錯誤(含特性),以及可以往哪方向排查,希望本文可以對你有些幫助。
4xx Errors
400 Bad Request
- 通常,這 Error Client 送了些 Server(通常指 Orging) 端看不懂或直接打槍的請求。
- 另一種情況,是 CloudFront 以 S3 Bucket 作為 Origin,這個 Bucket 原本在 A region(ex: us-east-1),後來因為某些原因,User 自己將該 Bucket 從 A region 刪除,又在 B region (ex: ap-northeast-1)開立了同樣名稱的 Bucket。此時因為 CloudFront 回源到 S3 時,指明了 Bucket 在 A region (實際上在B Regio),S3 就會返回 400 Bad Request。
403 Forbidden (CloudFront 產生)
因 CF 產生的 403,可能有以下常見原因:
- Distribution 創建後沒有設置 CNAME(ex: www.example.com),但直接添加了 DNS 紀錄,所以請求抵達時,CloudFront 找不到對應要參照哪一組,回覆 403
如果是因為沒有設置 CNAME,因為 CloudFront不知道請求要丟給哪一個 Distribution處理,所以你的 Distribution 不會看到 Log。
- Cloudfront 有開 Geographic registraion,而該請求被判訂為不接受連入的國家。
- Distribution 沒有允許使用對應的 HTTP Methdo。 ex: 設定僅接受 GET/HEAD,但 client 端送入HTTP POST請求。
- WAF 阻攔。
- CloudFront Functions or Lambda@edge 返回。
403 Forbidden (Origin 產生)
- Origin 是 S3,但對應的檔案不存在(ex: 不小心打錯檔案名稱 or 檔案已經刪除)
- 因為沒有正確的轉發對應的 Headers/QueryStrings/Cookies,所以 Origin 端因而收到不完整的請求資料,最終回覆 403。
- 也有可能是被 Origin 的 WAF 擋下。(ex: ALB, CLB, API G/W... 等)
404 Not Found
這個基本上都是 Origin 沒有對應的檔案。
405 Method not allowed.
通常是 Origin(ex: nginx/OpenResty) 沒有允許對應的請求。ex: Nginx 在沒修改設定前,預設不接受 HTTP Post。
(鋸箭法,修改 nginx 設定)
# To allow POST on static pages
error_page 405 =200 $uri;
409 CNAME already exists
當要設置的 CNAME 已經被其它 Distribution 使用了,就會出現這請況。需要將對應的 CNAME 直接搬遷到你身上才能解決這錯誤。
418 I'm a tea pot
這比較難定義為「錯誤」,而應該是一個有趣的小故事。無論如何,這是由 Origin 所返回。如果你對這故事有興趣,可以參考這文章
494 Header too large
如同文字說明,這是因為 Client 送來的請求太大的關係。公開文件中提到 CloudFront 允許的最大 Header(含 QueryString) 就是 20KB。如果超過這數值,CloudFront 回應 494。
你的 Distribution 也不會看到 Log。
5xx 錯誤。
500 Error
500 Error 基本上都來自 Origin。
如果你的 Origin 是 S3 --> 請參考 exponential backoff 讓 Client 端進行重試。
由於 Amazon S3 是分散式服務,因此在正常使用服務期間,預期 5xx 錯誤百分比會非常小。從 Amazon S3 傳回 5xx 錯誤的所有請求都可以重試。這是讓 Amazon S3 提出請求的任何應用程式具有容錯機制或實作重試邏輯的最佳實務。這樣做可以讓 S3 從這些錯誤中復原。
如果你的 Origin 不是 S3 --> 請檢查 Origin 為何會返回這樣的錯誤。
502 Bad Gateway
如果回覆 502 的是 CloudFront,大概有多種可能,包含:
- Origin 的 TLS 憑證已經到期,這類通常因為 Origin 的 Certificate 沒有隨著更新。如果可以,非常建議使用 AWS Certification Manager(ACM) 所頒發的 TLS 憑證,只要你持續有在使用,就可以自動續約(free),避免因為沒有繳交憑證費用而導致 Origin TLS 憑證過期。
- Origin 查不到 DNS Record(如果你的 Origin 有對應某些解析,ex: geo-based resolving,但沒有預設的回覆值)
- CloudFront 與 Origin 建立 HTTPS 連線失敗。比方說在 Distribution 中設定 Origin Request Protocol 是 HTTPS,而你是使用 ALB/CLB 作為 Origin,那麼此時如果對應的 Behavior 沒有轉發 'Host'標頭,CloudFront 就會無法與 Origin 建立 HTTPS連線,最終 502。
- Origin 的 TLS 對應使用的 Cypher 等,不被 CloudFront 所支援,造成最終 CloudFront 無法與 Origin 成功建立 HTTPS 連線。
- Origin 認為 CloudFront 用了一個應該已經關閉的 TCP Connection,斷然中斷連線。
假設 CF 的 Origin Keep Alive Timeout 是 10秒,而 Origin 本身設定 KeepAlive 僅有 5秒。那麼當前一筆連線是 6秒前送入,此時 CF 認為原本的連線仍可用,但 Origin 認為的 TCP 連線應該已經要關閉。此時 Origin 會直接送 TCP RST 要求 CF 不要繼續用該連線。若此時又剛好是 HTTP POST 這類不用 retry 的 Method,就會直接噴 502
- Origin 對應的 Port 沒有被使用,所以 Origin(ex: EC2)直接回 Connection Refused(L4)。
- Lambda@edge 驗證錯誤。
503 Service unavailable (CF 產生)
503 的錯誤原因就很多種,但基本上都是 Origin 端 or CF 暫時因為請求數量太多/負載太重,最終請求無法繼續被執行。
- Concurrency 太高,頂到 Lambda@edge 的執行數量上限。
- CF 的特定 PoP 實在剛好太忙、資源不足。
503 Service unavailable (Origin 產生)
Amazon S3 performance supports at least 3,500 requests per second to add data and 5,500 requests per second to retrieve data. Each S3 prefix can support these request rates, making it simple to increase performance significantly.
- 自定義的 Origin 所回覆。(ex Origin 以 nginx 做 reverse proxy,但 nginx 之後的服務無法接下請求,只好回吐 503。
504 Request Timeout (CF 產生)
因為 Origin 設定了 Security Group、IP Tables、或者甚至是 Routing 有問題,讓 Origin端收到請求後,不會正常回覆給 CF。CF 等不到回應,最終 產生 504。
504 Request Timeout (Origin 產生)
Origin 端的程式需要執行的時間太長,比方說,程式有著巨大的進步空間,但就是不能在特定時間範圍內處理完畢。
好了,基本的錯誤看完了,我們即將邁入第 30天,我們下篇文章見。