程序结构:
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自定义的配置方式