栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring cloud/Ribbon

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring cloud/Ribbon

总结

|com.netflix.loadbalancer.RoundRobinRule|默认规则,轮询|
Feign和OpenFeign集成了Ribbon默认具有负载均衡的能力

作用

客户端负载均衡;
使用什么“负载均衡算法”去负载“一个服务的多个实例”
一个服务可以有多个实例,进而负载均衡
负载均衡:将请求合理分配到多个服务上,实现系统的高可用

使用/多种负载均衡算法

IRule接口下多种负载均衡算法

算法类介绍
com.netflix.loadbalancer.RoundRobinRule默认规则,轮询
com.netflix.loadbalancer.ZoneAvoidanceRule区域内的服务性能
com.netflix.loadbalancer.NacosRule同集群中挑选服务实例进行负载均衡
com.netflix.loadbalancer.RandomRule随机
com.netflix.loadbalancer.RetryRule重试,先RoundRobinRule再RetryRule
com.netflix.loadbalancer.WeightedResponseTimeRule响应时间
com.netflix.loadbalancer.BestAvailableRule最可用,先过滤故障服务,再选择并发量最小的
com.netflix.loadbalancer.AvailableFilteringRule先过滤故障服务,再选择并发量较小的
使用/所有服务更换默认负载均衡规则

|com.netflix.loadbalancer.RoundRobinRule|默认规则,轮询|

pom.xml

Feign集成了ribbon

application.yaml

 

main

package com.xcrj.springcloud;

import com.xcrj.rule.MyRuleConfiguration ;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class, args);
    }
}

代码

package com.xcrj.springcloud.rule;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyRuleConfiguration {
    @Bean
    public IRule myRule() {
        return new RandomRule();
    }
}
package com.xcrj.springcloud.configuration;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;


@Configuration
public class AppContextConfiguration {

    @Bean
	// 因为restTemplate没有负载均衡的能力,所以加这个注解让restTemplate具有负载均衡的能力。因为Feign和OpenFeign具有负载均衡的能力,所以不用这个注解
	@LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
使用/部分服务更换默认负载均衡规则

com.netflix.loadbalancer.ZoneAvoidanceRule是默认规则,区域内的服务性能

pom.xml

Feign集成了ribbon

application.yaml

 

main

package com.xcrj.springcloud;

import com.xcrj.rule.MyRuleConfiguration ;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

@SpringBootApplication
@EnableEurekaClient
// 针对PAYMENT-SERVICE服务的实例采取MyRuleConfiguration配置的负载均衡规则
// @RibbonClients多个
@RibbonClient(name = "PAYMENT-SERVICE", configuration = MyRuleConfiguration .class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class, args);
    }
}

代码

// 因为仅仅针对PAYMENT-SERVICE服务实例定制化负载均衡规则,所以MyRuleConfiguration 不能在启动类所在包下,否则所有服务的实例都将使用这个定制的负载均衡规则
package com.xcrj.rule;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyRuleConfiguration {
    @Bean
    public IRule myRule() {
        return new RandomRule();
    }
}
package com.xcrj.springcloud.configuration;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;


@Configuration
public class AppContextConfiguration {

    @Bean
	// 因为restTemplate没有负载均衡的能力,所以加这个注解让restTemplate具有负载均衡的能力。因为Feign和OpenFeign具有负载均衡的能力,所以不用这个注解
	@LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
使用/自定义负载均衡器

pom.xml

Feign集成了ribbon

application.yaml

 

main

package com.xcrj.springcloud;

import com.xcrj.rule.MyRuleConfiguration ;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class, args);
    }
}
package com.xcrj.springcloud.configuration;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;


@Configuration
public class AppContextConfiguration {

    @Bean
	// 因为restTemplate没有负载均衡的能力,所以加这个注解让restTemplate具有负载均衡的能力。因为Feign和OpenFeign具有负载均衡的能力,所以不用这个注解
	@LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

MyLoadBalancer

package com.xcrj.springcloud.lb;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class MyLoadBalancer {
    @Resource
    private DiscoveryClient discoveryClient;

    private AtomicInteger atomicInteger = new AtomicInteger(0);

    
    private final int getAndIncrement() {
        int current;
        int next;
        do {
            current = this.atomicInteger.get();
            next = current >= Integer.MAX_VALUE ? 0 : current + 1;
        } while (!this.atomicInteger.compareAndSet(current, next));
        return next;
    }

    
    public ServiceInstance instances(String appName) {
        // discoveryClient获取服务实例
        List instances = discoveryClient.getInstances(appName);
        // 无可用服务实例 直接返回
        if (CollectionUtils.isEmpty(instances)) {
            return null;
        }
        // 获取将要访问的服务下标
        int index = getAndIncrement() % instances.size();
        // 从list中获取将要访问的服务
        return instances.get(index);
    }
}
package com.xcrj.springcloud.controller;

import com.xcrj.springcloud.lb.MyLoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.net.URI;

@RestController
@Slf4j
public class OrderController {
    private static final String PAYMENT_URL = "http://PAYMENT-SERVICE";
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private MyLoadBalancer myLoadBalancer;

    @GetMapping(value = "/consumer/payment/mylb")
    public String getPaymentLB() {
        // 使用自定义负载均衡器决定调用的服务实例
        ServiceInstance instance = myLoadBalancer.instances("PAYMENT-SERVICE");
        // 获取服务实例的uri
        URI uri = instance.getUri();
        return restTemplate.getForObject(uri + "/payment/lb", String.class);
    }
}
源码

com.netflix.loadbalancer.RoundRobinRule轮询

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.loadbalancer;

import com.netflix.client.config.IClientConfig;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RoundRobinRule extends AbstractLoadBalancerRule {
    private AtomicInteger nextServerCyclicCounter;
    private static final boolean AVAILABLE_ONLY_SERVERS = true;
    private static final boolean ALL_SERVERS = false;
    private static Logger log = LoggerFactory.getLogger(RoundRobinRule.class);

    public RoundRobinRule() {
        this.nextServerCyclicCounter = new AtomicInteger(0);
    }

    public RoundRobinRule(ILoadBalancer lb) {
        this();
        this.setLoadBalancer(lb);
    }

    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            log.warn("no load balancer");
            return null;
        } else {
            Server server = null;
            int count = 0;

            while(true) {
                if (server == null && count++ < 10) {
                    List reachableServers = lb.getReachableServers();
                    // allServers list存储了所有的服务
                    List allServers = lb.getAllServers();
                    int upCount = reachableServers.size();
                    int serverCount = allServers.size();
                    if (upCount != 0 && serverCount != 0) {
                    	// 服务实例的索引,线程安全的+1
                        int nextServerIndex = this.incrementAndGetModulo(serverCount);
                        // allServers list中根据索引获取访问的服务实例
                        server = (Server)allServers.get(nextServerIndex);
                        if (server == null) {
                            Thread.yield();
                        } else {
                            if (server.isAlive() && server.isReadyToServe()) {
                                return server;
                            }

                            server = null;
                        }
                        continue;
                    }

                    log.warn("No up servers available from load balancer: " + lb);
                    return null;
                }

                if (count >= 10) {
                    log.warn("No available alive servers after 10 tries from load balancer: " + lb);
                }

                return server;
            }
        }
    }

    private int incrementAndGetModulo(int modulo) {
        int current;
        int next;
        do {
            current = this.nextServerCyclicCounter.get();
            next = (current + 1) % modulo;
        } while(!this.nextServerCyclicCounter.compareAndSet(current, next));

        return next;
    }

    public Server choose(Object key) {
        return this.choose(this.getLoadBalancer(), key);
    }

    public void initWithNiwsConfig(IClientConfig clientConfig) {
    }
}

暑期编程PK赛 得CSDN机械键盘等精美礼品!
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1017132.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号