Feign:如何实现异步调用

背景

希望将http的调用由同步等待改为异步,仍使用feign的便捷。

使用feign理由

本质上其实feign就是将httpclient常用的操作进行简单封装,且屏蔽底层的httpclient,无感知具体的client实现,轻松完成具体client的替换

解决方案

feign在10.8版本后提供了Async接口(feign-github),如下:

 

demo代码实现

  1. 接口编写

    public interface OriginFeignClient {

        @RequestLine("POST /async/server/api")

        CompletableFuture<String> api(@Param("param") String param);

    }

  2. 接口发布

    @Configuration

    public class OriginFeignClientConfig {

        @Bean

        public SpringEncoder springEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {

            return new SpringEncoder(messageConverters);

        }

        @Bean

        public SpringDecoder springDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {

            return new SpringDecoder(messageConverters);

        }

        @Bean

        public OriginFeignClient originFeignClient(SpringEncoder springEncoder, SpringDecoder springDecoder) {

            return AsyncFeign.asyncBuilder()

                    .encoder(springEncoder)

                    .decoder(springDecoder)

                    .target(OriginFeignClient.class"http://localhost.charlesproxy.com:8090");

        }

    }

  3. 调用

    @GetMapping("testApi")

        public String testAsyncClient() throws ExecutionException, InterruptedException {

            List<CompletableFuture<String>> results = new ArrayList<>();

            for(int i = 0; i < 10; i++) {

                results.add(originFeignClient.api(i+""));

            }

            Thread.sleep(3000);

            int index = 0;

            for (CompletableFuture<String> result : results) {

                String str = result.get();

                log.info(String.format("%d, result:%s, ", index, str));

                index++;

            }

            return "success";

        }

  4. 结果(很明显,是异步调用)

    2021-05-11 14:31:29.989 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 0, result:receive: {"param":"0"} at 2021-05-11 02:31:27.243,

    2021-05-11 14:31:29.993 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 1, result:receive: {"param":"1"} at 2021-05-11 02:31:27.243,

    2021-05-11 14:31:29.995 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 2, result:receive: {"param":"2"} at 2021-05-11 02:31:27.244,

    2021-05-11 14:31:29.995 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 3, result:receive: {"param":"3"} at 2021-05-11 02:31:27.245,

    2021-05-11 14:31:29.995 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 4, result:receive: {"param":"4"} at 2021-05-11 02:31:27.243,

    2021-05-11 14:31:29.996 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 5, result:receive: {"param":"5"} at 2021-05-11 02:31:27.243,

    2021-05-11 14:31:29.996 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 6, result:receive: {"param":"6"} at 2021-05-11 02:31:27.244,

    2021-05-11 14:31:29.997 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 7, result:receive: {"param":"7"} at 2021-05-11 02:31:27.243,

    2021-05-11 14:31:29.997 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 8, result:receive: {"param":"8"} at 2021-05-11 02:31:27.244,

    2021-05-11 14:31:29.998 - INFO [TraceId: , SpanId : ] 24745 --- [nio-8091-exec-5] c.m.a.c.controller.ClientController : 9, result:receive: {"param":"9"} at 2021-05-11 02:31:27.245,

 问题

以上使用仅限雨原生feign使用,那Spring Cloud Open Feign呢?看下代码吧

feign增加的async实现是10.8版本,我们找到Spring boot 2.2.13和相应cloud最新版Hoxton.SR11(当然不是最新,是该小版本下最新,因为目前项目中使用的就是该版本),排查思路就是以@EnableFeignClients为入口

  1. EnableFeignClients内容如下
    @Import(FeignClientsRegistrar.class)
    public @interface EnableFeignClients {
    }

    引入了FeignClientsRegistrar

  2.  FeignClientsRegistrar功能如下:

    1. 扫描@FeignClient,并将其下入到BeanDefinition中

    2. 调用registerFeignClient,构造FeignClientFactoryBean(创建feign的工厂类,关键在此

    3. 进入FeignClientFactoryBean内部看下,构建feign的方法:getTarget():

      1. 从context中去找feign.Feign.Builder的实现(即@Bean),看下当前项目中有哪几种实现:

        1. org.springframework.cloud.openfeign.FeignCircuitBreaker.Builder Spring Cloud定义的通用断路器

        2. feign.hystrix.HystrixFeign.Builder 断路器的原生实现

      2. 先不管哪种builder,最终执行:loadBalance,方法内容如下:

        protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
        		HardCodedTarget<T> target) {
        	Client client = getOptional(context, Client.class);
        	if (client != null) {
        		builder.client(client);
        		Targeter targeter = get(context, Targeter.class);
        		return targeter.target(this, builder, context, target);
        	}
        
        	throw new IllegalStateException(
        			"No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
        }

         好了!!看到我们想要的了,Client的创建,不对,等等!!Client,我们先看下他的实现类是不是包含我们的AsyncClient,F*U*C*K¥%##¥!!!

      3. 一切幻想破灭

原来这个一直都是个平行于现有Spring Cloud Feign实现的东东

 

好了,所以目前的Spring cloud openfeign中仍未支持该特性,先这样用吧

 

 

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在使用 Feign 进行异步调用时,你可以通过以下步骤来实现: 1. 配置 Feign 客户端:在你的 Spring Boot 项目中,添加 Feign 的依赖,并在配置类上加上 `@EnableFeignClients` 注解,以启用 Feign 客户端。 2. 创建 Feign 接口:定义一个接口,用于声明需要调用的远程服务的方法。你可以使用 `@FeignClient` 注解来指定所要调用的服务的名称,并使用 `@RequestMapping` 或其他相关注解来定义接口的请求路径和参数。 3. 实现异步调用:在你的 Feign 接口中,可以使用 `@Async` 注解将方法标记为异步调用。然后,你可以在方法体内使用 Spring 的异步支持(如 `CompletableFuture`)来处理异步任务。 以下是一个简单的示例: ```java @FeignClient(name = "remote-service") public interface RemoteServiceClient { @Async @GetMapping("/api/async") CompletableFuture<String> getAsyncData(); } ``` 在上面的示例中,`RemoteServiceClient` 接口定义了一个异步调用的方法 `getAsyncData()`,它将返回一个 `CompletableFuture` 对象,表示异步任务的结果。通过 `@FeignClient` 注解指定了需要调用的远程服务的名称。 然后,在你的业务代码中,你可以通过调用 `getAsyncData()` 方法来发起异步调用,并使用 `CompletableFuture` 来处理异步任务的结果。 需要注意的是,为了使 Feign 客户端支持异步调用,你还需要在项目的配置文件中增加以下配置: ```properties feign.hystrix.enabled=false ``` 这样,Feign 客户端就能够支持异步调用了。希望这能帮到你!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值