SpringCloud learning-Feign remote call to solve the problem of missing request headers using Feign+CompletableFuture asynchronous calls

SpringCloud learns Feign remote call to call CompletableFuture asynchronously to solve the problem of missing request headers

1. The problem of missing request headers when using Feign for remote calls

When using Feign for remote calls, Feign will automatically construct a new http request before sending it. Therefore, the request header information of the original request will be lost by default. Some important data is lost (Cookie)

Insert picture description here

Solution : Add Feign remote call interceptor, and synchronize the request header information in the interceptor.

Principle : When Feign constructs an http remote call request, it will check whether there is an interceptor RequestInterceptor (the default is not). If so, the interceptor's apply method will be executed first during construction , so the synchronization of request header information is implemented in the apply method It can solve the problem of the loss of the original request header information .

Insert picture description here

Set up the interceptor :

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
y
@Configuration
public class MyFeignConfigration {
    
    
    //设置feign发送请求的拦截器,解决feign远程调用请求头丢失的问题
    @Bean
    public RequestInterceptor requestInterceptor(){
    
    
        return new RequestInterceptor() {
    
    
            //设置以后,Feign在远程调用之前,会先执行apply方法
            @Override
            public void apply(RequestTemplate requestTemplate) {
    
    
                //1.使用RequestContextHolder获取在Controller层进入的请求的所有属性,底层是使用ThreadLocal的机制
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                //2.同步请求头数据  (Cookie)
                String cookie = request.getHeader("Cookie");
                requestTemplate.header("Cookie",cookie);
            }
        };
    }
}

2. Use Feign+CompletableFuture asynchronous call to lose request header

Scenario : When using Feign+CompletableFuture for asynchronous (between multiple threads) remote calls, because the thread has sent changes, the previously added interceptor RequestInterceptor becomes invalid ( because the underlying RequestContextHolder uses ThreadLocal for data sharing in the same thread ), but asynchronous Under the circumstances, the thread changes, and the original request cannot be obtained .

Insert picture description here

Error code : Feign call in CompletableFuture asynchronous task

CompletableFuture<Void> addrFuture = CompletableFuture.runAsync(() -> {
    
    
    //远程查询所有的收获地址
    List<MemberAddr> memberAddrs = memberFeignService.infoById(memberResVo.getId());
    confirmData.setAddress(memberAddrs);
}, executor);
CompletableFuture<Void> cartFuture = CompletableFuture.runAsync(() -> {
    
    
    //远程查询购物车所有选中的购物项
    List<OrderItemVo> userCartItems = cartFeignService.getUserCartItems();
    confirmData.setItems(userCartItems);
}, executor);

Solution : Under the premise of using RequestInterceptor to intercept, manually add the request information before the feign call

//获取原线程的请求参数
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();

CompletableFuture<Void> addrFuture = CompletableFuture.runAsync(() -> {
    
    
    //设置请求原线程下的参数
    RequestContextHolder.setRequestAttributes(attributes);
    //远程查询所有的收获地址
    List<MemberAddr> memberAddrs = memberFeignService.infoById(memberResVo.getId());
    confirmData.setAddress(memberAddrs);
}, executor);
CompletableFuture<Void> cartFuture = CompletableFuture.runAsync(() -> {
    
    
    //设置请求原线程下的参数
    RequestContextHolder.setRequestAttributes(attributes);
    //远程查询购物车所有选中的购物项
    List<OrderItemVo> userCartItems = cartFeignService.getUserCartItems();
    confirmData.setItems(userCartItems);
}, executor);
ignService.getUserCartItems();
    confirmData.setItems(userCartItems);
}, executor);

Guess you like

Origin blog.csdn.net/weixin_44634197/article/details/108619068