Ribbon使Netflix提供的开源的项目,主要功能使提供软件负载均衡算法。
那怎么理解他呢?
在Spring Cloud Eureka中,我们了解到服务是如何注册,注册到哪里,服务消费者如何获取服务提供者的服务信息。但是Eureka只是维护了服务消费者,服务注册中心,服务提供者三者之间的关系。真正的服务消费者调用服务提供者的数据信息是通过Spring Cloud Ribbon实现的。
- 什么是Ribbon?
在Eureka中,我们知道服务消费者是从服务注册中心获取了服务列表并维护在本地,这种客户端发现模式的方式就是服务消费者选择合适的节点进行访问服务提供者的提供的数据信息,这个节点选择的过程就是Ribbon实现。所以Spring Cloud Ribbon也叫客户端负载均衡器,他是基于HTTP和TCP的客户端负载均衡器,可以通过配置ribbonServerList来设置服务端列表去轮询访问达到均衡负载的作用。
Ribbon客户端提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面的机器,Ribbon会自动的帮助你基于某种规则(简单轮询,随机链接等)去连接这些机器。
- LB方案分类
主流方案分为两类:一种是集中式LB,在服务的消费方和提供方之间使用独立的LB设施(可以是硬件如F5,可以是软件如nginx),由该设施负责把访问请求通过某种策略转发至服务的提供方;另一种中是进程内LB,将LB逻辑集成到消费方,消费方从服务注册中心获知哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。Ribbon就是后者,他只是一个类库,集成与消费方进程,消费方通过它获取到服务提供方的地址。
- Ribbon的核心组件
ServerList:用于获取地址列表,它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心定期查询地址列表)
ServerListFilter:仅当使用动态的ServerList时,用于在原始的服务列表中使用一定策略过滤掉一部分地址
IRule:选择一个最终服务地址作为LB结果,选择策略有轮询,根据相应时间加权,断路器等
工作流程:ServerList获取所有服务列表,ServerListFilter过滤一部分地址,IRule选择一台服务器作为最终结果
- Ribbon提供的主要负载均衡策略介绍
- 简单轮询负载均衡(RoundRobin):以轮询方式一次将请求调度到不同的服务器,即每次调度执行i=(i+1) mod n,并选择出第i台服务器
- 随机负载均衡(Random):随机选择状态为UP的Server
- 加权响应时间负载均衡(WeightedResponseTime):根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低
- 区域感知轮询负载均衡(ZoneAvoidanceRule):复合判断server所在区域的性能和server的可用性选择server
- 实验(Eureka+rest+Ribbon)
准备3个eureka-provider进行服务注册,每个eureka-provider的启动类中做修改home()以作区别不同端口的Controller响应
import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @EnableEurekaClient @RestController public class EurekaProviderApplication { @Value("${server.port}") String port; @RequestMapping("/") public String home() { return "Hello world ,port:" + port; } public static void main(String[] args) { SpringApplication.run(EurekaProviderApplication.class, args); } }
配置中每个provider的端口都修改一下
eureka: client: serviceUrl: defaultZone: http://localhost:8080/eureka/ spring: application: name: eureka-provider server: port: 8083
Ribbon Consumer:服务消费者
- 添加依赖spring-cloud-ribbon-consumer,客户端的负载均衡
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency>
- 开启服务负载均衡
通过@EnableDiscoveryClient注解向服务中心进行注册,并向程序的IOC注入一个Bean:restTemplate,并通过@LoadBalanced注解表明这个restTemplate开启负载均衡的功能。
@EnableDiscoveryClient @SpringBootApplication public class RibbonConsumerApplication { @LoadBalanced @Bean RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(RibbonConsumerApplication.class, args); } }
- 消费提供方法
新建ConsumerController类,调用提供者的hello方法,@Autowired 可以理解为一个初始化的注解,这里是构造restTemplate并初始化。@RestController是构造性注解,告诉spring以字符串的形式渲染结果,@GetMapping将HTTP 的GET映射到特定的处理方法上 。
@RestController public class ConsumerController { @Autowired private RestTemplate restTemplate; @GetMapping(value = "/hello") public String hello() { return restTemplate.getForEntity("http://eureka-provider/", String.class).getBody(); } }
- 添加配置
指定服务的注册中心,配置自己的服务端口,服务名称
eureka: client: serviceUrl: defaultZone: http://localhost:8080/eureka/ spring: application: name: ribbon-consumer server: port: 9000
- 测试服务
依次启动服务
spring-cloud-eureka-service 提供服务注册和发现,他会建立一个服务注册中心,供其它应用进行对话
spring-cloud-eureka-provider-1 服务提供者,向服务注册中心进行注册,续约,下线操作
spring-cloud-eureka-provider-2 服务提供者
spring-cloud-eureka-provider-3 服务提供者
spring-cloud-eureka-consumer 服务消费者,从服务注册中心获取服务列表,选择节点和服务器,消费服务
启动之后可以看到服务已被注册,有三个端口
- 负载均衡
浏览器访问http://localhost:9000/hello,F5刷新可以看到实现了Ribbon负载均衡
参考:https://www.w3cschool.cn/spring_cloud/spring_cloud-f7262ixh.html
附上原作者源码地址:https://github.com/souyunku/spring-cloud-examples/tree/master/spring-cloud-ribbon