Ribbon概述
Ribbon是一个客户端负载均衡器,它提供了对HTTP和TCP客户端的行为的大量控制。我们在上篇(请参考:SpringCloud系列——Feign 服务调用)已经实现了多个服务之间的Feign调用,服务消费者调用服务提供者,本文记录Feign调用Ribbon负载均衡的服务提供者
负载均衡
负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们通常所说的负载均衡都指的是服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点之间按照专门用于负载均衡的设备,比如F5等;而软件负载均衡则是通过在服务器上安装一些用于负载均衡功能或模块等软件来完成请求分发工作,比如Nginx等。不论采用硬件负载均衡还是软件负载均衡,只要是服务端都能以类似下图的架构方式构建起来:GitHub地址:https://github.com/Netflix/ribbon
服务提供者
服务提供者有两个,实际上可以看做只有一个,因为这两个只有端口不同,应用名相同,maven引入Ribbon
<!-- Ribbon --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
创建RibbonConfig文件,主类添加@RibbonClient(name = "RibbonConfig", configuration = RibbonConfig.class)
@EnableEurekaClient @RibbonClient(name = "RibbonConfig", configuration = RibbonConfig.class) @SpringBootApplication public class SpringbootSpringdataJpaApplication{ public static void main(String[] args) { SpringApplication.run(SpringbootSpringdataJpaApplication.class, args); } } @Configuration class RibbonConfig { @Bean public IRule ribbonRule(){ return new RandomRule(); //分配策略:随机选择一个server // return new BestAvailableRule(); //分配策略:选择一个最小的并发请求的server,逐个考察Server,如果Server被tripped了,则忽略 // return new RoundRobinRule(); //分配策略:轮询选择,轮询index,选择index对应位置的server // return new WeightedResponseTimeRule(); //分配策略:根据响应时间分配一个weight(权重),响应时间越长,weight越小,被选中的可能性越低 // return new ZoneAvoidanceRule(); //分配策略:复合判断server所在区域的性能和server的可用性选择server // return new RetryRule(); //分配策略:对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server } @Bean public IPing ribbonPing() { return new PingUrl(); } @Bean public ServerListSubsetFilter serverListFilter() { ServerListSubsetFilter filter = new ServerListSubsetFilter(); return filter; } }
下表显示了Spring Cloud Netflix默认为Ribbon提供的bean:
官网例子:
PS:我们启动的时候有可能会碰到这个问题或类似的问题,说我们注入的某个bean对象有重名,叫我们改名或启用覆盖
这个是ribbonRule跟txlcn框架的重名了,我们这里进行改名就能解决问题
@FeignClient(name = "springdatejpa", path = "/user/") public interface MyspringbootFeign { @RequestMapping("/ribbon") String ribbon(); }
我们添加一个测试接口
@RestController @RequestMapping("/user") public class UserController { @RequestMapping("/ribbon") public String ribbon() { return "springdatejpa -- 我的端口是:10082"; } }
第二个服务提供者也是这样配置,注意:应用名要相同(spring.application.name=springdatejpa);端口不同;
服务消费者
服务消费者使用Feign调用,无需做任何修改,Feign已经使用Ribbon。具体配置请戳:SpringCloud系列——Feign 服务调用
@FeignClient(name = "service-a", path = "/") public interface MyspringbootFeign { @RequestMapping("/ribbon") String ribbon(); }
/** * feign调用 */ @GetMapping("/ribbon") String ribbon(){ return myspringbootFeign.ribbon(); }
效果
启动所有项目,我们注册了三个服务,其中:
有两个服务名称相同、处理的业务相同、端口不同,这两台作为服务提供者(可看做是一个“小集群”);
另一个是服务消费者(Feign调用)
消费者不断调用,Ribbon会从注册中心的服务列表拉取实例集合进行负载均衡调用背后的服务提供者,负载均衡默认采用轮询机制进行服务的调用