一,声明式实现客户端
OpenFeign 是一种声明式的 HTTP 客户端,用于简化服务间的 HTTP 调用。使用 OpenFeign 时,只需要通过接口声明和注解,就能轻松实现远程服务的调用,避免了手动编写 HTTP 请求和响应处理的代码。
@FeignClient(value = "service-product") // feign客户端
public interface ProductFeignClient {
// mvc注解的两种使用逻辑
// 1. 标注在Controller上,是接受这样的请求
// 2. 标注在FeignClient上,是发送这样的请求
@GetMapping("/product/{id}")
Product getProductById(@PathVariable("id") Long id);
}
@FeignClient(value = "service-product")
:标明该接口是一个 Feign 客户端,调用名为 service-product
的服务。
@GetMapping("/product/{id}")
:定义了一个 GET 请求,路径中包含了 {id}
变量,该路径对应的就是服务端的某个接口。
@PathVariable("id") Long id
:从路径中提取 id
参数,并传递给方法 getProductById
。
二,使用远程调用接口
要使用这个接口,需要在 Spring Boot 服务中注入 ProductFeignClient
并调用其方法。示例如下:
@Autowired
private ProductFeignClient productFeignClient;
public Product getProduct(Long id) {
return productFeignClient.getProductById(id);
}
当调用 getProductById(id)
方法时,OpenFeign 会自动发送 HTTP 请求到 service-product
服务,并返回 Product
对象。
三,入口配置 Feign
为了确保 Feign 能正常工作,你需要在 Spring Boot 应用中启用 Feign 客户端支持,通常在主类中添加 @EnableFeignClients
注解:
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
四,日志添加Feign Logger
在微服务的配置文件下自定义 Feign 的日志记录器
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
// 设置日志级别
return Logger.Level.FULL;
}
}
在 @FeignClient
注解中引用该配置类:
@FeignClient(value = "service-product", configuration = FeignConfig.class)
public interface ProductFeignClient {
@GetMapping("/product/{id}")
Product getProductById(@PathVariable("id") Long id);
}
为特定 Feign 客户端配置日志:
feign:
client:
config:
service-product: # service-product 是 Feign 客户端的名称
loggerLevel: full # 设置日志级别为 FULL
五.超时配置
超时配置是为了防止 Feign 客户端在调用远程服务时长时间阻塞。我们可以配置连接超时和读取超时,以确保服务调用不会无限期地等待。
在 application.yml
中,我们可以使用以下配置来设置 Feign 的超时时间:
feign:
client:
config:
default:
connectTimeout: 5000 # 连接超时,单位毫秒
readTimeout: 5000 # 读取超时,单位毫秒
connectTimeout
:设置与服务建立连接的超时时间。
readTimeout
:设置读取服务响应的超时时间。
如果连接超时或读取超时,会抛出 FeignException
,这时可以结合重试机制或 Fallback 机制来处理错误。
六.重试机制
Feign 默认启用了重试机制,但是我们可以根据需要自定义重试策略。重试机制会在请求失败时自动重试一定次数,通常用于处理短期网络波动或服务暂时不可用的情况。
6.1启用和配置重试机制
在 application.yml
中配置 Feign 的重试机制:
feign:
client:
config:
default:
retryer:
# 最大重试次数
maxAttempts: 3
# 重试间隔
period: 1000 # 单位毫秒
# 重试间隔的扩展倍数
maxPeriod: 5000 # 单位毫秒
6.2自定义重试器
我们希望自定义重试的逻辑,可以创建一个自定义的 Retryer
类,并将其注入到 Feign 配置中:
import feign.Retryer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public Retryer feignRetryer() {
return new Retryer.Default(1000, 5000, 3); // 1s, 5s, max 3 attempts
}
@Bean
public Logger.Level feignLoggerLevel() {
// 设置日志级别
return Logger.Level.FULL;
}
}
在 @FeignClient
中引用这个配置:
@FeignClient(value = "service-product", configuration = FeignConfig.class)
public interface ProductFeignClient {
@GetMapping("/product/{id}")
Product getProductById(@PathVariable("id") Long id);
}
七.Feign 拦截器(Interceptor)
Feign 拦截器可以让在发送请求之前或响应之后执行自定义操作。拦截器常用于以下场景:
添加请求头(如认证 Token)
记录请求和响应日志
修改请求参数
实现请求签名
Feign 提供 RequestInterceptor
接口,允许我们自定义拦截逻辑,并在所有 Feign 请求中生效。案例添加请求头进行认证:
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;
import java.util.UUID;
@Component
public class XTokenRequestInterceptor implements RequestInterceptor {
/**
* 请求拦截器
* @param template 请求模板
*/
@Override
public void apply(RequestTemplate template) {
System.out.println("XTokenRequestInterceptor .......");
template.header("X-Token", UUID.randomUUID().toString());
}
}
1. @Component
- 该类被
@Component
注解,Spring Boot 会自动扫描并将其注册为 Bean,不需要手动在 FeignConfig
配置中声明。
2. implements RequestInterceptor
- 实现
RequestInterceptor
接口,意味着 apply(RequestTemplate template)
方法会在每次 Feign 请求发送前执行。
3. apply(RequestTemplate template)
template.header("X-Token", UUID.randomUUID().toString());
- 这里的
template.header
方法会为每个 Feign 请求添加 X-Token
头,并赋予一个随机生成的 UUID 作为 Token 值。
- 这在一些应用场景下很有用,例如:
- 需要唯一请求标识(
traceId
)。
- 需要向后端传递 Token 进行认证。
如下为前面定义好的Feign客户端,由于 上述拦截器XTokenRequestInterceptor
已经使用 @Component
注册,它会自动生效,不需要额外的 configuration
绑定。当 getProductById()
被调用时,Feign 将会在 HTTP 请求头中添加 X-Token: [UUID]
@FeignClient(value = "service-product")
public interface ProductFeignClient {
@GetMapping("/product/{id}")
Product getProductById(@PathVariable("id") Long id);
}
八,Fallback 机制
Fallback 机制是在远程调用失败时执行备选方案,通常用于当远程服务不可用时返回默认数据或做错误处理。需要定义一个类来实现 Feign 客户端接口,重写客户端中的调用方法,接口里边之前定义了一个getproductbyid,相当于按照商品的id去查商品的方法,而我们实现的这个方法其实就是兜底回调,它不一定会被调用,只有说远程调用失败以后才会走在该类中提供默认实现:
import org.springframework.stereotype.Component;
@Component
public class ProductFeignFallback implements ProductFeignClient {
@Override
public Product getProductById(Long id) {
// 返回默认值或做错误处理
return new Product(id, "Fallback Product", 0.0);
}
}
启用 Fallback在 Feign 客户端接口中使用 fallback
属性指定 Fallback 类:
@FeignClient(value = "service-product", fallback = ProductFeignFallback.class)
public interface ProductFeignClient {
@GetMapping("/product/{id}")
Product getProductById(@PathVariable("id") Long id);
}
当远程服务调用失败时,Feign 会自动调用 ProductFeignFallback
类中的 getProductById
方法,提供备用响应,返回保底的数据,避免异常。
Fallback 的作用
- 服务降级:当远程服务不可用时,可以提供一个默认值或错误响应,避免系统崩溃。
- 错误处理:通过 Fallback 可以集中处理服务调用失败的逻辑,比如记录日志、发送告警等。