日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Feign源码解析7:nacos loadbalancer不支持静态ip的负载均衡

發布時間:2024/1/21 windows 37 coder
生活随笔 收集整理的這篇文章主要介紹了 Feign源码解析7:nacos loadbalancer不支持静态ip的负载均衡 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

在feign中,一般是通過eureka、nacos等獲取服務實例,但有時候調用一些服務時,人家給的是ip或域名,我們這時候還能用Feign這一套嗎?

可以的。

有兩種方式,一種是直接指定url:

這種是服務端自己會保證高可用、負載均衡那些。

但也可能對方給了多個url(一般不會這樣,但是在app場景下,為了極致的高可用,可能會配置多個服務端地址),此時就需要咱們在客戶端配置多個url,并且進行負載均衡。

此時應該怎么配置呢?前面的文章提到了,可以像下面這樣配置:

spring:
  application:
    discovery:
      client:
        simple:
          instances:
            echo-service-provider:
              - uri: http://1.1.1.1:8082
                metadata:
                  my: instance1
              - uri: http://2.2.2.2:8082
                metadata:
                  my: instance2

但是,這第二種方式下,如果你同時使用了nacos,且打開了spring.cloud.loadbalancer.nacos.enabled=true這個選項,就會發現,調用報錯了。

原因分析

從上面的錯誤堆??梢钥吹?,在執行Double.parseDouble的時候拋了空指針異常,為啥還涉及什么浮點數呢?

我們定位到報錯的地方,原來是獲取服務實例的權重值的時候,報錯了:

很明顯,是因為我們的服務實例里面的metadata字段,沒有nacos.weight這個屬性,所以是null,自然就空指針了。

這里的服務實例是ServiceInstance,這是個通用接口,定義在spring-cloud-commons中的,按理說,你作為一種實現,是需要考慮到傳入的ServiceInstance不一定就有這個屬性,比如可能是Eureka管理的。但是上面報錯的地方又強制假設這個地方一定是metadata擁有nacos.weight。

這塊就是個兼容性bug,看了下最新版本,也還是未修復:

https://github.com/alibaba/spring-cloud-alibaba/blob/2022.x/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/balancer/NacosBalancer.java#L58

接下來,我們看下,那如果是從nacos獲取到的serviceInstance,是不是就沒有這個問題?為啥配置靜態ip地址的時候,就有這個問題。

nacos中獲取到的serviceInstance

咱們先把前面的靜態ip配置去掉,改為從nacos獲取。

從上圖看到,此時實例類型是com.alibaba.cloud.nacos.NacosServiceInstance:

此時自然就不會報錯了。

靜態ip時獲取到的serviceInstance

在獲取服務實例時,入口是org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient#getInstances,它內部聚合了兩個discoveryClient,第一個是simpleDiscoveryClient,這個就是從靜態ip獲取服務實例,可以看到其order是-1,所以它排在了第一位;第二個是nacosDiscoveryClient,由于它的order值是0,所以排序靠后。

從simpleDiscoveryClient中獲取到的serviceInstance的類型就是org.springframework.cloud.client.DefaultServiceInstance,它內部自然是沒有配置nacos相關的metadata的,所以在前面的場景中才會報錯。

解決辦法一

既然nacos這個loadbalancer不兼容靜態ip這種org.springframework.cloud.client.DefaultServiceInstance,那我不使用nacos的loadbalancer不就可以了。

是的,只要你不打開spring.cloud.loadbalancer.nacos.enabled=true這個選項,就不會用到nacos的這個loadbalancer。

我們搜了下這個選項:

這被弄成了一個條件注解。這個條件用于以下的自動裝配類:

在之前的文章里,我們提到了,每個feign服務只要url沒指定,就默認是走負載均衡,就會有一個loadbalancerClient。

每個loadbalancerClient都是通過一個spring容器來的,每個服務都有一個自己的用于創建loadbalancer的spring容器(比如這里的echo-service,就有一個自己的用于創建loadbalancer的spring容器)。這個容器里面默認有啥內容呢?

@LoadBalancerClients(defaultConfiguration = NacosLoadBalancerClientConfiguration.class)

這里的NacosLoadBalancerClientConfiguration.class就會被作為各個spring容器的默認配置類。

這里就會自動配置一個NacosLoadBalancer,一旦有了這個bean,spring-cloud-loadbalancer里的默認配置,就不會生效了:

最終獲取bean的時候,就拿到了nacos的這個NacosLoadBalancer類型的bean,進行負載均衡。

這個辦法的缺點:

這個選項是全局的,不能針對某一個服務來單獨開啟,這個選項一旦關了,那么其他的走nacos的服務,也就沒法用nacosLoadBalancer了。

所以,我們想到了如下的方法。

解決辦法二

我們上面提到,這個nacosLoadBalancer被自動裝配進去的,那么,破解自動裝配的辦法就是你自己定義一個這種類型的bean,它就不會再自動裝配了。

這樣的話,echo-service-provider的spring容器創建時,就會優先把這個配置class注冊到容器里:

這種辦法的優勢是,可以在spring.cloud.loadbalancer.nacos.enabled=true開啟的情況下,解決本文的問題。就是,nacos的依然可以用nacosLoadBalancer來負載均衡;靜態ip的服務,就可以用輪詢這種loadbalancer。

總結

這個feign寫得差不多了,后面寫點別的。如果后續需要補充這塊,再說。

參考

官網有類似bug:

https://github.com/alibaba/spring-cloud-alibaba/issues/3346

總結

以上是生活随笔為你收集整理的Feign源码解析7:nacos loadbalancer不支持静态ip的负载均衡的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。