Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。
1. 修改 microservicecloud-consumer-dept-80 工程
2. 修改pom.xml文件
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>microservicecloud-consumer-dept-80</artifactId> <description>部门微服务消费者</description> <dependencies> <dependency><!-- 自己定义的api --> <groupId>com.atguigu.springcloud</groupId> <artifactId>microservicecloud-api</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 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> </project>3. 修改application.yml 追加eureka的服务注册地址
server: port: 80 #下面是新加的配置 eureka: client: register-with-eureka: false service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
4. 对ConfigBean进行新注解@LoadBalanced 获得Rest时加入Ribbon的配置
package com.atguigu.springcloud.cfgbeans; 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 ConfigBean { @Bean @LoadBalanced //新加的注解 public RestTemplate getRestTemplate() { return new RestTemplate(); } }5. 主启动类DeptConsumer80_App添加@EnableEurekaClient
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient //新加的注解 public class DeptConsumer80_App { public static void main(String[] args) { SpringApplication.run(DeptConsumer80_App.class, args); } }6. 修改DeptController_Consumer客户端访问类
package com.atguigu.springcloud.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.atguigu.springcloud.entities.Dept; @RestController public class DeptController_Consumer { /*private static final String REST_URL_PREFIX = "http://localhost:8001"; 把该部分注释掉,使用微服务的名称!注意不是微服务的实例的名称! Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号 */ private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT"; @Autowired private RestTemplate restTemplate; @RequestMapping(value="/consumer/dept/add") public boolean add(Dept dept) { return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add", dept, Boolean.class); } @RequestMapping(value="/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id) { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id, Dept.class); } @SuppressWarnings("unchecked") @RequestMapping(value="/consumer/dept/list") public List<Dept> list() { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list", List.class); } //测试@EnableDiscoveryClient,消费端可以调用服务发现 @RequestMapping(value="/consumer/dept/discovery") public Object discovery() { return restTemplate.getForObject(REST_URL_PREFIX+"/dept/discovery", Object.class); } }7. 启动服务
启动服务器集群:3个eureka
启动provider: microservicecloud-provider-dept-8001
启动consumer:microservicecloud-consumer-dept-80
8. 测试
http://localhost/consumer/dept/get/1
http://localhost/consumer/dept/list
http://localhost/consumer/dept/add?dname=大数据部
1.架构说明
Ribbon在工作时分成两步: 第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server. 第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。 其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。
2. 具体步骤
(1)参考 microservicecloud-provider-dept-8001,新建两份,分别命名为8002,8003
(2)新建8002/8003数据库,各自微服务分别连各自的数据库
#8002 DROP DATABASE IF EXISTS cloudDB02; CREATE DATABASE cloudDB02 CHARACTER SET UTF8; USE cloudDB02; CREATE TABLE dept ( deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, dname VARCHAR(60), db_source VARCHAR(60) ); INSERT INTO dept(dname,db_source) VALUES('开发部',DATABASE()); INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE()); INSERT INTO dept(dname,db_source) VALUES('财务部',DATABASE()); INSERT INTO dept(dname,db_source) VALUES('市场部',DATABASE()); INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE()); #8003 DROP DATABASE IF EXISTS cloudDB03; CREATE DATABASE cloudDB03 CHARACTER SET UTF8; USE cloudDB03; CREATE TABLE dept ( deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, dname VARCHAR(60), db_source VARCHAR(60) ); INSERT INTO dept(dname,db_source) VALUES('开发部',DATABASE()); INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE()); INSERT INTO dept(dname,db_source) VALUES('财务部',DATABASE()); INSERT INTO dept(dname,db_source) VALUES('市场部',DATABASE()); INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE());(3)修改8002/8003各自YML
8002yml文件
server: port: 8002 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB02 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept8002 #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$8003yml文件
server: port: 8003 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml #mybatis所在路径 type-aliases-package: com.atguigu.springcloud.entities #entity别名类 mapper-locations: - classpath:mybatis/mapper/**/*.xml #mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/cloudDB03 username: root password: 123456 dbcp2: min-idle: 5 initial-size: 5 max-total: 5 max-wait-millis: 200 eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ instance: instance-id: microservicecloud-dept8003 #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$【提示】修改的部分:端口、数据库名!同时注意对外暴露的统一的微服务名microservicecloud-dept!可以把 8001,8002,8003理解为一个微服务的3个实例。
(4)启动3个eureka集群配置区
(5)启动3个Dept微服务并各自测试通过
http://localhost:8001/dept/list
http://localhost:8002/dept/list
http://localhost:8003/dept/list
(6)启动microservicecloud-consumer-dept-80
(7)客户端通过Ribbo完成负载均衡并访问上一步的Dept微服务
http://localhost/consumer/dept/list
注意观察看到返回的数据库名字,各不相同,负载均衡实现
(8)Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。
IRule:根据特定算法中从服务列表中选取一个要访问的服务
(1)RoundRobinRule 轮询
(2)RandomRule 随机
(3)AvailabilityFilteringRule
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列 表按照轮询策略进行访问。
(4)WeightedResponseTimeRule
根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。刚启动时如果统计信息不足,则 使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule
(5)RetryRule
先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
(6)BestAvailableRule
会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
(7) ZoneAvoidanceRule
默认规则,复合判断server所在区域的性能和server的可用性选择服务器
microservicecloud-consumer-dept-80的com.atguigu.springcloud.cfgbeans包下ConfigBean的编写
package com.atguigu.springcloud.cfgbeans; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ConfigBean { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } @Bean public IRule myRule() { return new RandomRule();//Ribbon默认是轮询,我自定义为随机 } }