我現在的架構結構大緻是:前端請求,通過zuul轉發到user的接口提供子產品,user接口提供子產品調用user服務子產品的業務功能(feign調用),user服務的業務功能需要調用base服務子產品的一個業務功能(手動調用),大緻就是:前端請求->userApi->userService->baseService。這個流程在兩個地方出現了此問題
1 在接口子產品中出現此錯誤
如果在zuul直接代理的接口層(也就是zuul直接轉發的那一層,我這裡是user接口提供層,userApi)的application.yml中配置了負載均衡,則會出現此問題:
com.netflix.zuul.exception.ZuulException: Forwarding error
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.handleException(RibbonRoutingFilter.java:198) ~[spring-cloud-netflix-zuul-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:173) ~[spring-cloud-netflix-zuul-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:119) ~[spring-cloud-netflix-zuul-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:117) ~[zuul-core-1.3.1.jar:1.3.1]
-------------------------隻截取了一些關鍵錯誤資訊--------------------------------
Caused by: com.netflix.client.ClientException: Load balancer does not have available server for client: SERVICE-USERAPI
at com.netflix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:184) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
at rx.Observable.unsafeSubscribe(Observable.java:10327) ~[rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94) ~[rxjava-1.3.8.jar:1.3.8]
at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42) ~[rxjava-1.3.8.jar:1.3.8]
SERVICE-USERAPI是我的服務名,是因為我在userApi子產品裡配置了如下代碼:
ribbon:
eureka:
enabled: true
zuul是有自己的反向代理和負載均衡功能,解決方法是把這句配置去掉就行。
2 在服務子產品中出現此問題
有時候會在業務層的服務中調用其他服務提供者的服務,這時如果用手動調用服務的方式(使用feign調用時候也一樣),如果在restTemplate上面開啟了@LoadBalanced,但是在配置檔案中未開啟負載均衡,那麼同樣也會出現這個錯誤,解決方法如下:
1 在被調用的服務配置檔案(這裡是baseService的application.yml)中加上:
ribbon:
eureka:
enabled: true
2 同時開啟restTemplate(userService裡開啟)的負載均衡能力
/**
* springCloud相關的一些配置
*
* @author lgs
*/
@Configuration
public class SpringCloudConfig {
/**
* 服務調用工具
*
* @return
* @LoadBalanced 讓RestTemplate在請求時擁有用戶端負載均衡的能力
*/
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
這兩個配置加上之後,手動調用其他服務也會有負載均衡的能力(userService調用baseService裡的服務):
@Override
public ResponseInfo findAllDataBase() {
MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
multiValueMap.add("name", "lgs");
//直接發送post請求
ResponseInfo responseInfo = restTemplate.postForObject(ServiceEnum.SERVICE_BASE.getServicePath() + "/base/sayHello", multiValueMap, ResponseInfo.class);
return responseInfo;
}
記錄錯誤,點滴成長。