记录每天八股文,来源于ChatGPT和deepseek生成答案,如有侵权,请联系删除。
Feign的性能优化?
主要是从Http客户端的角度去优化性能,Feign底层默认是JDK自带的HttpURLConnection,这个是单线程发送Http请求的,不能配置线程池,可以使用能够池化技术的来提升性能,可以选择OkHttp或者HttpClient来替换默认的HttpURLConnection.
Feign怎样实现认证的传递?
实现接口RequestInterceptor,通过header实现认证传递, 在微服务架构中,使用Feign传递认证信息(如Token、JWT等)通常通过以下方式实现,确保服务间调用的安全上下文正确传递:
1. 使用 RequestInterceptor
自动添加请求头
通过自定义Feign拦截器,从当前请求或安全上下文中提取认证信息,并自动添加到Feign请求头中。
步骤:
- 创建拦截器类:
@Component public class FeignAuthInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { // 从请求上下文中获取当前请求的Authorization头 String authHeader = Optional.ofNullable(RequestContextHolder.getRequestAttributes()) .map(ServletRequestAttributes.class::cast) .map(ServletRequestAttributes::getRequest) .map(request -> request.getHeader("Authorization")) .orElse(""); // 或从Spring Security上下文中获取Token(如JWT) Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && authentication.getCredentials() instanceof String) { authHeader = "Bearer " + authentication.getCredentials(); } // 添加认证头到Feign请求 if (!authHeader.isEmpty()) { template.header("Authorization", authHeader); } } }
- Feign客户端启用拦截器:
@FeignClient(name = "target-service", configuration = FeignConfig.class) public interface TargetServiceClient { @GetMapping("/api/data") String getData(); } // 配置类(可选,若拦截器已通过@Component自动注入) public class FeignConfig { @Bean public FeignAuthInterceptor feignAuthInterceptor() { return new FeignAuthInterceptor(); } }
2. 集成OAuth2(如使用Spring Security OAuth)
若系统使用OAuth2协议,可通过OAuth2FeignRequestInterceptor
自动传递Token。
步骤:
- 添加依赖:
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-client</artifactId> </dependency>
- 配置Feign客户端:
@FeignClient( name = "target-service", configuration = OAuth2FeignConfig.class ) public interface TargetServiceClient { // 方法定义 } // 配置类 public class OAuth2FeignConfig { @Bean public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext context) { return new OAuth2FeignRequestInterceptor(context, new DefaultOAuth2ClientContext()); } }
总结
- 通用场景:优先使用
RequestInterceptor
自动传递请求头。 - OAuth2集成:结合Spring Security OAuth2的拦截器也可以实现传递。
通过以上方法,Feign可实现认证信息的无缝传递,确保微服务间调用的安全性。
为什么Feign第一次调用耗时很长?
ribbon默认是懒加载的,只有第一次调用的时候才会生成ribbon对应的组件,这就会导致首次调用的会很慢的问题
Seata中xid怎样通过Feign进行全局传递
在 Seata 中,XID(全局事务 ID)需要在微服务之间进行传递,以保证全局事务的一致性。在使用 Feign 时,XID 可以通过拦截器的方式自动传递。具体过程如下:
- 配置 Feign 拦截器: 在 Seata 中,Feign 会自动将当前的 XID 加入到请求的头部。你需要为 Feign 客户端配置一个拦截器,它会在每个请求的 header 中加入当前的 XID。
- 添加 Seata Feign 拦截器: 通过
@EnableFeignClients
注解启用 Feign,并且在配置类中注册SeataFeignInterceptor
,它会自动在每次发送请求时,将全局事务 ID(XID)传递给下游服务。
@Configuration
@EnableFeignClients
public class FeignConfig {
@Bean
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
String xid = RootContext.getXID();
if (xid != null) {
template.header(RootContext.KEY_XID, xid); // 将 XID 添加到请求头中
}
}
};
}
}
- 传递 XID: 当 Feign 发起 HTTP 请求时,
SeataFeignInterceptor
会把当前全局事务的 XID 传递到请求头中。下游服务收到请求时,会从请求头中读取 XID,并自动设置到RootContext
中,保持全局事务的一致性。 - XID 自动传递: 下游服务在接收到请求后,Seata 会自动将请求头中的 XID 设置到当前线程的
RootContext
中,从而确保事务能够在下游服务中正常执行。
这样,你就可以在通过 Feign 进行微服务调用时,自动传递 XID,实现分布式事务的传递与控制。
Seata 使用的是类似于传统的两阶段提交协议,确保了分布式事务在微服务架构中的一致性和原子性。