zoukankan      html  css  js  c++  java
  • SpringCloud Ribbon 自定义负载均衡算法

    程序结构:

    pom.xml 依赖文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.9.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.zyu</groupId>
        <artifactId>consumer_service</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>consumer_service</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <!--SpringCloud所有依赖管理的坐标-->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Greenwich.SR3</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>

    方式一

    在springboot主程序扫描的包外定义配置类,然后为springboot主程序添加 @RibbonClient 注解引入配置类

    Springboot 主程序:

    package com.zyu;
    
    import com.ribbonconfig.MySelfRule;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.netflix.ribbon.RibbonClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    
    @SpringBootApplication
    //该注解表明应用既作为eureka实例又为eureka client 可以发现注册的服务
    @EnableDiscoveryClient
    //在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效
    @RibbonClient(value = "user-service", configuration = {MySelfRule.class})
    public class ConsumerServiceApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ConsumerServiceApplication.class, args);
        }
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate(){ return new RestTemplate(); }
    }

    Rule配置文件类,配置类不应该在SpringBoot的包路径下通过@RibbonClient 注解加载:

    package com.ribbonconfig;
    
    import com.netflix.loadbalancer.IRule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    
    @Configuration
    public class MySelfRule {
        @Bean
        public IRule getIRule() {
            /**
             * 修改Ribbon 负载均衡策略
             */
            //return new RandomRule();   //默认轮询,自定义为随机
    
            /**
             * 自定义 Ribbon 负载均衡策略
             */
            return new MyRule();
        }
    }

    自定义LoadBalance:

    package com.ribbonconfig;
    
    import com.netflix.client.config.IClientConfig;
    import com.netflix.loadbalancer.*;
    
    import java.util.List;
    import java.util.Random;
    
    
    public class MyRule extends AbstractLoadBalancerRule  {
    
        /**
         * 服务选择算法,随机调用
         * @param lb
         * @param o
         * @return
         */
        public Server choose(ILoadBalancer lb, Object o) {
            // 获取服务器列表
            List<Server> servers = lb.getAllServers();
            // 生产随机数
            Random r = new Random();
            int rand = r.nextInt(10);
            System.out.println("随机数: " + rand);
            if(rand > 7){
                return getServerByPort(servers, 9091);
            } else if (rand > 3) {
                return getServerByPort(servers, 9092);
            }else{
                return getServerByPort(servers, 9093);
            }
        }
    
        /**
         * 根据传入的端口号,返回服务对象
         * @param servers
         * @param port
         * @return
         */
        private Server getServerByPort(List<Server> servers, int port){
            for(Server s : servers){
                if(s.getPort() == port){
                    return s;
                }
            }
            return null;
        }
    
    
        @Override
        public void initWithNiwsConfig(IClientConfig iClientConfig) {
    
        }
    
        @Override
        public Server choose(Object o) {
            return choose(getLoadBalancer(), o);
        }
    }

    方式二

    application.yml文件配置方式

    #@RibbonClient(name = "user-service") 与name相同,表示针对该微服务使用自定义负载均衡规则
    user-service:
      ribbon:
        NFLoadBalancerRuleClassName: com.ribbonconfig.MyRule

    配置的优先级

    配置文件的优先级 > java代码的配置方式 > netflix自定义的配置方式

  • 相关阅读:
    According to TLD or attribute directive in tag file, attribute end does not accept any expressions
    Several ports (8080, 8009) required by Tomcat v6.0 Server at localhost are already in use.
    sql注入漏洞
    Servlet—简单的管理系统
    ServletContext与网站计数器
    VS2010+ICE3.5运行官方demo报错----std::bad_alloc
    java 使用相对路径读取文件
    shell编程 if 注意事项
    Ubuntu12.04下eclipse提示框黑色背景色的修改方法
    解决Ubuntu环境变量错误导致无法正常登录
  • 原文地址:https://www.cnblogs.com/zyulike/p/13897768.html
Copyright © 2011-2022 走看看