La solution au problème des en-têtes de requête manquants lors de l'appel de feign à distance (y compris l'utilisation du pool de threads pour effectuer des appels de simulation asynchrones)

Ajouter des informations de configuration

#配置自定义的线程池
gulimall.thread.core-size=20
gulimall.thread.max-size=200
gulimall.thread.keep-alive-time=10

Ajouter une classe de configuration

//跟配置文件绑定
@ConfigurationProperties(prefix = "gulimall.thread")
@Component
@Data
public class ThreadPoolConfigProperties {
    
    

    private Integer coreSize;
    private Integer maxSize;
    private Integer keepAliveTime;
}

Ajouter une classe de configuration de pool de threads

//开启属性配置(因为ThreadPoolConfigProperties写了@Component,所以就不用写了)
//@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {
    
    
    @Bean
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties pool) {
    
    
        return new ThreadPoolExecutor(pool.getCoreSize(),
                pool.getMaxSize(),
                pool.getKeepAliveTime(), TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(100000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

Dans le processus de feindre d'appeler le service distant, le filtre sera appelé couche par couche. Nous devons réaffecter les informations de l'en-tête de requête transmis par le frontal à la nouvelle requête de l'intercepteur requestInterceptor, nous ajoutons donc ici un classe de configuration: this La méthode peut résoudre le cas où seule une demande de simulation est appelée de manière synchrone.

@Configuration
public class GuliFeignConfig {
    
    
    @Bean
    public RequestInterceptor requestInterceptor() {
    
    

        return new RequestInterceptor() {
    
    

            @Override
            public void apply(RequestTemplate template) {
    
    

                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                if (attributes != null) {
    
    
                    HttpServletRequest request = attributes.getRequest();
                    if (request != null) {
    
    
                        //同步请求头数据 主要同步Cookie
                        String cookie = request.getHeader("Cookie");
                        //给新请求同步的老请求Cookie
                        template.header("Cookie", cookie);
                    }
                }
            }
        };
    }
}
  • Dans notre processus de développement, nous pouvons rencontrer la situation d'utilisation du pool de threads pour appeler d'autres services de manière asynchrone. Parce que lorsque nous démarrons l'appel asynchrone de thread, nous réacquérons un thread dans le pool de threads, il n'y aura donc aucune information d'en-tête de demande. Si d'autres modules de service doivent authentifier le jeton et d'autres informations dans l'en-tête de la demande, que devons-nous faire?
  • Les tâches Feign + asynchrones doivent partager RequestAttributes. Chaque tâche doit setRequestAttributes (), prendre les paramètres de l'en-tête de requête transmis par le frontal et les réattribuer au nouveau thread dans le pool de threads.
@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
    
    
    @Autowired
    MemberFeignService memberFeignService;

    @Autowired
    CartFeignService cartFeignService;
    @Autowired
    WareFeignServicewareFeignService;
    @Autowired
    ThreadPoolExecutor executor;
    //共享前端页面传过来的vo
    ThreadLocal<OrderSubmitVo> confirmVoThreadLocal = new ThreadLocal<>();

/**
     * 去结算
     * 给订单确认ye返回数据
     */
    @Override
    public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
    
    

        //要返回的大对象
        OrderConfirmVo confirmVo = new OrderConfirmVo();

        //在TreadLocal中获取用户
        MemberResVo memberResVo = LoginUserInterceptor.loginUser.get();

        //Feign + 异步任务 需要共享RequestAttributes 每个任务都要setRequestAttributes(),将前端传递过来的请求头里面的参数取出来再重新赋值给线程池里面的新线程。
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        CompletableFuture<Void> getAddressFuture = CompletableFuture.runAsync(() -> {
    
    
            //每一个线程都要共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
            //1 远程查询大对象的第一个属性 收货地址列表
            List<MemberAddressVo> address = memberFeignService.getAddress(memberResVo.getId());
            confirmVo.setAddress(address);
            //Feign在远程调用之前要构造请求,调用很多的拦截器
        }, executor);

        CompletableFuture<Void> cartFuture = CompletableFuture.runAsync(() -> {
    
    
            //每一个线程都要共享之前的请求数据
            RequestContextHolder.setRequestAttributes(requestAttributes);
            //2 远程查询大对象的第二个属性 所有购物项
            List<OrderItemVo> items = cartFeignService.currentUserItems();
            confirmVo.setItems(items);
        }, executor).thenRunAsync(() -> {
    
    
            //执行下一个任务线程
            R r = wareFeignService.getSkuHasStock(ids);
        }, executor);
        CompletableFuture.allOf(getAddressFuture, cartFuture).get();
        return confirmVo;
    }
}

Je suppose que tu aimes

Origine blog.csdn.net/u014496893/article/details/114144850
conseillé
Classement