feign client使用自定义名字服务

2021-07-29 15:28:23 浏览数 (2)

公司内部有名字服务,在使用feign client的时候,也希望可以访问名字服务对应的IP和端口

名字服务

demo这里假设名字服务是从hashmap中得到的,使用前缀mao://

代码语言:javascript复制
@Getter
@SuppressWarnings("UnstableApiUsage")
public class CustomLoadBalancer {
    private static final Map<String, HostAndPort> HOST_AND_PORT_HASH_MAP = new HashMap<>();

    static {
        HOST_AND_PORT_HASH_MAP.put("baidu", HostAndPort.fromString("www.baidu.com:80"));
        HOST_AND_PORT_HASH_MAP.put("netEasy", HostAndPort.fromString("www.163.com:80"));
    }
    private static final String PROTOCOL_PREFIX = "mao://";

    private final String name;

    private CustomLoadBalancer(String name) {
        this.name = name;
    }

    /**
     * 解析mao://{name}/hello/world
     */
    public static CustomLoadBalancer parse(String url) {
        Preconditions.checkArgument(CustomLoadBalancer.isAcceptable(url));
        String urlBody = url.substring(PROTOCOL_PREFIX.length());
        int index = urlBody.indexOf("/");
        String name = index > 0 ? urlBody.substring(index) : urlBody;

        if (!HOST_AND_PORT_HASH_MAP.containsKey(name)) {
            throw new IllegalArgumentException("there is not host and port for "   name);
        }
        return new CustomLoadBalancer(name);
    }

    public static boolean isAcceptable(String url) {
        return url.startsWith(PROTOCOL_PREFIX);
    }

    public HostAndPort getHostAndPort() {
        HostAndPort hostAndPort = HOST_AND_PORT_HASH_MAP.get(name);
        if (hostAndPort == null) {
            throw new IllegalArgumentException("there is not host and port for "   name);
        }
        return hostAndPort;
    }
}

feign clieng客户端

使用自定义客户端可以实现对名字服务的调用,来重建请求URL

代码语言:javascript复制
@Slf4j
@SuppressWarnings("UnstableApiUsage")
public class TenmaoFeignClient  extends LoadBalancerFeignClient {
    public static final String BALANCER = "ribbon";

    public TenmaoFeignClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory, SpringClientFactory clientFactory) {
        super(delegate, lbClientFactory, clientFactory);
    }

    @Override
    public Response execute(Request request, Request.Options options) throws IOException {
        log.info("feign client request:{} ", request);
        URI orgUri = URI.create(request.url());
        String listOfServers = ConfigurationManager.getConfigInstance()
                .getString(Joiner.on(".").join(orgUri.getHost(), BALANCER, ListOfServers.key()));
        if (CustomLoadBalancer.isAcceptable(listOfServers)) {
            CustomLoadBalancer balancer = CustomLoadBalancer.parse(listOfServers);
            HostAndPort hostAndPort = balancer.getHostAndPort();
            //重建请求URL
            String url = String.format("http://%s:%d%s?%s", hostAndPort.getHost(), hostAndPort.getPort(), orgUri.getRawPath(), orgUri.getRawQuery());
            URI newUrl = URI.create(url);
            Map<String, Collection<String>> headers = new LinkedHashMap(request.headers());
            Request newRequest = Request.create(request.httpMethod(), newUrl.toASCIIString(), headers, request.requestBody());
            return super.getDelegate().execute(newRequest, options);
        }
        return super.execute(request, options);
    }

    @Override
    protected IOException findIOException(Throwable t) {
        return super.findIOException(t);
    }

    @Override
    public Client getDelegate() {
        return super.getDelegate();
    }
}

feign配置: 使用自定义feign client

代码语言:javascript复制
@Slf4j
@Configuration
public class FeignClientConfiguration {
    @ConditionalOnMissingBean(Client.class)
    @Bean
    public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
                              SpringClientFactory clientFactory) {
        return new TenmaoFeignClient(new Client.Default(null, null),
                cachingFactory, clientFactory);
    }
}

配置文件

代码语言:javascript复制
eureka:
  client:
    enabled: false

home:
  ribbon:
    listOfServers: mao://baidu

0 人点赞