spring cloud 用的是 hystrix,是一个容错组件。
Hystrix实现了 超时机制和断路器模式。
Hystrix是Netflix开源的一个类库,用于隔离远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。主要有以下几点功能:
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.18</version>
</dependency>
测试代码,当出现错误时解决方案,
hystrix简单理解就是对错误以及不符合业务逻辑的项目的一种修复及补丁处理
public class CommonTest extends HystrixCommand<String> { private String name; public CommonTest(String name) { super(HystrixCommandGroupKey.Factory.asKey("myGroup")); this.name=name; } @Override protected String run() throws Exception { Thread.sleep(1000); return Thread.currentThread().getName(); } /* @Override protected String getFallback() { return "超时了,请等等"; }*/ public static void main(String[] args) throws InterruptedException, ExecutionException { CommonTest t= new CommonTest("zhangsan"); Future<String> future=t.queue(); while (!future.isDone()){ Thread.sleep(700); System.out.println(111); } System.out.println(future.get()); //System.out.println(aa1); } }
简单介绍服务降级:就是当访问数据时由于数据量过大或者某些原因,不能提供给前端完整的数据,我们可以提供部分数据给到前端,这样既保证了前端的部分显示,又保证了后端服务继续提供
application.properties中添加如下配置,即feign中开启hystrix
feign.hystrix.enabled=true
在api中添加forback配置
@FeignClient(name = "user-provider",fallback = UserProvider.class) public interface UserApi extends UserHandler { @RequestMapping("/getUser") User getUser(); @RequestMapping("/testMap") Map testMap(); @RequestMapping("/putUser") String putUser(User var1); }
这样如果服务不通或者出现其他故障,将进入UserProvider类当中,所以UserProvider应该实现UserApi,因为这样就可以对每个方法进行处理了
@Component public class UserProvider implements UserApi { /**对服务进行降级*/ @Override public User getUser() { User user = new User(); user.setName("服务不正常,返回默认数据"); return user; } @Override public Map testMap() { return null; } @Override public String putUser(User var1) { return null; } }
测试访问接口:正常访问:

当我在服务方设置睡眠之后:

再次访问:

测试完成,再次测试,如果我在服务端设置两个服务器,其中一个睡眠,一个不睡,然后用ribbon做负载均衡,测试如下:
负载均衡

测试结果:当访问到线程等待的服务器时直接返回降级之后的数据,并没有再次请求别的服务器,如果没有配置hystrix时,会访问其他的机器(感觉好像应该先访问别的机器,等所有的机器都访问不了时才触发降级)

写法二,使用fallbackFactory实现
@FeignClient(name = "user-provider",fallbackFactory = UserProvider.class) public interface UserApi extends UserHandler { @RequestMapping("/getUser") User getUser(); @RequestMapping("/testMap") Map testMap(); @RequestMapping("/putUser") String putUser(User var1); }
编写UserProvider
@Component public class UserProvider implements FallbackFactory<UserApi> { @Override public UserApi create(Throwable throwable) { return new UserApi() { @Override public User getUser() { Throwable cause = throwable.getCause(); String message = cause.getMessage(); User user=new User(); user.setName(message); return user; } @Override public Map testMap() { return null; } @Override public String putUser(User var1) { return null; } }; } }
这样写的好处是对不同的错误可以进行不同的处理
引入pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<groupId>paic.consumer</groupId>
<artifactId>user_consumer</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>paic.common</groupId>
<artifactId>user_api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在启动类中增加注解,如果不加,则hystrix不再生效:
@EnableCircuitBreaker
使用方式:为了代码的规范性,hystrix最好写在service模块当中
@LoadBalanced @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } @Autowired RestTemplate restTemplate; @GetMapping("/getUser") @HystrixCommand(fallbackMethod = "getUserBackMethod") public User getUser() { ResponseEntity<User> userResponseEntity= restTemplate.getForEntity("http://USER-PROVIDER/getUser",User.class); User body = userResponseEntity.getBody(); return body; } public User getUserBackMethod(){ User user =new User(); user.setName("fullBack"); return user; }
在使用feign时,不能在类上加其他的路径,比如

feign不支持这样形式的拼接写法,你可以直接写在下面的方法上面
原文:https://www.cnblogs.com/baierhu/p/14940397.html