最近平台有人員反應了幾個問題:
1.商家充值記錄有時候莫名其妙存在充值后的重復數據記錄。
2.開發人員無意中提了一次我們的feign負載均衡有時候會負載到兩台集群服務器都會執行。
3.定時調度去執行當日表移單要歷史表,發現存儲過程被調用了兩次。
由於這幾個問題不是同一時間段出現的,再加上是偶發性的,當初重點排查的是業務本身的代碼,毫無頭緒,但是隨着這些問題經常的出現,需要引起重視並與解決。
在測試環境一次調試中,發現一個奇怪的現象,兩台服務器A,B集群,被feign負載均衡分別各執行了一次,為了百分之百命中並重現問題,將里面的方法休眠一段時間,果然不出所料,feign負載均衡百分之百對各實例都分別執行一次。
查閱springcloud feign客戶端負載均衡相關資料,springcloud的重試機制是指:負載均衡客戶端Ribbon發現遠程請求實例不可到達之后,去重試其他實例的過程。那么果然就是這個問題,有些服務在執行過程中由於各種原因導致超時,feign client的重試,導致接口重復執行。
解決這個問題之前也要具體問題具體分析,如果是查詢操作,操作失敗了進行重試是可行的,但是如果是非冪等性的寫操作,如果被調用方某個實例實際中執行了寫操作,僅僅是因為網絡或其他原因造成了異常,調用方依然進行重試,這就是不允許的。
像上面的業務就屬於非冪等性的寫操作,所以將其配置成不允許重試機制。
OkToRetryOnAllOperations: false
MaxAutoRetriesNextServer: 0
原理說明:
Feign是通過內置的Ribbon進行負載均衡,並通過HTTP去訪問被調用方,所以Feign的重試,其實就是Ribbon的重試。另外,我們在實際工作中使用Feign,用到Hystrix,在這里就順便說一下Hystrix的原理。舉例說明下,假如在沒有Hystrix的情況下,用戶一個下單操作需要調用訂單、支付、物流三個服務,如果其中物流Service因為種種問題不能提供服務,即便另外兩個服務都好好的,整個下單操作也會因為物流Service而阻塞住,導致下單服務崩潰。而Hystrix為每個依賴的服務配置獨立的線程池並進行隔離,假設下單服務有90個線程,沒有Hystrix,則因為物流Service不能提供服務,不停地重試直到90個線程全卡死。而有了Hystrix,三個依賴的服務,每個30個線程,即便物流的30個全部阻塞了,也不影響另外兩個服務的線程。