依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
主启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class OrderFeignMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderFeignMain80.class,args);
}
}
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id);
}
调用
@RestController
public class OrderFeignController {
@Resource
private PaymentFeignService paymentFeignService;
@GetMapping(value = "/consumer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
return paymentFeignService.getPaymentById(id);
}
}
当前版本修改超时时间有3中方案:
(1) feign client
feign:
client:
config:
default:
#default为全局配置,如果要单独配置每个服务,改为服务名
# 请求连接的超时时间
connectTimeout: 1000,#默认为10s
# 请求处理的超时时间,#默认为60s
readTimeout: 1000
#这是默认的配置,单次请求最大时长是1s,默认重试5次
#所以如果使用默认配置,超时时间最长也就6s左右,如果要更长时间,则需要自定义了
retryer: feign.Retryer.Default
(2)hystrix
#默认为true可不配置
#hystrix.command.default.execution.timeout.enabled=true
#默认为1s
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000
(3)rubbin
Feign 的负载均衡底层用的就是 Ribbon
在application.properties中添加如下配置,超过5秒没连接上报连接超时,如果超过5秒没有响应,报请求超时
ribbon:
# 请求处理的超时时间
ReadTimeout: 1000 #单位为秒
# 请求连接的超时时间 默认的时间为 1 秒
ConnectTimeout: 1000
rubbin默认等待1秒钟,超时报错
那么问题来了,我把这三个配置项都配置上去了,而且把值改大,服务仍然秒超时。
二、解决方案
查阅了各种资料后,发现 FeignClient的默认超时时间为10s,不会开启重试机制。
看见重点了吗,“不会开启重试机制”,没有重试,超时时间再长也没用,所以还得手动加上。
#这是默认的配置,单次请求最大时长是1s,默认重试5次
#所以如果使用默认配置,超时时间最长也就6s左右,如果要更长时间,则需要自定义了
feign.client.config.default.retryer=feign.Retryer.Default
ribbon:
# 请求处理的超时时间
ReadTimeout: 1000 #单位为秒
# 请求连接的超时时间 默认的时间为 1 秒
ConnectTimeout: 1000
#这是默认的配置,单次请求最大时长是1s,默认重试5次
#所以如果使用默认配置,超时时间最长也就6s左右,如果要更长时间,则需要自定义了
feign.client.config.default.retryer=feign.Retryer.Default
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
logging:
level:
com.atguigu.springcloud.service.PaymentFeignService: debug
application.yml
feign:
client:
config:
default:
#default为全局配置,如果要单独配置每个服务,改为服务名
# 请求连接的超时时间,#默认为10s
connectTimeout: 1000
# 请求处理的超时时间,#默认为60s
readTimeout: 1000
#默认重试5次
retryer: feign.Retryer.Default
@Configuration
public class FeignClientConfiguration {
//自定义重试次数
@Bean
public Retryer feignRetryer() {
// period=100 发起当前请求的时间间隔,单位毫秒
// maxPeriod=1000 发起当前请求的最大时间间隔,单位毫秒
// maxAttempts=5 最多请求次数,包括第一次
Retryer retryer = new Retryer.Default(100, 1000, 5);
return retryer;
}
//自定义请求超时时间
@Bean
public Request.Options feignRequest() {
// connectTimeoutMillis=1000 链接超时时间
// readTimeoutMillis=1000 响应超时时间,如果超过10秒没有接过发起下一次请求
Request.Options options = new Request.Options(1000, 5000);
return options;
}
}
@FeignClient(name = "Ekafka-DW", url = "${ecollector.server.url}",
configuration = FeignClientConfiguration.class)
public interface EServerClient {
@RequestMapping(method = RequestMethod.GET, value = "/test2/tenants/{tenant_id}/clusters/{cluster_id}/cgs/{group}")
List<String> getTest2(@PathVariable("tenant_id") String tenantId,
@PathVariable("cluster_id") String clusterId,
@PathVariable("group") String group);
}
一般使用的配置文件
FeignClientConfiguration.class
@Configuration
public class FeignClientConfiguration {
//自定义重试次数
@Bean
public Retryer feignRetryer() {
// period=100 发起当前请求的时间间隔,单位毫秒
// maxPeriod=1000 发起当前请求的最大时间间隔,单位毫秒
// maxAttempts=5 最多请求次数,包括第一次
Retryer retryer = new Retryer.Default(100, 1000, 3);
return retryer;
}
//自定义请求超时时间
@Bean
public Request.Options feignRequest() {
// connectTimeoutMillis=1000 链接超时时间
// readTimeoutMillis=1000 响应超时时间,如果超过10秒没有接过发起下一次请求
Request.Options options = new Request.Options(1000, 5000);
return options;
}
//日志配置
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
//请求https时忽略证书
@Bean
public Client feignClient() {
Client trustSSLSockets = new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());
return trustSSLSockets;
}
private SSLSocketFactory getSSLSocketFactory() {
try {
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//Do your validations
return true;
}
};
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
return sslContext.getSocketFactory();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}
feign自己的请求风格:
@FeignClient(name = "test", url = "localhost:8080",
configuration = FeignClientConfiguration.class)
public interface EServerClient {
@RequestLine("GET /test1")
String getTest1();
@RequestLine("GET /test2/{id}")
String getTest2(@PathVariable("id") long id);
}
在配置类中声明
@Configuration
public class FeignClientConfiguration {
//支持feign自己的请求风格,不支持SpringMVC的风格
@Bean
public Contract useFeignAnnotations() {
return new Contract.Default();
}
}