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次的目标。
920

被折叠的 条评论
为什么被折叠?



