前言: Ribbon是客户端 负载均衡的工具。
第一步:Ribbon 初步配置
1.1 在pom.xml文件中添加如下依赖
<!-- Ribbon相关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
1.2 在application.yml文件中
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/ ,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
1.3 在RestTemplate配置类中添加@LoadBalanced
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
/* @Bean
public IRule myRule(){
return new RandomRule();
}*/
}
1.4 主启动类上面添加注解@EnableEurekaClient注解
@SpringBootApplication
@EnableEurekaClient
public class ConsumerDeptApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerDeptApplication.class,args);
}
}
1.5 在服务消费方的controller方法中,修改url为要调用微服务的名称
private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";
@RequestMapping(value = "/consumer/discovery")
public Object discovery(){
return restTemplate.getForObject(rest_url+ "/dept/discovery",Object.class);
}
总结:上面的步骤 是Ribbon和Eureka的整合,Consumer可以直接调用微服务名称而不用再关心地址和端口号
第二部分:负载均衡
一个服务提供方部署成集群模式,意思就是同一个微服务部署在多个服务器上面,服务消费者(客户端)通过Ribbo完成负载均衡并访问要访问的微服务
Ribbon在工作时分成两步
第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。
其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。

第三部分:自定义负载均衡算法
3.1 IRule组件:根据特定算法,从注册中心服务列表中选择一个要访问的服务,默认有七种算法,默认轮询算法。
我现在想用随机算法,在配置类中添加下面代码
@Bean
public IRule myRule(){
return new RandomRule();
}
3.2 自定义负载均衡算法,不用出厂自带的
3.2.1 在主启动类添加@RibbonClient注解,这个注解作用,在启动微服务的时候去加载我们自定义的Ribbon配置类,从而使我们自己定义的算法生效
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "MICROSERVICECLOUD-DEPT",configuration = MySelfRule.class)
public class ConsumerDeptApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerDeptApplication.class,args);
}
}
3.2.2 自定义ribbon配置类(如下所示),不能放在@ComponentScan所扫描的当前包及子包下面,否则我们自定义的这个配置类就会被所有的ribbon客户端所共享,也就达不到特殊化定制化的目的了
@Configuration
public class MySelfRule {
@Bean
public IRule mySelRule(){
return new RandomRule_ZY();
}
}
//我自定义的算法
public class RandomRule_ZY extends AbstractLoadBalancerRule
{
// total = 0 // 当total==5以后,我们指针才能往下走,
// index = 0 // 当前对外提供服务的服务器地址,
// total需要重新置为零,但是已经达到过一个5次,我们的index = 1
// 分析:我们5次,但是微服务只有8001 8002 8003 三台,OK?
//
private int total = 0; // 总共被调用的次数,目前要求每台被调用5次
private int currentIndex = 0; // 当前提供服务的机器号
public Server choose(ILoadBalancer lb, Object key)
{
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers();
List<Server> allList = lb.getAllServers();
int serverCount = allList.size();
if (serverCount == 0) {
/*
* No servers. End regardless of pass, because subsequent passes only get more
* restrictive.
*/
return null;
}
// int index = rand.nextInt(serverCount);// java.util.Random().nextInt(3);
// server = upList.get(index);
// private int total = 0; // 总共被调用的次数,目前要求每台被调用5次
// private int currentIndex = 0; // 当前提供服务的机器号
if(total < 5)
{
server = upList.get(currentIndex);
total++;
}else {
total = 0;
currentIndex++;
if(currentIndex >= upList.size())
{
currentIndex = 0;
}
}
if (server == null) {
/*
* The only time this should happen is if the server list were somehow trimmed.
* This is a transient condition. Retry after yielding.
*/
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
// Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
}
return server;
}
@Override
public Server choose(Object key)
{
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig)
{
// TODO Auto-generated method stub
}
}