只需在方法上添加@HystrixCommand,即可实现超时短路。如果 Spring 扫描到该注解注释的类,它将动态生成一个代理,来包装这个方法,并通过专门用于处理远程调用的线程池来管理对该方法的所有调用。
修改 licensingservice 服务中的 OrganizationByRibbonService,OrganizationFeignClient,给其中的方法加上@HystrixCommand的注解。然后再访问接口localhost:10011/licensingByRibbon/11313,localhost:10011/licensingByFeign/11313。多次访问可发现抛出错误com.netflix.hystrix.exception.HystrixRuntimeException,断路器生效,默认情况下操时时间为 1s。
{ "timestamp": 1543823192424, "status": 500, "error": "Internal Server Error", "exception": "com.netflix.hystrix.exception.HystrixRuntimeException", "message": "OrganizationFeignClient#getOrganization(String) timed-out and no fallback available.", "path": "/licensingByFeign/11313/" }可通过设置注解参数来修改操时时间。设置超时时间大于 2s 后便不会报操时错误。(不知道为什么在 Feign 中设置失败,ribbon 中正常。)。一般都是将配置写在配置文件中。
@HystrixCommand(commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "20000") }) 3、后备处理由于远程资源的消费者和资源本身之间存在存在一个"中间人",因此开发人员能够拦截服务故障,并选择替代方案。在 Hystrix 中进行后备处理,非常容易实现。
在 ribbon 中的实现
只需在@HystrixCommand注解中加入属性 fallbackMethod="methodName",那么在执行失败时,便会执行后备方法。注意防备方法必须和被保护方法在同一个类中,并且方法签名必须相同。修改 licensingservice 中 service 包下的 OrganizationByRibbonService 类,改为如下:
@Component public class OrganizationByRibbonService { private RestTemplate restTemplate; @Autowired public OrganizationByRibbonService(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @HystrixCommand(commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") },fallbackMethod = "getOrganizationWithRibbonBackup") public Organization getOrganizationWithRibbon(String id) throws Exception { ResponseEntity<Organization> responseEntity = restTemplate.exchange("http://organizationservice/organization/{id}", HttpMethod.GET, null, Organization.class, id); return responseEntity.getBody(); } public Organization getOrganizationWithRibbonBackup(String id)throws Exception{ Organization organization = new Organization(); organization.setId("0"); organization.setName("组织服务调用失败"); return organization; } }启动应用,多次访问localhost:10011/licensingByRibbon/11313/,可以发现调用失败时,会启用后备方法。
在 feign 中实现
在 feign 中实现后备模式,需要编写一个 feign 接口的实现类,然后在 feign 接口中指定该类。以 licensingservice 为例。首先在 client 包中添加一个 OrganizationFeignClientImpl 类,代码如下:
@Component public class OrganizationFeignClientImpl implements OrganizationFeignClient{ @Override public Organization getOrganization(String orgId) { Organization organization=new Organization(); organization.setId("0"); organization.setName("后备模式返回的数据"); return organization; } }然后修改 OrganizationFeignClient 接口的注解,将@FeignClient("organizationservice")改为@FeignClient(name="organizationservice",fallback = OrganizationFeignClientImpl.class。
重启项目,多次访问localhost:10011/licensingByFeign/11313/,可发现后备服务起作用了。
在确认是否要启用后备服务时,要注意以下两点:
后备是一种在资源操时或失败时提供行动方案的机制。如果只是用后备来捕获操时异常然后只做日志记录,那只需要 try..catch 即可,捕获 HystrixRuntimeException 异常。
注意后备方法所执行的操作。如果在后备服务中调用另一个分布式服务,需要注意用@HystrixCommand 方法注解包装后备方法。
4、实现舱壁模式在基于微服务的应用程序中,通常需要调用多个微服务来完成特定的任务,在不适用舱壁的模式下,这些调用默认是使用同一批线程来执行调用的,而这些线程是为了处理整个 Java 容器的请求而预留的。因此在存在大量请求的情况下,一个服务出现性能问题会导致 Java 容器内的所有线程被占用,同时阻塞新请求,最终容器彻底崩溃。
Hystrix 使用线程池来委派所有对远程服务的调用,默认情况下这个线程池有 10 个工作线程。但是这样很容易出现一个运行缓慢的服务占用全部的线程,所有 hystrix 提供了一种一种易于使用的机制,在不同的远程资源调用间创建‘舱壁’,将不同服务的调用隔离到不同的线程池中,使之互不影响。