- 老的客户端是用服务端依赖swagger-codegen-maven-plugin在打包的时候自动生成的,服务接口调用本质上是用的restTemplate
- 切换为微服务以后,只需要在restTemplate上面加一个@LoadBalanced注解即可根据服务名调用
遇到的问题
1.provider并发不足,会进入熔断短路状态:Hystrix circuit short-circuited and is OPEN
consumer会一直重试,可能会让provider奔溃,所以consumer应该在provider返回熔断错误以后一段时间内不再调用provider,等provider恢复以后再调用
处理方案:我的consumer业务场景是MQ消费消息做离线任务处理,在自定义RestTemplate的errorHandler中识别出provider出现500错误以后休眠30秒
也可以在LoadBalancerInterceptor拦截器中处理,也可以自己重写调用方法并加上HystrixCommand熔断方法
2.MQ消费是多线程消费,在程序启动的时候经常出现nested exception is java.net.UnknownHostException
原因:推测是因为Ribbon进行客户端负载均衡的Client并不是在服务启动的时候就初始化好的,而是在调用的时候才会去创建相应的Client
解决方案:ribbon有一个eager-load配置项,启用以后可以在实例化类以后提前创建好client
ribbon:
ReadTimeout: 60000
ConnectTimeout: 10000
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 1
OkToRetryOnAllOperations: true
ServerListRefreshInterval: 3000 #刷新服务列表的时间
eureka:
enabled: true
restclient:
enabled: true
http:
client:
enabled: true
# 懒加载,启动时创建
eager-load:
clients: data-service
enabled: true
@Autowired
@Qualifier("loadBalanced")
@LoadBalanced
private RestTemplate loadBalanced;
public @Bean
ApiClient apiClient() throws Exception {
ApiClient c = new ApiClient(apiClientRestTemplate());
c.setBasePath(basePath);
return c;
}
private RestTemplate apiClientRestTemplate() {
ResponseErrorHandler errorHandler = apiClientErrorHandler();
loadBalanced.setErrorHandler(errorHandler);
return loadBalanced;
}
private ResponseErrorHandler apiClientErrorHandler() {
return new ResponseErrorHandler() {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
// return !response.getStatusCode().is2xxSuccessful();
HttpStatus status = response.getStatusCode();
return status.is4xxClientError() || status.is5xxServerError();
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
try (InputStream in = response.getBody()) {
String errorStr = IOUtils.toString(in);
log.error(errorStr);
// 系统异常,阻塞休眠30秒, 可以写入到配置文件
if(response.getStatusCode().is5xxServerError()){
try {
TimeUnit.SECONDS.sleep(30);
} catch (InterruptedException e) {
log.error("", e);
}
}
} catch (Exception e) {
log.error("{}", e);
}
throw new RuntimeException("系统繁忙,请稍后再试");
}
};
}