Openfeign动态构建client实现同服务serviceId不同instanceId互相调用

本文基于springcloud2.0.0.RELEASE和eureka

openfeign2.0.4.RELEASE版本:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-openfeign-core</artifactId>
    <version>2.0.4.RELEASE</version>
</dependency>

工具类:

import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.FeignClientBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Getter
@Component
public class DynamicFeignClient {

  private String serviceId;//一般是xxx-server

  private String instanceId;//一般是ip:port

  private InstanceInfo thisInfo;

  private final FeignClientBuilder feignClientBuilder;

  @Resource
  private EurekaClient eurekaClient;

  public DynamicFeignClient(@Autowired ApplicationContext appContext) {
    feignClientBuilder = new FeignClientBuilder(appContext);
  }

  @PostConstruct
  public void init() {
    ApplicationInfoManager applicationInfoManager = eurekaClient.getApplicationInfoManager();
    serviceId = applicationInfoManager.getEurekaInstanceConfig().getAppname();
    thisInfo = applicationInfoManager.getInfo();

    instanceId = thisInfo.getInstanceId();
  }

  /*
   * 返回若干个client,分别对应不同的服务实例
   * excludeThis=true排除自己
   * */
  public <T> List<T> getClientsList(Class<T> type, boolean excludeThis) {
    FeignClient annotation = AnnotationUtils.findAnnotation(type, FeignClient.class);
    if (annotation == null) {
      throw new IllegalArgumentException("缺少@FeignClient注解");
    }
    List<InstanceInfo> instances = eurekaClient.getApplications().getInstancesByVirtualHostName(getServiceId());
    if (excludeThis) {
      instances = instances.stream().filter(f -> !f.equals(thisInfo)).collect(Collectors.toList());
    }
    String path = annotation.path();
    List<T> ret = new ArrayList<>(instances.size());
    for (InstanceInfo instance : instances) {
      String homePageUrl = instance.getHomePageUrl();
      FeignClientBuilder.Builder<T> builder = feignClientBuilder.forType(type, getServiceId());
      builder.url(homePageUrl);
      builder.path(path);
      ret.add(builder.build());
    }
    return ret;
  }

  public <T> List<T> getClientsList(Class<T> type) {
    return getClientsList(type, false);
  }

}

 

posted @ 2024-05-15 00:34  Jackie_JK  阅读(33)  评论(0编辑  收藏  举报