1.問題背景
web站點透過Nginx做反向代理,兩個tomcat做負載平衡。
web網站有一個群發簡訊模組,管理員可以填寫發送內容,手機號碼清單。點擊發送,後台會執行群發簡訊操作,在發送結束後,回傳發送結果。
在很早之前遇到過,重複發送的問題。最開始以為管理員異常操作,重複點擊了發送按鈕。因此對前端提交做了限制。點擊發送時,把按鈕置為disable,執行完畢拿到返回數據,再置為可用,從前端限制重複提交。
今天突然有同事又使用到了這個模組,分別群發了兩批短信(8000條和1600條),前端都提示了操作失敗,但自己的手機卻分別收到了重複的短信推送。
2.問題分析
首先確認了手機號碼列表沒有重複,也透過瀏覽器調試確認前端沒有發起重複請求。
透過查看兩台伺服器的日誌,確實出現了重複的發送,且發送時間點不在同一時刻。
透過日誌,可以估算出,發送一封簡訊的時間在10毫秒。
也通過日誌,查看到了處理超時日誌,並且發現了規律,重複的請求在不同機器處理且處理間隔時間相差一致
A日誌
10:03:05,878 INFO TIMEOUT.info:252 - time: 75701ms, concurrent: 1, url: /push/sendmessage.10:07:24,705 INFO TIMEOUT.info:252 - time: 15148ms, concurrent: 0, url: /push/sendmessage.
Bee
rrrereeeA日誌
10:03:21,599 INFO TIMEOUT.info:252 - time: 76471ms, concurrent: 1, url: /push/sendmessage.10:07:39,718 INFO TIMEOUT.info:252 - time: 15113ms, concurrent: 0, url: /push/sendmessage.應該是請求執行時間超過限制,造成前端提示失敗。重複的提交應該是重試機製造成。 於是聯繫運維進行確認。得到相關答案:Nginx可以配置逾時時間,假設配置15s,而一個請求需要16s才能處理完返回。 Nginx路由到A伺服器處理,A執行到第15s時,沒有正常返回,Nginx會重新發到B服務處理,B執行到第15s時,也沒有正常回傳。前端等待30s,最後回傳失敗。 A和B分別收到對應的請求,內部都進行了處理。 和維運同學確認過原因後,就可以根據相關資訊自行搜尋。 nginx的重試機制文中也點到了一種解決方案,可以透過ip存取服務,繞過nginx。 另外我們的web站點,有一個下載的功能,在優化之前,每次下載的執行時間也很長,但是確沒有遇到超時問題。分析了可能是GET和POST的差異。上文也給了下面這個鏈接,確定大致思路。 http://serverfault.com/questions/528653/how-can-i-stop-nginx-from-retrying-put-or-post-requests-on-upstream-server-timeo3.問題總結
透過網路上的資訊參考,Nginx可以對檔案上傳,下載,GET和POST請求設定不同的逾時策略。 另外對於簡訊群發業務,其實有單獨的模組,透過規則管理配置,做離線任務執行。現有保留的群發模組,只是為了應對小規模的業務。