工具:IntelliJ IDEA 2019.2.4
JDK:1.8
补充:为什么要有断路器?
消费者(上游)访问访问生产者(下游),如果生产者出席故障、异常、宕机、等待超时时间等。有可能会造成线程等待,阻塞,不仅影响服务性能,还可能使整个服务挂掉。
熔断机制:上游先访问熔断器,再访问下游。比如设置连续几次访问失败或者当访问失败比例超过多少时,则熔断器直接返回失败。这样就节省了每次等待超时时间。也防止因为局部故障累积导致整个系统奔溃,也可以实现故障转移,服务降级。
PS:本文在consumer(基于Feign的调用)服务上修改,具体搭建详见前文。
1、修改application.yml
server:
port: 8091
spring:
application:
name: cloud-consumer
eureka:
client:
service-url:
defaultZone: http://user:123456@localhost:8080/eureka/ #服务注册中信地址,含有BASIC认证的用户名和密码
instance:
prefer-ip-address: true #将IP注册到服务注册中心
feign:
hystrix:
enabled: true
2、编写fallback处理。如果判断下游服务为失败,则返回什么,这个相当于降级服务了。
第一种:实现类
修改ProviderClient.java,添加fallback=ProviderHystrixImpl参数
@FeignClient(name = "cloud-provider", fallback = ProviderHystrixImpl.class)
public interface ProviderClient {
@RequestMapping(value = "/customer/queryCustomerInfoByTel",method = RequestMethod.GET)
public JSONObject queryCustomerInfoByTel(@RequestParam("tel") String tel);
@RequestMapping(value = "/house/queryHouseList",method = RequestMethod.POST)
public JSONObject queryHouseList(@RequestBody Map<String, Object> requestMap);
}
新建ProviderHystrixImpl实现类,记得加@Component
package com.cloud.consumer.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.cloud.consumer.feign.ProviderClient;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class ProviderHystrixImpl implements ProviderClient {
@Override
public JSONObject queryCustomerInfoByTel(String tel) {
JSONObject object = new JSONObject();
object.put("data","I'm Hystrix from queryCustomerInfoByTel");
return object;
}
@Override
public JSONObject queryHouseList(Map<String, Object> requestMap) {
JSONObject object = new JSONObject();
object.put("data","I'm Hystrix from queryHouseList");
return object;
}
}
第二种:fallbackFactory = HouseManegeFallbackFactory.class工厂,记得加@Component
package com.cloud.consumer.feign;
import com.alibaba.fastjson.JSONObject;
import com.cloud.consumer.factory.HouseManegeFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
@FeignClient(name = "cloud-provider", fallbackFactory = HouseManegeFallbackFactory.class)
public interface ProviderClient {
@RequestMapping(value = "/customer/queryCustomerInfoByTel",method = RequestMethod.GET)
public JSONObject queryCustomerInfoByTel(@RequestParam("tel") String tel);
@RequestMapping(value = "/house/queryHouseList",method = RequestMethod.POST)
public JSONObject queryHouseList(@RequestBody Map<String, Object> requestMap);
}
package com.cloud.consumer.factory;
import com.alibaba.fastjson.JSONObject;
import com.cloud.consumer.feign.ProviderClient;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class HouseManegeFallbackFactory implements FallbackFactory<ProviderClient> {
public ProviderClient create(Throwable cause) {
return new ProviderClient() {
@Override
public JSONObject queryCustomerInfoByTel(String tel) {
JSONObject object = new JSONObject();
object.put("data","I'm Hystrix from queryCustomerInfoByTel");
return object;
}
@Override
public JSONObject queryHouseList(Map<String, Object> requestMap) {
JSONObject object = new JSONObject();
object.put("data","I'm Hystrix from queryHouseList");
return object;
}
};
}
}
4、启动注册中心、启动生产者服务、启动consumer
5、正常访问
6、关闭provider无法,再次访问。
如下两张图,
第一次,等待时间长
第二次立刻返回。
7、重新启动provider,再次调用接口发现还是走熔断器
8、补充:hystrix断路器配置application.yml
feign底层是ribbon的封装,直接配置hystrix超时时间不生效。
必须配置ribbon,ribbon默认超时也是1秒。ribbon的超时时间要大于hystrix的超时时间,否则 hystrix自定义的超时时间毫无意义。
server:
port: 8091
spring:
application:
name: cloud-consumer
eureka:
client:
service-url:
defaultZone: http://user:123456@localhost:8080/eureka/ #服务注册中信地址,含有BASIC认证的用户名和密码
instance:
prefer-ip-address: true #将IP注册到服务注册中心
feign:
hystrix:
enabled: true
#hystrix超时时间配置 (如果不配置的话默认是1000毫秒超时)
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000
ribbon:
ReadTimeout: 10000
ConnectTimeout: 9000