最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解如何獨(dú)立使用ribbon實(shí)現(xiàn)業(yè)務(wù)客戶端負(fù)載均衡

 更新時(shí)間:2023年06月27日 09:05:40   作者:linyb極客之路  
這篇文章主要為大家介紹了詳解如何獨(dú)立使用ribbon實(shí)現(xiàn)業(yè)務(wù)客戶端負(fù)載均衡,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

ribbon是Netflix開源的客戶端負(fù)載均衡工具,ribbon實(shí)現(xiàn)一系列的負(fù)載均衡算法,通過這些負(fù)載均衡算法去查找相應(yīng)的服務(wù)。ribbon被大家所熟知,可能是來源于spring cloud,今天就來聊聊如何單獨(dú)使用ribbon來實(shí)現(xiàn)業(yè)務(wù)客戶端負(fù)載均衡

實(shí)現(xiàn)關(guān)鍵

springcloud ribbon獲取服務(wù)列表是通過注冊中心,而單獨(dú)使用ribbon,因?yàn)闆]有注冊中心加持,就得單獨(dú)配置服務(wù)列表

示例

1、在業(yè)務(wù)項(xiàng)目中pom引入ribbon GAV

<dependency>
    <groupId>com.netflix.ribbon</groupId>
    <artifactId>ribbon</artifactId>
    <version>2.2.2</version>
</dependency>

不過引進(jìn)去,發(fā)現(xiàn)如果引入netfiix的相關(guān)的類,比如IPing,會(huì)發(fā)現(xiàn)引不進(jìn)去,原因是因?yàn)檫@個(gè)GAV里面依賴的jar的生命周期是runtime,即在運(yùn)行期或者測試階段才生效,在編譯階段是不生效的。如果我們?yōu)榱朔奖悖梢灾苯訂为?dú)引入
spring cloud ribbon

<dependency>
           <groupId>org.springframework.cloud</groupId>-->
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>-->
           <version>2.2.2.RELEASE</version>
    </dependency>

本文我們是想脫離springcloud,直接使用ribbon,因此我們可以直接 引入如下GAV

<!--  核心的通用性代碼-->
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-core</artifactId>
            <version>${ribbon.version}</version>
        </dependency>
        <!-- 基于apache httpClient封裝的rest客戶端,集成了負(fù)載均衡模塊,內(nèi)嵌http心跳檢測-->
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-httpclient</artifactId>
            <version>${ribbon.version}</version>
        </dependency>
        <!-- 負(fù)載均衡模塊-->
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-loadbalancer</artifactId>
            <version>${ribbon.version}</version>
        </dependency>
        <!-- IClientConfig配置相關(guān)-->
        <dependency>
            <groupId>com.netflix.archaius</groupId>
            <artifactId>archaius-core</artifactId>
            <version>0.7.6</version>
        </dependency>
        <!-- IClientConfig配置相關(guān)-->
        <dependency>
            <groupId>commons-configuration</groupId>
            <artifactId>commons-configuration</artifactId>
            <version>1.8</version>
        </dependency>

2、創(chuàng)建ribbon元數(shù)據(jù)配置類

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class RuleDefinition {

    /**
     * 服務(wù)名稱
     */
    private String serviceName;

    /**
     * 命名空間,當(dāng)服務(wù)名相同時(shí),可以通過namesapce來進(jìn)行隔離區(qū)分
     * 未指定默認(rèn)為public
     */
    @Builder.Default
    private String namespace = DEFAULT_NAMESPACE;

    /**
     * 自定義負(fù)載均衡策略,未指定默認(rèn)為輪詢
     */
    @Builder.Default
    private String loadBalancerRuleClassName = RoundRobin;

    /**
     * 自定義心跳檢測,未指定不檢測
     */
    @Builder.Default
    private String loadBalancerPingClassName = DummyPing;

    /**
     * 服務(wù)列表,多個(gè)用英文逗號隔開
     */
    private String listOfServers;


    /**
     * 該優(yōu)先級大于loadBalancerPingClassName
     */
    private IPing ping;

    /**
     * 心跳間隔,不配置默認(rèn)是10秒,單位秒
     */
    private int pingIntervalSeconds;


    /**
     * 該優(yōu)先級大于loadBalancerRuleClassName
     */
    private IRule rule;



}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix = PREFIX)
public class LoadBalanceProperty {
    public static final String PREFIX = "lybgeek.loadbalance";
    private List<RuleDefinition> rules;
    public Map<String,RuleDefinition> getRuleMap(){
        if(CollectionUtils.isEmpty(rules)){
            return Collections.emptyMap();
        }
        Map<String,RuleDefinition> ruleDefinitionMap = new LinkedHashMap<>();
        for (RuleDefinition rule : rules) {
            String key = rule.getServiceName() + RULE_JOIN + rule.getNamespace();
            ruleDefinitionMap.put(key,rule);
        }
        return Collections.unmodifiableMap(ruleDefinitionMap);
    }
}

3、創(chuàng)建負(fù)載均衡工廠【核心實(shí)現(xiàn)】

private final LoadBalanceProperty loadBalanceProperty;
    // key:serviceName + nameSpace
    private static final Map<String, ILoadBalancer> loadBalancerMap = new ConcurrentHashMap<>();
    public ILoadBalancer getLoadBalancer(String serviceName,String namespace){
        String key = serviceName + RULE_JOIN + namespace;
        if(loadBalancerMap.containsKey(key)){
            return loadBalancerMap.get(key);
        }
        RuleDefinition ruleDefinition = getAvailableRuleDefinition(serviceName,namespace);
        IPing ping = ruleDefinition.getPing();
        if(ObjectUtils.isEmpty(ping)){
            // 無法通過ConfigurationManager.getConfigInstance().setProperty(serviceName + DOT + namespace + DOT + PING_CLASS_NAME, ruleDefinition.getLoadBalancerPingClassName());
            //LoadBalancerBuilder沒提供通過ClientConfig配置ping方法,只能通過withPing修改
            ping = getPing(serviceName,namespace);
        }
        IRule rule = ruleDefinition.getRule();
        if(ObjectUtils.isEmpty(rule)){
            // 也可以通過ConfigurationManager.getConfigInstance().setProperty(serviceName + DOT + namespace + DOT + RULE_CLASS_NAME, ruleDefinition.getLoadBalancerRuleClassName());
            rule = getRule(serviceName,namespace);
        }
        // 配置服務(wù)列表
        ConfigurationManager.getConfigInstance().setProperty(serviceName + DOT + namespace + DOT + SERVER_LIST, ruleDefinition.getListOfServers());
        // 因?yàn)榉?wù)列表目前是配置寫死,因此關(guān)閉列表更新,否則當(dāng)觸發(fā)定時(shí)更新時(shí),會(huì)重新將服務(wù)列表狀態(tài)恢復(fù)原樣,這樣會(huì)導(dǎo)致server的isLive狀態(tài)不準(zhǔn)確
        // 不設(shè)置默認(rèn)采用com.netflix.loadbalancer.PollingServerListUpdater
        ConfigurationManager.getConfigInstance().setProperty(serviceName + DOT + namespace + DOT + SERVERLIST_UPDATER_CLASS_NAME, EmptyServerListUpdater.class.getName());
        IClientConfig config = new DefaultClientConfigImpl(namespace);
        config.loadProperties(serviceName);
        ZoneAwareLoadBalancer<Server> loadBalancer = getLoadBalancer(config, ping, rule);
        loadBalancerMap.put(key,loadBalancer);
        if(ruleDefinition.getPingIntervalSeconds() > 0){
            // 默認(rèn)每隔10秒進(jìn)行心跳檢測
            loadBalancer.setPingInterval(ruleDefinition.getPingIntervalSeconds());
        }
        return loadBalancer;
    }
    public ZoneAwareLoadBalancer<Server> getLoadBalancer(IClientConfig config, IPing ping, IRule rule){
        ZoneAwareLoadBalancer<Server> serverZoneAwareLoadBalancer = LoadBalancerBuilder.newBuilder()
                .withClientConfig(config)
                .withPing(ping)
                .withRule(rule)
                .buildDynamicServerListLoadBalancerWithUpdater();
        return serverZoneAwareLoadBalancer;
    }
    /**
     * 獲取 iping
     * @param serviceName
     * @param namespace
     * @return
     */
    @SneakyThrows
    public IPing getPing(String serviceName, String namespace){
        RuleDefinition ruleDefinition = getAvailableRuleDefinition(serviceName,namespace);
        Class<?> loadBalancerPingClass = ClassUtils.forName(ruleDefinition.getLoadBalancerPingClassName(), Thread.currentThread().getContextClassLoader());
        Assert.isTrue(IPing.class.isAssignableFrom(loadBalancerPingClass),String.format("loadBalancerPingClassName : [%s] is not Iping class type",ruleDefinition.getLoadBalancerPingClassName()));
        return (IPing) BeanUtils.instantiateClass(loadBalancerPingClass);
    }
    /**
     * 獲取 loadbalanceRule
     * @param serviceName
     * @param namespace
     * @return
     */
    @SneakyThrows
    public IRule getRule(String serviceName, String namespace){
        RuleDefinition ruleDefinition = getAvailableRuleDefinition(serviceName,namespace);
        Class<?> loadBalancerRuleClass = ClassUtils.forName(ruleDefinition.getLoadBalancerRuleClassName(), Thread.currentThread().getContextClassLoader());
        Assert.isTrue(IRule.class.isAssignableFrom(loadBalancerRuleClass),String.format("loadBalancerRuleClassName : [%s] is not Irule class type",ruleDefinition.getLoadBalancerRuleClassName()));
        return (IRule) BeanUtils.instantiateClass(loadBalancerRuleClass);
    }
    private RuleDefinition getAvailableRuleDefinition(String serviceName,String namespace){
        Map<String, RuleDefinition> ruleMap = loadBalanceProperty.getRuleMap();
        Assert.notEmpty(ruleMap,"ruleDefinition is empty");
        String key = serviceName + RULE_JOIN + namespace;
        RuleDefinition ruleDefinition = ruleMap.get(key);
        Assert.notNull(ruleDefinition,String.format("NOT FOUND AvailableRuleDefinition with serviceName : [{}] in namespace:[{}]",serviceName,namespace));
        return ruleDefinition;
    }

核心實(shí)現(xiàn)類:com.netflix.loadbalancer.LoadBalancerBuilder 利用該類創(chuàng)建相應(yīng)的負(fù)載均衡

4、測試

a、 新起2個(gè)服務(wù)提供者占用6666端口、和6667端口

b、 在消費(fèi)端的application.yml配置如下內(nèi)容

lybgeek:
  loadbalance:
    rules:
      - serviceName: provider
        namespace: test
        loadBalancerPingClassName: com.github.lybgeek.loadbalance.ping.TelnetPing
        pingIntervalSeconds: 3
     #   loadBalancerRuleClassName: com.github.lybgeek.loadbalance.rule.CustomRoundRobinRule
        listOfServers: 127.0.0.1:6666,127.0.0.1:6667

c、 測試類

@Override
    public void run(ApplicationArguments args) throws Exception {

        ServerChooser serverChooser = ServerChooser.builder()
                .loadBalancer(loadbalanceFactory.getLoadBalancer("provider", "test"))
                .build();

        while(true){
            Server reachableServer = serverChooser.getServer("provider");
            if(reachableServer != null){
                System.out.println(reachableServer.getHostPort());
            }
            TimeUnit.SECONDS.sleep(1);

        }


    }

當(dāng)服務(wù)提供者都正常提供服務(wù)時(shí),觀察控制臺

可以觀察以輪詢的方式調(diào)用服務(wù)提供者,當(dāng)斷掉其中一臺服務(wù)提供者時(shí),再觀察控制臺

會(huì)發(fā)現(xiàn)只調(diào)用服務(wù)正常的那臺

總結(jié)

獨(dú)立使用ribbon其實(shí)不會(huì)很難,主要對LoadBalancerBuilder這個(gè)API熟悉就可以定制自己想要的負(fù)載均衡器。springcloud從2020版本就將ribbon廢棄了,轉(zhuǎn)而要扶持其親兒子loadbalancer,就目前功能而言,loadbalancer還沒ribbon豐富,通過本文紀(jì)念一下被springcloud遺棄的ribbon

demo鏈接

以上就是詳解如何獨(dú)立使用ribbon實(shí)現(xiàn)業(yè)務(wù)客戶端負(fù)載均衡的詳細(xì)內(nèi)容,更多關(guān)于ribbon客戶端負(fù)載均衡的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

松桃| 新昌县| 呼图壁县| 临夏市| 景德镇市| 泉州市| 阿勒泰市| 乡宁县| 阳春市| 永吉县| 昌宁县| 洪江市| 白水县| 金溪县| 永城市| 越西县| 崇明县| 五大连池市| 大城县| 锡林郭勒盟| 商南县| 澎湖县| 南乐县| 左权县| 兴国县| 浮山县| 鄄城县| 法库县| 栖霞市| 安福县| 宣城市| 丹东市| 通城县| 江城| 龙游县| 神农架林区| 和静县| 碌曲县| 甘洛县| 平阳县| 沛县|