SpringCloud中使用Ribbon的方法详解
springcloud之ribbon介绍
ribbon是负责负载均衡的,属于进程内负载均衡。请求发送到ribbon然后由ribbon发送到各个服务。
服务器端负载均衡:Nginx与F5集中式负载均衡只位于因特网与服务提供者之间,并负责把网络请求转发到各个提供单位。
进程内负载均衡是指从一个实例库选取一个实例进行流量导入,在微服务的范畴内,实例库一般是存储在Eureka、Consul、Zookeeper、etcd这样的注册中心,而此时的负载均衡器就是类似于Ribbon的IPC(Inter-Process Communication,进程间通信)组件,因此,进程内,因此,进程内负载均衡也叫做客户端负载均衡。
Ribbon负载均衡策略
策略类 | 命令 | 描述 |
RandomRule | 随机策略 | 随机选择server |
RoundRobinRule | 轮询策略 | 按照顺序循环选择server |
RetryRule | 重试策略 |
在一个配置时间段内当选择server不成功,则一直尝试选择一个可用的server |
BestAvailableRule | 最低并发策略 | 逐个考察server,如果server断路器打开,则忽略,再选择其中并发连接最低的server |
AvailabilityFilteringRule | 可用过滤策略 | 过滤掉一直连接失败并被标记位circuit tripped的server,过滤掉那些高并发连接的server(active connections超过配置的阈值) |
ResponseTimeWeightedRule | 响应时间加权策略 | 根据server的响应时间分配权重。响应时间越长,权重越低,被选择到的概率就越低;响应时间越短,权重越高,被选择到的概率就越高。这个策略很贴切,综合了各种因素,如:网络、磁盘、IO等,这些因素直接影响着响应时间。 |
ZoneAvoidanceRule | 区域权衡策略 | 综合判断server所在区域的性能和server的可用性轮询选择server,并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server |
可以在java配置文件中添加自己所需要的负载均衡策略如:
1 2 3 4 5 6 7 8 9 10 11 12 | import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RandomRule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TestConfiguration { @Bean public IRule ribbonRule(){ return new RandomRule(); } } |
也可以在yml文件中配置负载均衡的实现类:(注意:yml的配置高于java配置文件,若同时配置了Java和yml则会选择yml的配置)
1 2 3 | client-a: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule |
application.yml中配置ribbon的其他配置
1 2 3 4 5 6 7 | client-a: ribbon: ConnectTimeout: 300000 ReadTimeout: 300000 MaxAutoRetries: 1 #对第一次请求的服务的重试次数 MaxAutoRetriesNextServer: 1 #要重试的下一个服务的最大数量(不包括第一个服务) OkToRetryOnAllOperations: true |
ribbon默认是懒加载,所以第一次请求会慢很多(他需要从注册中心拿去服务实例列表,在进行自身策略的调整),为了避免这个问题使懒加载变为饿加载让其在项目启动时就加载,我们采用如下配置:
1 2 3 4 | ribbon: eager-load: enable: true clients: client-a, client-b, client-c |
ribbon1.2.0之后的版本支持了yml配置ribbon的行为,也就是说通过配置文件能决定让ribbon使用哪些实现类来完成负载均衡:
ribbon各个功能的接口:这些接口在用到的时候可查有哪些实现类,若有兴趣也可自己实现具体实现类来配置。
自定义配置实现类的列表:
Ribbon实例
搭建Eureka服务器
pom.xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <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> <groupId>eureka-client-ribbon</groupId> <artifactId>eureka-client-ribbon</artifactId> <version> 0.0 . 1 -SNAPSHOT</version> <packaging>jar</packaging> <name>Provider8003</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version> 2.0 . 3 .RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF- 8 </project.build.sourceEncoding> <project.reporting.outputEncoding>UTF- 8 </project.reporting.outputEncoding> <java.version> 1.8 </java.version> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope> import </scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
application.yml
1 2 3 4 5 6 7 8 9 10 11 12 | server: port: 7001 eureka: instance: hostname: localhost client: register-with-eureka: false fetchRegistry: false service-url: defaultZone: http: //localhost:7001/eureka |
Application.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package com.zk.ribbon; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableEurekaServer public class Application { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(Application. class , args); } } |
搭建服务提供者
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <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> <groupId>eureka-client-ribbon</groupId> <artifactId>eureka-client-ribbon</artifactId> <version> 0.0 . 1 -SNAPSHOT</version> <packaging>jar</packaging> <name>Provider8003</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version> 2.0 . 3 .RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF- 8 </project.build.sourceEncoding> <project.reporting.outputEncoding>UTF- 8 </project.reporting.outputEncoding> <java.version> 1.8 </java.version> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope> import </scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
Police.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | package com.zk.springribbon; public class Police { private String id; // 警察编号,用来保存用户输入的参数 private String url; // 处理请求的服务器url private String message; // 提示信息 public String getId() { return id; } public void setId(String id) { this .id = id; } public String getUrl() { return url; } public void setUrl(String url) { this .url = url; } public String getMessage() { return message; } public void setMessage(String message) { this .message = message; } } |
PoliceApplication.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.zk.springribbon; import java.util.Scanner; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class PoliceApplication { public static void main(String[] args) { Scanner scan = new Scanner(System. in ); String port = scan.nextLine(); new SpringApplicationBuilder(PoliceApplication. class ).properties( "server.port=" + port).run(args); } } |
PoliceController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | package com.zk.springribbon; import org.apache.catalina.servlet4preview.http.HttpServletRequest; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class PoliceController { @RequestMapping(value= "/getPolice" , method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE) public Police getPolice(HttpServletRequest request){ Police p = new Police(); p.setUrl(request.getRequestURL().toString()); p.setMessage( "警察派出成功" ); return p; } @RequestMapping(value= "/getPoliceById/{id}" , method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE) public Police getPolice(HttpServletRequest request, @PathVariable( "id" ) String id){ Police p = new Police(); p.setId(id); p.setUrl(request.getRequestURL().toString()); p.setMessage( "指定警察派出成功" ); return p; } } |
application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 | server: port: 8003 spring: application: name: springCloud-ribbon-police eureka: client: register-with-eureka: true fetchRegistry: false service-url: defaultZone: http: //localhost:7001/eureka |
因为需要测试负载均衡,服务提供者需要开启多个服务实例。我们使用手动读取端口号的方式,启动多个服务实例,下面启动8002、8003端口,输入localhost:7001
服务调用者
配置 pom.xml,加入springCloud核心依赖、配置及eureka客户端依赖、Ribbon依赖
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <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> <groupId>eureka-client-ribbon</groupId> <artifactId>eureka-client-ribbon</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>eureka-client-ribbon</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8 </project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
PersonApplication.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package com.zk.springribbon; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class PersonApplication { public static void main(String[] args) { new SpringApplicationBuilder(PersonApplication. class ).web( true ).run(args); } } |
PersonController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | package com.zk.springribbon; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; 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; @RestController @Configuration public class PersonController { @Bean @LoadBalanced public RestTemplate getRestTemplate(){ return new RestTemplate(); } @RequestMapping( "/getPolice" ) public String getPolice(){ RestTemplate rt = getRestTemplate(); String result = rt.getForObject( "http://springCloud-ribbon-police/getPolice" , String. class ); return result; } @RequestMapping( "/getPoliceById/{id}" ) public String getPoliceById(@PathVariable( "id" ) String id){ RestTemplate rt = getRestTemplate(); String result = rt.getForObject( "http://springCloud-ribbon-police/getPoliceById/" +id, String. class ); return result; } } |
Application.yml
1 2 3 4 5 6 7 8 9 | server: port: 9090 spring: application: name: springCloud-ribbon-person eureka: client: serviceUrl: defaultZone: http: //localhost:8761/eureka/ |
启动http://localhost:9090/getPolice,发现负载均衡服务接口已经调通了。
参考文档如下:https://www.cnblogs.com/li-yan-long/p/15989103.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)