可能會(huì)因?yàn)镋urake觸發(fā)了保護(hù)機(jī)制或者是服務(wù)剔除的延遲深碱,導(dǎo)致服務(wù)調(diào)用到故障實(shí)例,針對(duì)這類問題的容錯(cuò),我們可以加入重試機(jī)制锌畸。
新建工程
- 新建一個(gè)Spring Boot工程,命名為feign-retry(隨意)
- 編輯pom.xml他嚷,主要依賴內(nèi)容如下
<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.....的配置是通過指定服務(wù)配置進(jìn)行配置的
指定服務(wù)配置:
<client>.ribbon.key=value
<client>
代表的是@FeignClient
的value值
在使用@FeignClient(value = "HELLO-CLIENT")
來創(chuàng)建Feign客戶端的時(shí)候蹋绽,同時(shí)也會(huì)創(chuàng)建一個(gè)名為HELLO-CLIENT
的Ribbon客戶端,所以我們可以使用@FeignClient
注解中的name
或者value
屬性值來設(shè)置對(duì)應(yīng)的Ribbon參數(shù)筋蓖。
ConnectTimeout
:請求連接的超時(shí)時(shí)間
ReadTimeout
:請求處理的超時(shí)時(shí)間
OkToRetryOnAllOperations
:對(duì)所有操作請求都進(jìn)行重試
MaxAutoRetriesNextServer
:切換實(shí)例的重試次數(shù)
MaxAutoRetries
:對(duì)當(dāng)前實(shí)例的重試次數(shù)
通過上面的配置卸耘,當(dāng)訪問到故障請求時(shí),它會(huì)在嘗試訪問一次當(dāng)前實(shí)例(次數(shù)由
MaxAutoRetries
控制)粘咖,如果不行就換一個(gè)實(shí)例進(jìn)行訪問蚣抗,如果還是不行,就再換一個(gè)實(shí)例進(jìn)行訪問(次數(shù)由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();
}
}
修改服務(wù)提供實(shí)例
- 添加FeignRetryController類
@RestController
@RequestMapping(value = "/feign")
public class FeignRetryController {
@Autowired
DiscoveryClient discoveryClient;
@RequestMapping(value = "/retry")
public String testFeign() throws InterruptedException {
System.out.println("收到消費(fèi)者請求");
int sleepTime = new Random().nextInt(3000);
System.out.println("進(jìn)入等讽坏,等待時(shí)間為" + sleepTime);
Thread.sleep(sleepTime);
System.out.println("等待時(shí)間為" + sleepTime + "的請求處理結(jié)束");
return "Hello World";
}
}
我們在方法里面加了一個(gè)隨機(jī)數(shù)锭魔,用來測試超時(shí),我們在配置文件里面配置的處理請求超時(shí)時(shí)間為2000路呜,隨機(jī)數(shù)大于2000對(duì)應(yīng)的請求都應(yīng)該會(huì)請求重試迷捧。
測試
啟動(dòng)服務(wù)注冊中心、啟動(dòng)服務(wù)提供實(shí)例胀葱、啟動(dòng)剛剛新建的工程
訪問:http://localhost:9000/feign/retry
ReadTimeout
設(shè)置的值,會(huì)立即對(duì)當(dāng)前實(shí)例再次請求抵屿,第二次請求的隨機(jī)數(shù)為1161庆锦,小于ReadTimeout
設(shè)置的值,正常返回結(jié)果轧葛。
我們這個(gè)例子只測試了對(duì)當(dāng)前實(shí)例請求重試的效果搂抒,自己可以測試一下更換實(shí)例進(jìn)行請求重試的效果艇搀。