我们在前两章分别讲了通过Ribbon和Feign对服务进行负载均衡的访问,但是当访问的服务不可用时,可能就会有大量的请求等待从而消耗服务器的资源
通过熔断器hystrix,当服务不可用,或者达到我们设置的某个阈值时,我们就可以快速失败,从而防止资源耗尽,而避免雪崩效应的发生。
下面我们将分别对Ribbon和Feign进行熔断器的配置,代码我们将基于前2章的代码,此处将只只是新添加的代码
1. Ribbon使用RestTemplate配置熔断器
我们基于eureka-ribbon-client项目做修改
1.1 pom中添加hystrix的依赖
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <version>2.2.1.RELEASE</version> </dependency>
1.2 在启动类上加上 @EnableHystrix
package com.devin.eurekaribbonclient; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; @EnableHystrix @EnableEurekaClient @SpringBootApplication public class EurekaRibbonClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaRibbonClientApplication.class, args); } }
1.3 修改Service中RestTemplate对eureka-cleint的调用
增加eureka-client不可用时的熔断方法,当服务接口不可用时,将调用熔断方法 helloFallback
详细代码如下
package com.devin.eurekaribbonclient.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
/**
* @author Devin Zhang
* @className RibbonHelloService
* @description TODO
* @date 2020/3/28 11:54
*/
@Service
public class RibbonHelloService {
@Resource
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "helloFallback")
public String sayHello(String name) {
return restTemplate.getForObject("http://EUREKA-CLIENT/sayHello?name=" + name, String.class);
}
public String helloFallback(String name) {
return "hello " + name + " , response by hystrix";
}
}
1.4 测试
启动eureka-server (7001) eureka-client(7002) eureka-ribbon-client(7004)
访问接口 http://localhost:7004/sayHelloFromRibbon?name=devin ,可以看到接口返回正常
此时关闭 eureka-client ,再次刷新页面可以看到,请求已经进入到熔断器的方法
2. 在Feign中使用熔断器
我们基于上一章的eureka-feign-client 进行改造 ,因为feign中已经引入了熔断器,所以不需要添加新的依赖
2.1 在配置文件 application.yml 中启用熔断器hystrix
feign.hystrix.enabled=true ,完整的配置如下:
eureka:
auth:
user: dev
password: 123456
client:
serviceUrl:
defaultZone: http://${eureka.auth.user}:${eureka.auth.password}@localhost:7001/eureka/
instance:
#使用IP进行注册
prefer-ip-address: true
#配置实例的注册ID
instance-id: ${spring.cloud.client.ip-address}:${server.port}
#心跳时间,即服务续约间隔时间(缺省为30s)
lease-renewal-interval-in-seconds: 5
#发呆时间,即服务续约到期时间(缺省为90s)
lease-expiration-duration-in-seconds: 10
health-check-url-path: /actuator/health
server:
port: 7004
spring:
application:
name: eureka-feign-client
feign:
httpclient:
enabled: true
hystrix:
enabled: true
2.2 在声明式调用中,设置熔断器的调用类
package com.devin.eurekafeignclient.service;
import com.devin.eurekafeignclient.config.FeignConfig;
import com.devin.eurekafeignclient.vo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author Devin Zhang
* @className FeignHelloService
* @description TODO
* @date 2020/3/28 16:49
*/
@FeignClient(value = "eureka-client", configuration = FeignConfig.class,fallback = FeignHelloFallbacjService.class)
public interface FeignHelloService {
@GetMapping(value = "/sayHello")
String sayHello(@RequestParam String name);
@PostMapping(value = "/login", consumes = "application/json")
String login(@RequestBody User user);
}
2.3 定义熔断器调用的实现类
该类实现了我们的声明式调用接口,并实现各个方法,这些方法将在调用的服务不可用时自动进行调用
package com.devin.eurekafeignclient.service; import com.devin.eurekafeignclient.vo.User; /** * @author Devin Zhang * @className FeignHelloFallbacjService * @description TODO * @date 2020/3/30 16:03 */ public class FeignHelloFallbacjService implements FeignHelloService { @Override public String sayHello(String name) { return "hello " + name + " ,this is response by feign hystrix"; } @Override public String login(User user) { return "hello " + user.getUserName() + " ,the server is busy now ,pls retry later,this is response by feign hystrix"; } }
2.4 测试
分别启动 eureka-server 7001 eureka-client 7002 eureka-feign-client 7004
get访问 http://localhost:7004/sayHelloFromFeign?name=devin
post访问 http://localhost:7004/loginFromFeign?userName=devin&userPass=123456
可以看到返回正确的结果
此时,关闭eureka-client,分别访问以上两个接口,将可以看到熔断器hystrix返回的结果
至此,我们分别在Ribbon和Feign实现了Hystrix熔断器的功能