我们知道Spring Cloud Fegin默认集成了Spring Cloud Ribbon
那么我们在用Fegin远程调用服务时,可以通过设置Ribbon的调用超时时间来控制服务调用的等待时常,避免出现线程被占用长久等待的问题,同时还能在调用超时时进行重试(之后再写一篇)。当然这和Hystrix的使用是不一样的,一般来说Hystrix设置的超时时间要小于Ribbon的设置的超时时间,不然到了超时时间,Hystrix就先给你熔断了,哪里还有机会重试。。。
这里我们先熟悉下ribbon的超时全局配置和指定服务配置基本使用,我们直接看下eureka注册中心的信息:
有两个客户端EUREKA-CLIENT和EUREKA-CLIENT1作为服务提供者
有个Fegin的客户端EUREKA-FEIGN-CLIENT,用来远程调用服务
EUREKA-CLIENT提供一个接口:
这里在调用方法时,线程睡眠了600ms的时间
先用全局配置方式,我们给fegin客户端增加调用超时时间为500ms:
ribbon:
ConnectTimeout: 500
ReadTimeout: 500
同时fegin客户端有一个接口来远程调用EUREKA-CLIENT服务:
@Component
@FeignClient(name = "eureka-client")
public interface FeignInterface {
@GetMapping(value = "/helloWorld/{name}")
User feignClient(@PathVariable("name") String name);
}
@Service
public class FeignService {
@Autowired
private FeignInterface feignInterface;
public User feignClient(String name) {
User user = feignInterface.feignClient(name);
System.out.println(user);
return user;
}
}
@RequestMapping("/feign")
@RestController
public class FeignController {
@Autowired
private FeignService feignService;
@GetMapping("/{name}")
public User helloFeign(@PathVariable("name") String name) {
return feignService.feignClient(name);
}
}
输入http://localhost:8765/feign/AA测试下是否报超时:
没错,超时了。。。,这就对了,和我们要的结果是一样的
这时想到我们还有一个EUREKA-CLIENT1客户端,可是我不想他的超时时间也是500ms,每个提供远程服务的客户端完全可能因为业务复杂,性能不同导致正常响应的时间不同,所以我们设置相同的超时时间就不够适用了,那么我们就得用上指定服务配置了。
EUREKA-CLIENT1客户端的接口完全和EUREKA-CLIENT客户端的一样,都是睡眠600ms,但是我们希望调用EUREKA-CLIENT1的接口时,不会超时。
先给fegin客户端再加上一个调用EUREKA-CLIENT1客户端服务的接口:
@Component
@FeignClient(name = "eureka-client1")
public interface FeignInterface1 {
@GetMapping(value = "/helloWorld/{name}")
User feignClient(@PathVariable("name") String name);
}
@Service
public class FeignService1 {
@Autowired
private FeignInterface1 feignInterface;
public User feignClient(String name) {
User user = feignInterface.feignClient(name);
System.out.println(user);
return user;
}
}
@RequestMapping("/feign")
@RestController
public class FeignController {
@Autowired
private FeignService feignService;
@Autowired
private FeignService1 feignService1;
@GetMapping("/{name}")
public User helloFeign(@PathVariable("name") String name) {
return feignService.feignClient(name);
}
@GetMapping("/1/{name}")
public User helloFeign1(@PathVariable("name") String name) {
return feignService1.feignClient(name);
}
}
然后加上如下配置为服务指定不同超时策略,eureka-client为500ms,eureka-client1为1000ms:
eureka-client:
ribbon:
ConnectTimeout: 500
ReadTimeout: 500
eureka-client1:
ribbon:
ConnectTimeout: 1000
ReadTimeout: 1000
分别访问http://localhost:8765/feign/AA和http://localhost:8765/feign/1/AA
从图里可以看到,eureka-client访问依旧超时,而eureka-client1访问是成功的,所以我们为不同的服务配置不同的超时策略成功生效
从指定配置代码里可以看出我们配置的其实都是服务名,这是我们服务注册到注册中心所使用的服务名,也是**@FeignClient(name = “eureka-client”)**里的name值:
eureka-client:
ribbon:
ConnectTimeout: 500
ReadTimeout: 500
eureka-client1:
ribbon:
ConnectTimeout: 1000
ReadTimeout: 1000
为什么可以做到这样呢,其实当我们在使用@FeignClient(name = “eureka-client”)注解来生成一个名为eureka-client的feign客户端时,同时也生成了一个名为eureka-client的ribbon客户端,所以我们才能用注解@FeignClient里的name值(value也是一样的)来设置对应的ribbon参数,起到指定服务的效果,不再是全局配置了。