一、Ribbon简介
Ribbon是Netflix公司开源的使用在客户端的一个负载均衡的项目。是SpringCloud Finchley.M8版本结合使用Consul时使用默认负载均衡客户端。
负载均衡策略有以下,当然我们一可以更具实际需求,来自定义负载均衡策略。
SpringCloud中默认使用ZoneAvoidanceRule策略
类(策略) | 说明 | 实现简介 |
---|---|---|
ZoneAvoidanceRule | 复合判断server所在区域的性能和server的可用性选择server | 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server |
RandomRule | 随机选择一个server | 在index上随机,选择index对应位置的server |
RoundRobinRule | roundRobin方式轮询选择server | 轮询index,选择index对应位置的server |
RetryRule | 对选定的负载均衡策略机上重试机制 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
WeightedResponseTimeRule | 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server |
AvailabilityFilteringRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
BestAvailableRule | 选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
表格中的内容参考博客:
https://blog.youkuaiyun.com/rickiyeat/article/details/64918756
二、RestTemplate的原理
原理简介:使用RestTemplate作为负载均衡模版,必须要使用@LoadBalance注解。
通过该注解,将RestTemplate被标记为使用RibbonLoadBalancerClient的作为负载均衡模版。使用restTmeplate发起http请求,请求被Spring拦截器拦截,然后处理拦截的请求,首先ConsulClient通过serviceId获取所有ServiceInstance,在使用RibbonLoadBalancerClient选择一个满足负载策略的ServiceInstance作为请求的service,最后通过RestTemplate请求service。
三、创建服务consulservice3
1、引入依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--用于监控与管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--config server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul</artifactId>
</dependency>
<!--服务发现依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--用于consul配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
</dependencies>
2、简单的配置
spring.application.name=consulservice3
spring.cloud.consul.discovery.instance-id=${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
3、创建程序启动入口
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class ConsulService3App {
@Value("${spring.application.name}")
private String serviceName;
@Value("${server.port}")
private int servicePort;
@RequestMapping("/say")
public String say(){
return "hello world! I'm '" + serviceName + ":" + servicePort + "'";
}
public static void main(String[] args){
SpringApplication.run(ConsulService3App.class, args);
}
}
4、分别以端口8001和8002启动consulservice3
可以看到服务已经注册到ConsulServer了,一个伪集群
三、创建客户端consulclient3
1、引入依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--用于监控与管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--config server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul</artifactId>
</dependency>
<!--服务发现依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--用于consul配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
</dependencies>
2、简单配置
spring.application.name=consulclient3
3、创建启动引用程序入口
说明:由于简单教程,所以接口和配置都放在一起了,实际应用中决不允许这么做
@SpringBootApplication
@EnableDiscoveryClient
@RestController
@Configuration
public class ConsulClient3App {
@Bean
@LoadBalanced//此注解必须存在
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Autowired
private RestTemplate restTemplate;
//serviceId获取service
private static final String SERVICE_ID = "consulservice3";
@RequestMapping("/say")
public String sayService() {
//使用restTemplate作为模版,serviceId会被ribbonClient替换为服务的地址
return restTemplate.getForObject("http://"+SERVICE_ID+"/say",String.class);
}
public static void main(String[] args){
SpringApplication.run(ConsulClient3App.class, args);
}
}
4、以端口9999启动consulclient3,调用接口,证明负载均衡成功