springcloud-04-自定义ribbon的配置方式
在dubbo项目中, zookeeper即注册中心帮我们实现了调度和负载均衡的能力, 这种方式被称为服务器端的负载均衡, springcloud中, 使用ribben实现的客户端负载均衡
什么是ribbon?
Ribbon是Netflix发布的云中间层服务开源项目,其主要功能是提供客户端侧负载均衡算法。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,我们可以在配置文件中列出Load Balancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,我们也很容易使用Ribbon实现自定义的负载均衡算法。
eureka使用ribbon的大致架构
Ribbon工作时分为两步:第一步先选择 Eureka Server, 它优先选择在同一个Zone且负载较少的Server;第二步再根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略,例如轮询round robin、随机Random、根据响应时间加权等。
通过代码实现:
将刚才的cosumer-movie改造成ribbon的项目
添加一个注解类, 需要放置在mainClass扫描不到的包下, 或者在mainClass中通过@COmponentScan进行过滤
这儿使用的是注解过滤, 所以首先需要一个注解:
package com.wenbronk.cosumer.ribben.annotation; /** * 自定义注解, 排除不想被扫描到的内容 * Created by wenbronk on 2017/5/18. */ public @interface ExcudeAnnotation { }
然后是一个ribbon的注解声明类:
package com.wenbronk.cosumer.ribben.config; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RandomRule; import com.wenbronk.cosumer.ribben.annotation.ExcudeAnnotation; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 默认规则为轮询, 这个为随机规则 * 该类必须放置在扫描不到的包下, 或者添加排除, 虽然他必须有注解 * Created by wenbronk on 2017/5/18. */ @Configuration @ExcudeAnnotation public class MyRibbonConfig { @Bean public IRule ribbonRule() { return new RandomRule(); } }
在mainClass中进行过滤
package com.wenbronk.cosumer.ribben; import com.wenbronk.cosumer.ribben.annotation.ExcudeAnnotation; import com.wenbronk.cosumer.ribben.config.MyRibbonConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; import org.springframework.web.client.RestTemplate; /** * 通过RIbbonClient自定义ribbon客户端 * Created by root on 2017/5/18. */ @SpringBootApplication @EnableEurekaClient // 使用此规则不可放在 可扫描的路径下, 如果非要放置, 需要加自定义注解 @RibbonClient(name = "microserver-provider-user", configuration = MyRibbonConfig.class) @ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {ExcudeAnnotation.class})}) public class MovieRibbenApplication { /** * 使用LoadBalanced开启客户端负载均衡的功能 * @return */ @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(MovieRibbenApplication.class, args); } }
验证:
通过配置端口, 将user服务启动4个实例, 并注册为2个服务, 在movie-ribbon的controller中加入如下代码
package com.wenbronk.cosumer.ribben.controller; import com.wenbronk.cosumer.ribben.entity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; 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; /** * Created by root on 2017/5/18. */ @RestController public class MovieRibbenController { @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @RequestMapping("/movie/{id}") public User findById(@PathVariable Long id) { return restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class); } @GetMapping("/test") public void test() { ServiceInstance instance = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER"); System.out.println("111: " + instance.getServiceId() + ": " + instance.getHost() + ": " + instance.getPort()); // System.out.println(instance.toString()); ServiceInstance instance1 = this.loadBalancerClient.choose("MICROSERVICE-PROVIDER-USER-1"); System.out.println("222: " + instance1.getServiceId() + ": " + instance1.getHost() + ": " + instance1.getPort()); // System.out.println(instance1); // System.out.println(instance == instance1); } }
通过浏览器重复的发送请求, 在控制台可看到只有provide-user 使用了我们自定义的规则, user-1 仍然使用的ribbon的默认规则轮询
通过配置文件的方式, 自定义ribbonclient:
从版本1.2.0开始,Spring Cloud Netflix现在支持使用属性与Ribbon文档兼容来自定义Ribbon客户端。
配置的优先级: 配置文件 > java代码 > springcloud default
配置文件配置, 只需要在yml'中添加如下内容
users:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
NFLoadBalancerRuleClassName 是规则, 除了此规则 springcloud还有

每个规则可添加的类也有很多
mainClass.java
package com.wenbronk.cosumer.ribbon.yml; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; /** * Created by wenbronk on 2017/5/20. */ @SpringBootApplication @EnableEurekaClient public class MoveiRibbonYmlApplicatoin { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(MoveiRibbonYmlApplicatoin.class, args); } }
MovieRibbonController
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 | package com.wenbronk.cosumer.ribbon.yml.controller; import com.wenbronk.cosumer.ribbon.yml.entity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; 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; /** * Created by root on 2017/5/18. */ @RestController public class MovieRibbenController { @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @RequestMapping( "/movie/{id}" ) public User findById(@PathVariable Long id) { return restTemplate.getForObject( "http://microservice-provider-user/simple/" + id, User. class ); } @GetMapping( "/test" ) public void test() { ServiceInstance instance = this .loadBalancerClient.choose( "MICROSERVICE-PROVIDER-USER" ); System. out .println( "111: " + instance.getServiceId() + ": " + instance.getHost() + ": " + instance.getPort()); // System.out.println(instance.toString()); ServiceInstance instance1 = this .loadBalancerClient.choose( "MICROSERVICE-PROVIDER-USER-1" ); System. out .println( "222: " + instance1.getServiceId() + ": " + instance1.getHost() + ": " + instance1.getPort()); // System.out.println(instance1); // System.out.println(instance == instance1); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix