可能会因为Eurake触发了保护机制或者是服务剔除的延迟,导致服务调用到故障实例,针对这类问题的容错,我们可以加入重试机制。
新建工程
- 新建一个Spring Boot工程,命名为feign-retry(随意)
- 编辑pom.xml,主要依赖内容如下
<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>
- 修改主类
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class RetryApplication {
public static void main(String[] args) {
SpringApplication.run(RetryApplication.class, args);
}
}
- 修改application.yml
server:
port: 9000
eureka:
client:
service-url:
defaultZone: http://peer1:1111/eureka/
spring:
application:
name: feign-retry
HELLO-CLIENT:
ribbon:
ConnectTimeout: 500
ReadTimeout: 2000
OkToRetryOnAllOperations: true
MaxAutoRetriesNextServer: 2
MaxAutoRetries: 1
application.yml中的HELLO-CLIENT.ribbon.....的配置是通过指定服务配置进行配置的
指定服务配置:
<client>.ribbon.key=value
<client>
代表的是@FeignClient
的value值
在使用@FeignClient(value = "HELLO-CLIENT")
来创建Feign客户端的时候,同时也会创建一个名为HELLO-CLIENT
的Ribbon客户端,所以我们可以使用@FeignClient
注解中的name
或者value
属性值来设置对应的Ribbon参数。
ConnectTimeout
:请求连接的超时时间
ReadTimeout
:请求处理的超时时间
OkToRetryOnAllOperations
:对所有操作请求都进行重试
MaxAutoRetriesNextServer
:切换实例的重试次数
MaxAutoRetries
:对当前实例的重试次数
通过上面的配置,当访问到故障请求时,它会在尝试访问一次当前实例(次数由
MaxAutoRetries
控制),如果不行就换一个实例进行访问,如果还是不行,就再换一个实例进行访问(次数由MaxAutoRetriesNextServer
控制),如果还是不行,则返回失败信息。
- 新建RetryService
@Service
@FeignClient(value = "HELLO-CLIENT")
public interface RetryService {
@RequestMapping(value = "/feign/retry")
String hello();
}
- 新建RetryController
@RestController
@RequestMapping(value = "/feign")
public class RetryController {
@Autowired
private RetryService retryService;
@RequestMapping(value = "/retry")
public String retryTest() {
return retryService.hello();
}
}
修改服务提供实例
- 添加FeignRetryController类
@RestController
@RequestMapping(value = "/feign")
public class FeignRetryController {
@Autowired
DiscoveryClient discoveryClient;
@RequestMapping(value = "/retry")
public String testFeign() throws InterruptedException {
System.out.println("收到消费者请求");
int sleepTime = new Random().nextInt(3000);
System.out.println("进入等,等待时间为" + sleepTime);
Thread.sleep(sleepTime);
System.out.println("等待时间为" + sleepTime + "的请求处理结束");
return "Hello World";
}
}
我们在方法里面加了一个随机数,用来测试超时,我们在配置文件里面配置的处理请求超时时间为2000,随机数大于2000对应的请求都应该会请求重试。
测试
启动服务注册中心、启动服务提供实例、启动刚刚新建的工程
访问:http://localhost:9000/feign/retry
ReadTimeout
设置的值,会立即对当前实例再次请求,第二次请求的随机数为1161,小于ReadTimeout
设置的值,正常返回结果。
我们这个例子只测试了对当前实例请求重试的效果,自己可以测试一下更换实例进行请求重试的效果。
网友评论