欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?cloud如何實現(xiàn)FeignClient指定Zone調(diào)用

 更新時間:2022年03月01日 10:40:19   作者:干貨滿滿張哈希  
這篇文章主要介紹了Spring?cloud如何實現(xiàn)FeignClient指定Zone調(diào)用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

本文基于Spring Cloud Fincheley SR3

背景介紹

目前項目多個區(qū)域多個集群,這些集群共用同一個Eureka集群。

通過設(shè)置eureka.instance.metadata-map.zone設(shè)置不同實例所屬的zone,zone之間不互相調(diào)用,只有zone內(nèi)部調(diào)用(其實這里用zone做了集群隔離,實際上集群肯定是跨可用區(qū)的,這里的eureka中的zone在我們項目里面并不是可用區(qū)的概念)。

對應配置(假設(shè)調(diào)用的服務(wù)名字是service-provider)

# 當前實例所在區(qū)域,同時由于NIWSServerListFilterClassName配置的是ZoneAffinityServerListFilter并且EnableZoneAffinity和EnableZoneExclusivity都是true,只有處于同一個zone的實例才會被調(diào)用
eureka.instance.metadata-map.zone=local
service-provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.AvailabilityFilteringRule
service-provider.ribbon.NIWSServerListFilterClassName=com.netflix.loadbalancer.ZoneAffinityServerListFilter
service-provider.ribbon.EnableZoneAffinity=true
service-provider.ribbon.EnableZoneExclusivity=true
service-provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.AvailabilityFilteringRule
# ribbon.ServerListRefreshInterval時間內(nèi)有多少斷路次數(shù)就觸發(fā)斷路機制
niws.loadbalancer.service-provider.connectionFailureCountThreshold=3
niws.loadbalancer.service-provider.circuitTripTimeoutFactorSeconds=10
niws.loadbalancer.service-provider.circuitTripMaxTimeoutSeconds=30

但是,統(tǒng)一管理后臺就比較麻煩了。理想情況下,應該是每個微服務(wù)做自己的管理接口封裝為OpenFeignClient給管理后臺調(diào)用,但是在這種場景下,只能每個集群部署一個管理后臺。這樣很不方便。

能不能通過簡單地改造還有配置,實現(xiàn)傳入zone來指定OpenFeignClient調(diào)用哪個zone的實例呢?

分析

首先,Eureka是同一個集群。在Eureka上面有service-provider的所有不同zone的實例信息

Ribbon拉下來的本地緩存,是有定時任務(wù)從EurekaClient中拉取的

拉下來之后,通過NIWSServerListFilter進行過濾,如果我們制定過濾類為com.netflix.niws.loadbalancer.DefaultNIWSServerListFilter,那么就是什么也不過濾,直接返回從Eureka上面拉取的,也就是返回所有zone的所有對應實例

這里放上源碼

DynamicServerListLoadBalancer.java

?
public void updateListOfServers() {
? ? List<T> servers = new ArrayList<T>();
? ? if (serverListImpl != null) {
? ? ? ? servers = serverListImpl.getUpdatedListOfServers();
? ? ? ? LOGGER.debug("List of Servers for {} obtained from Discovery client: {}",
? ? ? ? ? ? ? ? getIdentifier(), servers);
? ? ? ? if (filter != null) {
? ? ? ? ? ? //通過指定NIWSServerListFilter過濾
? ? ? ? ? ? servers = filter.getFilteredListOfServers(servers);
? ? ? ? ? ? LOGGER.debug("Filtered List of Servers for {} obtained from Discovery client: {}",
? ? ? ? ? ? ? ? ? ? getIdentifier(), servers);
? ? ? ? }
? ? }
? ? updateAllServerList(servers);
}
?

默認的LoadBalancer是什么呢?

通過查看org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration的源代碼:

public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerList<Server> serverList, ServerListFilter<Server> serverListFilter, IRule rule, IPing ping, ServerListUpdater serverListUpdater) {
? ? ? ? return (ILoadBalancer)(this.propertiesFactory.isSet(ILoadBalancer.class, this.name) ? (ILoadBalancer)this.propertiesFactory.get(ILoadBalancer.class, config, this.name) : new ZoneAwareLoadBalancer(config, rule, ping, serverList, serverListFilter, serverListUpdater));
? ? }

我們知道,只要沒自定義(通過@RibbonClient注解),或者配置(通過ribbon.NFLoadBalancerClassName),默認就是ZoneAwareLoadBalancer。

注意這里構(gòu)造器也和其他的LoadBalancer不一樣,其他的都是調(diào)用IClientConfigAware接口方法,這里是直接構(gòu)造器。

ZoneAwareLoadBalancer的選擇Server源碼

if (!ENABLED.get() || getLoadBalancerStats().getAvailableZones().size() <= 1) {
? ? logger.debug("Zone aware logic disabled or there is only one zone");
? ? return super.chooseServer(key);
}
Server server = null;
try {
? ? LoadBalancerStats lbStats = getLoadBalancerStats();
? ? Map<String, ZoneSnapshot> zoneSnapshot = ZoneAvoidanceRule.createSnapshot(lbStats);
? ? logger.debug("Zone snapshots: {}", zoneSnapshot);
? ? if (triggeringLoad == null) {
? ? ? ? triggeringLoad = DynamicPropertyFactory.getInstance().getDoubleProperty(
? ? ? ? ? ? ? ? "ZoneAwareNIWSDiscoveryLoadBalancer." + this.getName() + ".triggeringLoadPerServerThreshold", 0.2d);
? ? }
? ? if (triggeringBlackoutPercentage == null) {
? ? ? ? triggeringBlackoutPercentage = DynamicPropertyFactory.getInstance().getDoubleProperty(
? ? ? ? ? ? ? ? "ZoneAwareNIWSDiscoveryLoadBalancer." + this.getName() + ".avoidZoneWithBlackoutPercetage", 0.99999d);
? ? }
? ? Set<String> availableZones = ZoneAvoidanceRule.getAvailableZones(zoneSnapshot, triggeringLoad.get(), triggeringBlackoutPercentage.get());
? ? logger.debug("Available zones: {}", availableZones);
? ? if (availableZones != null && ?availableZones.size() < zoneSnapshot.keySet().size()) {
? ? ? ? //核心看這里,我們只要指定了zone,而不是隨機,就能通過getLoadBalancer獲取到對應zone的loadbalancer從而返回對應zone的實例
? ? ? ? String zone = ZoneAvoidanceRule.randomChooseZone(zoneSnapshot, availableZones);
? ? ? ? logger.debug("Zone chosen: {}", zone);
? ? ? ? if (zone != null) {
? ? ? ? ? ? BaseLoadBalancer zoneLoadBalancer = getLoadBalancer(zone);
? ? ? ? ? ? server = zoneLoadBalancer.chooseServer(key);
? ? ? ? }
? ? }
} catch (Exception e) {
? ? logger.error("Error choosing server using zone aware logic for load balancer={}", name, e);
}
if (server != null) {
? ? return server;
} else {
? ? logger.debug("Zone avoidance logic is not invoked.");
? ? return super.chooseServer(key);
}

我們來實現(xiàn)我們自己的LoadBalancer,擴展ZoneAwareLoadBalancer即可

實現(xiàn)

package com.netflix.loadbalancer;
import com.netflix.client.config.IClientConfig;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
@Log4j2
public class ZoneChosenLoadBalancer<T extends Server> extends ZoneAwareLoadBalancer {
? ? //通過ThreadLocal指定Zone,所以不能開啟Hystrix
? ? //所以配置:feign.hystrix.enabled=false
? ? //開啟hystrix會導致切換線程執(zhí)行
? ? private static ThreadLocal<String> zoneThreadLocal = new ThreadLocal<>();
? ? public static void setZone(String zone) {
? ? ? ? zoneThreadLocal.set(zone);
? ? }
? ? /**
? ? ?* 必須調(diào)用這個方法傳入對應的Bean初始化,其他構(gòu)造器是不完整的
? ? ?* @see org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration
? ? ?* @param clientConfig
? ? ?* @param rule
? ? ?* @param ping
? ? ?* @param serverList
? ? ?* @param filter
? ? ?* @param serverListUpdater
? ? ?*/
? ? public ZoneChosenLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping, ServerList serverList, ServerListFilter filter, ServerListUpdater serverListUpdater) {
? ? ? ? super(clientConfig, rule, ping, serverList, filter, serverListUpdater);
? ? }
? ? @Override
? ? public Server chooseServer(Object key) {
? ? ? ? try {
? ? ? ? ? ? String zone = zoneThreadLocal.get();
? ? ? ? ? ? if (StringUtils.isBlank(zone)) {
? ? ? ? ? ? ? ? log.info("zone is blank, use base loadbalancer");
? ? ? ? ? ? ? ? return super.chooseServer(key);
? ? ? ? ? ? }
? ? ? ? ? ? BaseLoadBalancer zoneLoadBalancer = getLoadBalancer(zone);
? ? ? ? ? ? Server server = zoneLoadBalancer.chooseServer(key);
? ? ? ? ? ? if (server != null) {
? ? ? ? ? ? ? ? return server;
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? log.info("server is null for zone {}, use base loadbalancer", zone);
? ? ? ? ? ? ? ? return super.chooseServer(key);
? ? ? ? ? ? }
? ? ? ? } finally {
? ? ? ? ? ? //無論如何都要remove
? ? ? ? ? ? zoneThreadLocal.remove();
? ? ? ? }
? ? }
}

配置類

注意不能通過文件配置實現(xiàn)類,走IClientConfigAware,上面源代碼里說明了原因,ZoneAwareLoadBalancer的構(gòu)造本來就特殊:

import com.netflix.loadbalancer.MultiZoneLoadBalancerConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Configuration;
@Configuration
//name對應要調(diào)用的微服務(wù)
@RibbonClient(name = "service-provider", configuration = MultiZoneLoadBalancerConfiguration.class)
public class ServiceScaffoldProviderLoadBalancerConfiguration {
}
package com.netflix.loadbalancer;
import com.netflix.client.config.IClientConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MultiZoneLoadBalancerConfiguration {
? ? @Bean
? ? public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerList<Server> serverList, ServerListFilter<Server> serverListFilter, IRule rule, IPing ping, ServerListUpdater serverListUpdater) {
? ? ? ? return new ZoneChosenLoadBalancer(config, rule, ping, serverList, serverListFilter, serverListUpdater);
? ? }
}

需要修改的配置

#關(guān)閉feign hystrix
feign.hystrix.enabled=false
#指定對應微服務(wù)的list不過濾
service-provider.ribbon.NIWSServerListFilterClassName=com.netflix.niws.loadbalancer.DefaultNIWSServerListFilter

Spring cloud Eureka: 指定Zone

有坑。

先說結(jié)論

如果想給當前服務(wù)指定屬于哪個zone, 使用

eureka.instance.metadata-map.zone=myzone

屬性是無效的,而應該使用:

eureka.client.availabilityZones.beijing=myzone # beijing是region

同時指定region:

eureka.client.region=beijing

至于原因,可以在EurekaClientConfigBean的源碼中找到:

@Override
? ? public String[] getAvailabilityZones(String region) {
? ? ? ? String value = this.availabilityZones.get(region);
? ? ? ? if (value == null) {
? ? ? ? ? ? value = DEFAULT_ZONE;
? ? ? ? }
? ? ? ? return value.split(",");
? ? }

也就是說在判斷當前服務(wù)屬于哪個zone時,先從availabilityZone這個Map中查找,查找用的key是region名。

如果找不到,就使用默認值,即我們熟知的defaultZone。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 解決eclipse中maven引用不到已經(jīng)存在maven中jar包的問題

    解決eclipse中maven引用不到已經(jīng)存在maven中jar包的問題

    這篇文章主要介紹了解決eclipse中maven引用不到已經(jīng)存在maven中jar包的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • java利用DFA算法實現(xiàn)敏感詞過濾功能

    java利用DFA算法實現(xiàn)敏感詞過濾功能

    在最近的開發(fā)中遇到了敏感詞過濾,便去網(wǎng)上查閱了很多敏感詞過濾的資料,在這里也和大家分享一下自己的理解。下面這篇文章主要給大家介紹了關(guān)于java利用DFA算法實現(xiàn)敏感詞過濾功能的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-06-06
  • IDEA如何切換JDK版本

    IDEA如何切換JDK版本

    本文主要介紹了IDEA如何切換JDK版本,JDK版本之間的關(guān)系是一個向后兼容的關(guān)系,所以我們需要切換JDK的版本號,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Java中增強for循環(huán)的實現(xiàn)原理和坑詳解

    Java中增強for循環(huán)的實現(xiàn)原理和坑詳解

    增強的for循環(huán)是在傳統(tǒng)的for循環(huán)中增加的強大的迭代功能的循環(huán),是在jdk1.5之后提出來的。下面這篇文章主要給大家介紹了關(guān)于Java中增強for循環(huán)的實現(xiàn)原理和坑的相關(guān)資料,需要的朋友可以參考下
    2018-04-04
  • Mybatis Mybatis-Plus傳入多個參數(shù)的處理方式

    Mybatis Mybatis-Plus傳入多個參數(shù)的處理方式

    這篇文章主要介紹了Mybatis Mybatis-Plus傳入多個參數(shù)的處理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java接口統(tǒng)一樣式返回模板的實現(xiàn)

    Java接口統(tǒng)一樣式返回模板的實現(xiàn)

    這篇文章主要介紹了Java接口統(tǒng)一樣式返回模板的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12
  • Spring中Bean的加載與SpringBoot的初始化流程詳解

    Spring中Bean的加載與SpringBoot的初始化流程詳解

    這篇文章主要介紹了Spring中Bean的加載與SpringBoot的初始化流程詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Spring中bean標簽的用法詳解

    Spring中bean標簽的用法詳解

    Bean標簽一般用于配置對象交由Spring?來創(chuàng)建,這篇文章主要來和大家詳細聊聊Spring中bean標簽的用法,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-06-06
  • XML操作類庫XStream使用詳解

    XML操作類庫XStream使用詳解

    這篇文章主要給大家介紹了關(guān)于XML操作類庫XStream使用的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • SpringBoot實現(xiàn)redis緩存菜單列表

    SpringBoot實現(xiàn)redis緩存菜單列表

    本文主要介紹了SpringBoot實現(xiàn)redis緩存菜單列表,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評論