V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sunzy
V2EX  ›  Java

feign 是怎么选择 httpclient 的?

  •  
  •   sunzy · 2020-07-13 18:16:08 +08:00 · 2532 次点击
    这是一个创建于 1380 天前的主题,其中的信息可能已经有所发展或是发生改变。
    @FeignClient("service-id")
    

    默认走的是 LoadBalancerFeignClient

    而一旦注解加上了 url,走的就是 DefaultClient 了

    这块是在哪儿处理的?我能不能手动指定使用哪一个?

    第 1 条附言  ·  2020-07-14 11:35:42 +08:00

    可能我描述的不太清楚,再附加一些吧

    背景是我们项目里要调一些其他的服务,有Eureka的,也有通过url调的。 Eureka的就不说了,直接用就行了。

    url的要区分开发环境和线上环境,但他们有一些共性就是一级域名是相同的,二级域名是服务ID 所以就想偷个懒,用拦截器统一设置域名

    @Component
    public class MyFeignInterceptor implements RequestInterceptor {
        @Value("${svc.host}")
        private String svcHost;
    
        @Override
        public void apply(RequestTemplate template) {
            String name = template.feignTarget().name();
            if (name.toLowerCase().endsWith("xxx-svc")){
                template.target("http://" + name.toLowerCase() + "." + svcHost);
            }
        }
    }
    

    这样执行的话,直接会报错,说服务找不到 看了下源码,在FeignClientFactoryBean里会根据@FeignClient注解里的url选择是否走负载均衡(Ribbon) 走Ribbon的话,肯定是获取不到服务的(Eureka里没有嘛)

    所以目前的解决判断是@FeignClient上加一个不为空的url(随便什么都行,只要不为空) 这种看起来不太优雅。

    还想过自定义Ribbon的Rule,看能不能在选择服务那拦截修改,也没成功。

    想问问各位大神,有没有什么高招?

    9 条回复    2020-07-14 10:51:38 +08:00
    k9990009
        1
    k9990009  
       2020-07-13 18:25:52 +08:00
    可以,写在配置文件里

    @FeignClient(value = "service-id",url="${service.url:}")
    sunzy
        2
    sunzy  
    OP
       2020-07-13 18:41:56 +08:00
    @k9990009 这样写走的是 DefaultClient,我想不写 url,而让它不要走 LoadBalancerFeignClient
    twogoods
        3
    twogoods  
       2020-07-13 18:50:42 +08:00
    不写 url 他怎么知道调谁啊,不知道他就要走一次基于服务名的服务发现啊,发现了多个自然就需要 LoadBalancer 了。服务发现好像没有多个实现可选吧,你想拓展继承 LoadBalancerFeignClient 自己实现一个呗
    limuyan44
        4
    limuyan44  
       2020-07-13 19:04:39 +08:00
    你是不是搞错需求了,是要改负载的策略还是改 client 的连接配置?当前的需求肯定是不合理的,代码写死了没有 url 必然走 loadblance,原因楼上也说了,具体可以看他的 factorybean 。
    BBCCBB
        5
    BBCCBB  
       2020-07-13 19:07:37 +08:00
    你在说啥??

    你说的 httpclient 是说用 okhttp, apache httpclient..

    还是说选择哪一个 web 实例去调用??
    sunzy
        6
    sunzy  
    OP
       2020-07-13 19:59:45 +08:00
    @limuyan44
    factorybean 看了,硬编码通过 url 判断来搞的

    我的需求是写一个 feign 拦截器,针对一批共性的 feign client,通过名称和环境,换成 url 访问……
    ilumer
        7
    ilumer  
       2020-07-14 00:50:35 +08:00
    不知道你这个共性指的是啥,如果简单的话,直接在配置文件里指定 feignClient 的 url 直接走 url,不会再使用负载均衡,大概就是这样
    @FeignClient(name = "${feign.name}", url = "${feign.url:null}"),如果配置中心里面没有对应的 key,这个适合就可以走负载均衡,有 key 就可以走你需要的 url
    wangyanrui
        8
    wangyanrui  
       2020-07-14 08:18:40 +08:00
    一脸懵逼的进来,没看懂描述的什么问题。
    feign.SynchronousMethodHandler#client 就是真正执行远程调用的东西,根据你的需求,动态修改这个就可以了
    原因看 feign.SynchronousMethodHandler#invoke 方法
    sunzy
        9
    sunzy  
    OP
       2020-07-14 10:51:38 +08:00
    @ilumer 共性是有一部分微服务不是走 eureka 的,并且 url 都是 serviceId+相同的后缀,并且环境

    现在的解决方案是通过拦截器

    ```
    @Slf4j
    @Component
    public class MyFeignInterceptor implements RequestInterceptor {

    @Value("${svc.host}")
    private String svcHost;

    @Override
    public void apply(RequestTemplate template) {
    String name = template.feignTarget().name();
    if (name.toLowerCase().endsWith("xxx-svc")){
    template.target("http://" + name.toLowerCase() + "." + svcHost);
    }
    }
    }
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5271 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 08:55 · PVG 16:55 · LAX 01:55 · JFK 04:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.