1.什么是Ribbon
Ribbon是客户端的一个负载均衡的工具;就是将请求尽量平均分配到各个系统上,分摊系统处理的压力,保证服务稳定的一种方式,其均衡策略 有轮询(默认),随机,过滤故障服务,自定义 等多种算法;
2,Ribbon的基本配置的学习(基于RestTemplate的系统通讯和Bribbon默认均衡策略 轮询)

 一,之前好的搭建集群服务 springCloud服务搭建 集群服务搭建
 
 二,在consumer 8001的服务引入Ribbon的依赖(完整pom)
<?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.0.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.zt.frank</groupId>
	<artifactId>zt-frank-consumer-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>zt-frank-consumer-service</name>
	<description>zt-frank-consumer-service</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<!-- actuator  健康检查 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<!-- 负载均衡ribbon -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
			<version>2.0.0.RELEASE</version>
		</dependency>
		<!--eureka -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
			<version>2.0.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
			<version>2.0.2.RELEASE</version>
		</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>
 
三,application.yml文件配置
app:
  id: zt-frank-consumer-service-8001
  name: zt-frank-consumer-service-8001
server:
  port: 8001
spring:
  application:
    name: zt-frank-consumer-service-8001
#eureka注册中心的地址
eureka:
  client:
    register-with-eureka: false #是否向服务注册中心注册自己(这里不要向注册中兴注册)
    service-url:
      #defaultZone: http://localhost:6001/eureka/
      defaultZone: http://eureka6001.com:6001/eureka/,http://eureka6002.com:6002/eureka/,http://eureka6003.com:6003/eureka/  #集群配置,将此服务同时注册到6001,6002,6003的服务中
 
四,编写RestTemplate的bean(注意:加上@LoadBalanced使用Ribbon的负载均衡)
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 RestTemplateConfig {
    @Bean
    @LoadBalanced  //访问7001,7002服务带上负载均衡的机制
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
 
五,8001端请求7001 或者7002代码的编写(这里请求的URL是7001,7002的yml文件spring.application.name的值,而且两个服务的值需要一样,注意转大写如下图)
 
 下面是:8001服务用resetTemplate方式请求7001,7002服务的controller代码
@RestController
@RequestMapping("/con")
public class ConsumerTestController {
    private static Logger logger = Logger.getLogger(ConsumerTestController.class);
   //这个就是需要负载均衡的服务7001,7002 的http://+spring.application.name的值 (注意转大写)
    private final static String TEMPLATE_RIBBON_TEST ="http://ZT-FRANK-CONFIG-SERVICE";
    @Autowired
    private RestTemplate restTemplate;
    /**
     *  restTemplate  Ribbon负载均衡测试
     * @param str
     * @return
     */
	    @PostMapping("/ribbonTest")
	    public String restTemplateRibbonTest(@RequestParam String str){
	        logger.info("start-restTemplateRibbonTest:"+str);
	        String res = restTemplate.postForObject(TEMPLATE_RIBBON_TEST+"/config/health", str, String.class);
	        logger.info("end-restTemplateRibbonTest");
	        return res;
	    }
    }
 
六,测试,分别启动上述六个服务,并用postmen 调用8001服务的测试接口,并由Ribbon来决定调用7001,还是7002端口下的接口
7001的接口:
@Controller
@RequestMapping("/config")
public class Test {
    private static Logger logger = Logger.getLogger(Test.class);
    @PostMapping("/health")
    @ResponseBody
    public String test(){
        logger.info("+++++++++++++++++++++++++++++++请求成功TEST_7001+++++++++++++++++++++++++++++++++++");
        return "UP7001";
    }
}
 
7002的接口:
@Controller
@RequestMapping("/config")
public class Test {
    private static Logger logger = Logger.getLogger(Test.class);
    @PostMapping("/health")
    @ResponseBody
    public String test(){
        logger.info("+++++++++++++++++++++++++++++++请求成功TEST_7002+++++++++++++++++++++++++++++++++++");
        return "UP7002";
    }
}
 
测试:
 
 
 测试显示7001和7002的接口通过8001服务来调用都是可以请求通的,而且8001调用7001,7002服务的顺序在没有额外配置的情况下是轮询的;
3.Ribbon负载均衡策略以及核心组件
第一种:
RiboonRobinRule
按照顺序执行
第二种:
RandomRule
随机
第三种:
AvailablilityFilteringRule
过滤掉多次访问故障发生熔断处于跳闸的服务,以及访问量超过阈值的服务,然后将剩下的服务列表进行轮询访问
第四种:
WeightedResponseTimeRule
根据服务平均响应时间计算,服务响应越快权重越大(但是服务刚启动服务信息统计不全,会使用轮询的策列,当服务信息足够了,就会使用这个策列)
第五种:
RetryRule 会按照默认轮询的策略进行服务访问,如果服务获取失败,会在指定的时间,进行重试,获取可用服务;
第六种:
BestAvailableRule 会过滤掉处于熔断跳闸状态的服务,然后选择一个并发量最小的一个服务
第七种:
ZoneAvoidanceRule 复合判断server所在区域的性能,来选择服务
部分配置
@Configuration
public class ConfigBean {
    /**
     * RestTemplate 的bean
     * @return
     */
    @Bean
    @LoadBalanced  //访问7001,7002服务带上负载均衡的机制
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
    /**
     * Riboon负载均衡随机的策列
     * @return
     */
    @Bean
    public IRule myRandomRule(){
        return new RandomRule();
    }
    /**
     * Riboon负载均衡会过滤掉处于熔断跳闸状态的服务,然后选择一个并发量最小的一个服务
     * @return
     */
   //@Bean
   // public IRule myBestAvailableRule(){
   //     return new BestAvailableRule();
   // }
}
 
4,自定义负载均衡(实现目标:每台服务按顺序轮询执行3次)
第一步:
 去除之前配置Ribbon提供的负载均衡配置bean
 第二步:
 在主启动类上添加@RibbonClient 注解,如下图:
@SpringBootApplication
@EnableEurekaClient
/**
 * 自定义负载均衡策列:
 * 		name:需要被负载均衡的7001,7002的服务yml文件下spring.application.name的值;
 * 		configuration:自定义策略的类;
 * 注意:
 * 		自定义Rule 配置类不能在@ComponentScan(注意:@SpringBootApplication就包含这个注解了)注解所扫描的当前包以及子包下面,
 * 		不然自定义的Ribbon配置规则就会被所有Ribbon客户端所共享,达不到特殊指定的规则
 */
@RibbonClient(name="ZT-FRANK-CONFIG-SERVICE" ,configuration = MyRule.class)
public class ZtFrankConsumerServiceApplication8001 {
	
	private static Logger logger = Logger.getLogger(ZtFrankConsumerServiceApplication8001.class);
	public static void main(String[] args) {	
		SpringApplication.run(ZtFrankConsumerServiceApplication8001.class, args);
		logger.info("*********ZtFrankConsumerServiceApplication80启动成功*********");
	}
}
 
第三步;新建包和MyRule , MyCustomRule类
MyRule :
 
 MyCustomRule:
package com.zt.frank.zt.frank.rule;
import java.util.List;
import java.util.Random;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
/**
 * 自定义规则:
 * 实现目标:每台服务按顺序轮询执行3次
 * @author tao.zhang
 *
 */
public class MyCustomRule extends AbstractLoadBalancerRule{
	
	//轮询执行3次
	int total = 0;
	//当前机器号 7001 7002
	int curenIndex = 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) {
                return null;
            }
            /**
             * 自定义规则
             */
            if(total<3){
            	server = upList.get(curenIndex);
            	total++;
            }else{
            	total = 0;
            	curenIndex++;
            	if(curenIndex>=upList.size()){
            		curenIndex = 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 arg0) {
		// TODO Auto-generated method stub
		
	}
	
	
}
 
第四步:
 配置完成,测试:。。。。。。。略;
                  
                  
                  
                  
                            
本文详细介绍了Spring Cloud Ribbon作为客户端负载均衡器的作用,讲解了Ribbon的基本配置,包括基于RestTemplate的系统通讯和默认轮询策略。接着探讨了Ribbon的各种内置负载均衡策略,如轮询、随机、过滤故障服务等。最后,文章演示了如何自定义负载均衡策略,以实现每台服务按顺序轮询执行3次的目标。
          
      
          
                
                
                
                
              
                
                
                
                
                
              
                
                
              
            
                  
					4171
					
被折叠的  条评论
		 为什么被折叠?
		 
		 
		
    
  
    
  
            


            