源码地址:https://pan.baidu.com/s/1Hmvh1Bbss_Z1w1I7I1mwDw 提取码:e41h
在进行服务调用的时候,可能由于各种原因,服务器挂掉或是网络不稳定超时等,使得响应迟迟不能返回给客户端,而后面的请求又在不断请求这个服务,这样则很可能导致服务瘫痪。Hystrix 熔断器机制就是来处理这种情况的,服务开启熔断器时,若在规定时间内没有返回响应,则认为服务出错了,断开服务,让后面的请求直接返回。让请求直接调用本地的缓存或是本地的其他方法,这就是所谓的 服务降级。
服务降级让请求调用本地的方法,去缓存查找数据,或者返回错误处理等响应信息。(如果客户发送了一个请求,却迟迟得不到回应,可能会一直发送请求,增加服务器的负担,及时返回响应的话,即使不是客户想要的结果,也可以缓解其情绪,减缓其操作)
可以说服务降级通常是熔断机制启动后的处理方法
下面在 service-rest 服务和 service-feign 服务加一些东西就可以实现熔断与服务降级了
为了更好地看效果,稍微改造一下 serviceA1 服务中 controller 类的 getList() 方法
@RequestMapping("/getList")
public List getList() {
long start = System.currentTimeMillis();
try {// 降级测试
long sleeptime = (long) (Math.random() * 3000);
Thread.sleep(sleeptime);
} catch (InterruptedException e) {
e.printStackTrace();
}
List list = new ArrayList();
list.add("author: xiao");
list.add("serverPort: " + serverPort);
long end = System.currentTimeMillis();
System.out.println("响应时间:" + (end - start));
return list;
}
主要是让线程执行这个方法时,睡眠 0~3 s 再返回结果,后面会设置熔断的超时时间为 2s ,即服务调用时,若 2s 还未返回结果,则熔断请求,并进行服务降级。
再就是在 serviceA1 的控制台输出了该请求的响应时间
1. pom.xml 加入 hystrix 依赖
org.springframework.cloud
spring-cloud-starter-hystrix
1.4.1.RELEASE
2. application.properties 加入如下配置
## 设置所有实例的默认值,超时时间,超过该时间未响应则熔断,不写默认 1s,这里设置为 2s
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000
3. service 类改成如下
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
@Service
public class ServiceRestService {
@Autowired
private RestTemplate restTemplate;
@SuppressWarnings("unchecked")
@HystrixCommand(fallbackMethod = "getWrongInfo")
public List getServiceA() {
return restTemplate.getForObject("http://serviceA/getList", List.class);
// return restTemplate.getForEntity("http://localhost:7071/getList", List.class).getBody();
}
// hystrix fallback方法
public List getWrongInfo() {
List list = new ArrayList();
list.add("获取 A 服务异常,请稍后再试。。。");
return list;
// return restTemplate.getForObject("http://xxx/xxx", List.class);
}
}
(1)在调用 A 服务的方法上加了注解 @HystrixCommand(fallbackMethod = “getWrongInfo”),指明这个请求熔断后执行 getWrongInfo 这个方法。
(2)服务降级方法方法名可以自定义,但是参数和返回值必须与请求的方法是一样的
(3)除了可以在本地处理,还可以让请求去调用其他服务器的其他方法
4. 启动类加入注解 @EnableCircuitBreaker 标识开启熔断器功能
5. 熔断降级测试
启动服务注册中心,serviceA1 服务和 service-rest 服务,输入 localhost:7073/getListRest
试着多刷新几次,看看 serviceA1 的控制台,可以发现每次调用了服务降级方法的时候,serviceA1 的响应时间都是超过了 2000 ms
修改内容基本差不多,只是 service-feign 服务工程的 service 层是接口,所以服务降级方法是写一个类去实现这个接口,具体如下:
1. pom.xml 加入 hystrix 依赖
org.springframework.cloud
spring-cloud-starter-hystrix
1.4.1.RELEASE
2. application.properties 加入如下配置
## 开启熔断器
feign.hystrix.enabled=true
### 超时时间,超过该响应时间则降级处理
### 不加该配置默认为 1s
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
在配置文件中开启熔断器,启动类不用修改
3. 创建 ServiceFeignFallback 类实现自己工程 service 层的相应接口,本例如下:
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import com.xiao.service.ServiceFeignService;
@Component
public class ServiceFeignFallback implements ServiceFeignService{
@Override
public List getListFegin() {
List list = new ArrayList();
list.add("调用 A 服务异常,请稍后重试");
return list;
}
}
熔断后调用该降级方法
4. 修改 service 层接口
import java.util.List;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import com.xiao.fallback.ServiceFeignFallback;
@FeignClient(value="serviceA", fallback=ServiceFeignFallback.class)
public interface ServiceFeignService {
//请求映射路径 /serviceA/getList 同 A 服务的映射路径
@RequestMapping(value="/getList")
public List getListFegin();
}
fallback=ServiceFeignFallback.class 指定降级方法地址
5. 熔断降级测试
启动注册中心,serviceA1 服务和 service-feign 服务,输入 localhost:7074/getListFeign
ps:
(1)Feign 加入熔断器后进行测试,我发现虽然降级方法成功调用了,但是我设置的熔断超时时间没有起作用,还是超过 1s 就熔断降级了。
(2)当响应时间超过 1s 时会重试 1 次
(3)当我同时开启 serviceA1、serviceA2 服务时,A2 服务没有设置睡眠,再次发送请求,当调用 A1 超过 1s 后,会成功调用 A2。(A1、A2 是 serviceA 的集群)
(4)由于 Feign 自动集成了 Ribbon ,其中有 Ribbon 的超时、重试等情况,具体情况还没摸清楚,有知道的朋友可以留言指导一下。
博主经验尚浅,也暂无微服务相关项目经验,如果理解不到位甚至理解错误,希望评论区讨论,请多指教!