使用Spring Cloud組件構建的服務集羣,在第一次請求時常常會出現timeout的狀況,然而第二次就正常了。Spring Cloud版本爲Dalston.SR4。html
啓動涉及到的相關服務:spring
測試的端點接口爲:http:/login/oauth/token。服務之間的調用順序爲:gateway->auth-Service->user-Service。網關收到客戶端的請求,轉發請求到鑑權服務,鑑權服務對用戶身份的核驗是經過調用用戶服,用戶服務給鑑權服務返回身份校驗的結果,鑑權服務將身份受權信息返回給gateway,gateway將最終的結果response返回給客戶端。
三個服務啓動後,經過zipkin監控調用鏈路信息,能夠看到第一次和第二次調用狀況以下圖所示:app
經過上面兩次的鏈路監控信息截圖,能夠看到第一次的耗時是第二次的10多倍。遇到某些狀況,極可能會出現第一次請求的超時。去官網看了下,主要緣由是zuul網關和各個調用服務之間的Ribbon進行客戶端負載均衡的Client懶加載,致使第一次的請求調用包括了建立Ribbon Client的時間。經過啓動日誌信息就能夠發現:負載均衡
下面分兩部分解決這個問題,一是服務之間調用Ribbon的飢餓加載,對應上面的測試爲auth-Service調用user-Service;二是zuul網關的飢餓加載。性能
通過調查發現,形成第一次auth-Service調用user-Service耗時長的緣由主要是,Ribbon進行客戶端負載均衡的服務實例並非在服務啓動的時候就初始化好的,而是在調用的時候纔會去建立相應的服務實例。因此第一次調用user-Service耗時不單單包含發送HTTP請求的時間,還包含了建立Ribbon Client的時間,這樣一來若是建立時間速度較慢,同時設置的請求超時又比較短的話,很容易就會出現耗時很長甚至超時的狀況。
在官網能夠看到以下的配置說明:測試
Each Ribbon named client has a corresponding child Application Context that Spring Cloud maintains, this application context is lazily loaded up on the first request to the named client. This lazy loading behavior can be changed to instead eagerly load up these child Application contexts at startup by specifying the names of the Ribbon clients.優化
意爲Spring Cloud爲每一個Ribbon客戶端維護了一個相對的子應用環境的上下文,應用的上下文在第一次請求到指定客戶端的時候懶加載。不過能夠經過以下配置進行修改:this
ribbon:
eager-load:
enabled: true
clients: client1, client2, client3複製代碼
按照如上的配置以後,發現鑑權服務啓動時就將user服務的Ribbon客戶端進行了加載。url
上面小節解決了auth-Service調用user-Service的Ribbon客戶端啓動時飢餓加載。網關做爲對外請求的入口,zuul內部使用Ribbon調用其餘服務,Spring Cloud默認在第一次調用時懶加載Ribbon客戶端。zuul一樣須要維護一個相對的子應用環境的上下文,因此也須要啓動時飢餓加載。spa
Zuul internally uses Ribbon for calling the remote url’s and Ribbon clients are by default lazily loaded up by Spring Cloud on first call. This behavior can be changed for Zuul using the following configuration and will result in the child Ribbon related Application contexts being eagerly loaded up at application startup time.
具體配置以下:
zuul:
ribbon:
eager-load:
enabled: true複製代碼
至此,優化完成,再次重啓服務進行第一次請求,發現狀況已經好多了,你們能夠本身動手嘗試改進一下。
本文主要介紹了Spring Cloud的服務第一次請求超時的優化方法。首先介紹了問題的背景,並排查了問題形成的緣由,主要是Ribbon客戶端的懶加載;而後分別針對zuul網關和服務之間調用的Ribbon客戶端進行配置,使其啓動時便加載Ribbon客戶端的相關上下文信息。最後想說的是,http調用畢竟仍是性能遠低於RPC。。🙂
訂閱最新消息,關注公衆號,加入個人星球。