Spring Cloud入门教程(二):客户端负载均衡(Ribbon)
对于大型应用系统负载均衡(LB:Load Balancing)是首要被解决一个问题。在微服务之前LB方案主要是集中式负载均衡方案,在服务消费者和服务提供者之间又一个独立的LB,LB通常是专门的硬件,如F5,或者是基于软件的,如VS、HAproxy等。LB上有所有服务的地址映射表,当服务消费者调用某个目标服务时,它先向LB发起请求,由LB以某种策略(比如:Round-Robin)做负载均衡后将请求转发到目标服务。
而微服务的出现,则为LB的实现提供了另外一种思路:把LB的功能以库的方式集成到服务消费方的进程内,而不是由一个集中的设备或服务器提供。这种方案称为软负载均衡(Soft Load Balancing)或者客户端负载均衡。在Spring Cloud中配合Eureka的服务注册功能,Ribbon子项目则为REST客户端实现了负载均衡。
接下来我们将通过扩展上一篇中的示例代码来搭建一个基于Ribbon的客户端负载均衡示例。
1. 示例代码
保持上一篇中的代码不变。
2. 如何启用Ribbon
在上一篇中的consumer-hello
工程(也就是我们的服务消费方)的pom的依赖中声明了:
<dependency><groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-ribbon</artifactId> </dependency>
也就是说在本项目中将会启动Ribbon。
2.1 启动类
@EnableDiscoveryClient
@SpringBootApplication
public class Application { @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
在该启动类中:
@EnableDiscoveryClient
注解,说明这是一个Eureka客户端,同时也可以获取到Eureka服务器中所注册的服务列表;- 在
RestTemplate
中我们增加了一个@LoadBalanced
注解,该注解就是能够让RestTemplate
启用客户端负载均衡。
备注:如果你对Spring的RestTemplate使用还不是很了解,可以参考我的这篇文章《Spring Cloud入门教程(番外篇一):RestTemplate使用指南》。
3. 负载均衡测试
1) 启动Eureka服务器;
2) 启动多个服务提供者:SERVICE-HELLO,这里我启动了两个:
java -jar service-hello-1.0.0-SNAPSHOT.jarjava -jar service-hello-1.0.0-SNAPSHOT.jar --server.port=2200
通过Maven将Service-Hello
打包成一个FatJar,可以使用上面的命令启动多个实例。这里SERVICE-HELLO
的两个实例服务器端口分别为:2100
和2200
。
3) 启动服务消费者:consumer-hello;
4) 打开Eureka服务器管理页面:http://localhost:8260,可以看到已经有两个SERVICE-HELLO
服务和一个CONSUMER-HELLO
服务注册进来了。
5) 打开Consumer-Hello:http://localhost:8080/hello,多次刷新,在页面中我们可以看到下面两个输出交替出现:
说明了consumer-hello
在交替访问SERVICE-HELLO
的两个服务实例,也就是说我们的负载均衡测试是成功的。
4. 直接使用Ribbon的API
另外,除了使用@LoadBalanced
注解外,我们还可以直接使用Ribbon所提供的LoadBalancerClient
来实现负载均衡:
@RestController
public class HelloController { protected Logger logger = LoggerFactory.getLogger(HelloController.class); @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @RequestMapping(value = "/hello", method = RequestMethod.GET) public String hello() { return restTemplate.getForEntity("http://SERVICE-HELLO/hello", String.class).getBody(); } @RequestMapping(value = "/helloEx", method = RequestMethod.GET) public String helloEx() { ServiceInstance instance = this.loadBalancerClient.choose("SERVICE-HELLO"); URI helloUri = URI.create(String.format("http://%s:%s/hello", instance.getHost(), instance.getPort())); logger.info("Target service uri = {}. ", helloUri.toString()); return new RestTemplate().getForEntity(helloUri, String.class).getBody(); } }
同样多次访问http://localhost:8080/helloEx后,在控制台中将会输出以下日志:
2017-06-26 21:31:30 891 [http-nio-8080-exec-3] INFO i.t.c.c.h.controller.HelloController - Target service uri = http://cd826dembp.lan:2100/hello. 2017-06-26 21:31:33 008 [http-nio-8080-exec-4] INFO i.t.c.c.h.controller.HelloController - Target service uri = http://cd826dembp.lan:2200/hello. 2017-06-26 21:31:34 447 [http-nio-8080-exec-6] INFO i.t.c.c.h.controller.HelloController - Target service uri = http://cd826dembp.lan:2100/hello. 2017-06-26 21:31:35 395 [http-nio-8080-exec-7] INFO i.t.c.c.h.controller.HelloController - Target service uri = http://cd826dembp.lan:2200/hello. 2017-06-26 21:31:36 220 [http-nio-8080-exec-8] INFO i.t.c.c.h.controller.HelloController - Target service uri = http://cd826dembp.lan:2100/hello.
说明负载均衡是一样启作用的。
注意:在helloEx
方法中不能够使用之前自动织入的restTemplate
,否则会报以下错误:
java.lang.IllegalStateException: No instances available for cd826dembp.lan
这个是因为自动织入的restTemplate
会把服务器的逻辑名称当作服务名称来使用,造成找不到相应的服务实例,从而报错。
另外,我们还可以采用下面的方式:
@Primary
@Bean(name="lbcRestTemplate")
RestTemplate lbcRestTemplate() { return new RestTemplate(); }
上面的类更改为:
@RestController
public class HelloController { protected Logger logger = LoggerFactory.getLogger(HelloController.class); @Autowired @Qualifier(value = "restTemplate") private RestTemplate restTemplate; @Autowired @Qualifier(value = "lbcRestTemplate") private RestTemplate lbcRestTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @RequestMapping(value = "/hello", method = RequestMethod.GET) public String hello() { return restTemplate.getForEntity("http://SERVICE-HELLO/hello", String.class).getBody(); } @RequestMapping(value = "/helloEx", method = RequestMethod.GET) public String helloEx() { ServiceInstance instance = this.loadBalancerClient.choose("SERVICE-HELLO"); URI helloUri = URI.create(String.format("http://%s:%s/hello", instance.getHost(), instance.getPort())); logger.info("Target service uri = {}. ", helloUri.toString()); return this.lbcRestTemplate.getForEntity(helloUri, String.class).getBody(); } }
5. Ribbon负载均衡策略
Ribbon本身提供了下面几种负载均衡策略:
- RoundRobinRule: 轮询策略,Ribbon以轮询的方式选择服务器,这个是默认值。所以示例中所启动的两个服务会被循环访问;
- RandomRule: 随机选择,也就是说Ribbon会随机从服务器列表中选择一个进行访问;
- BestAvailableRule: 最大可用策略,即先过滤出故障服务器后,选择一个当前并发请求数最小的;
- WeightedResponseTimeRule: 带有加权的轮询策略,对各个服务器响应时间进行加权处理,然后在采用轮询的方式来获取相应的服务器;
- AvailabilityFilteringRule: 可用过滤策略,先过滤出故障的或并发请求大于阈值一部分服务实例,然后再以线性轮询的方式从过滤后的实例清单中选出一个;
- ZoneAvoidanceRule: 区域感知策略,先使用主过滤条件(区域负载器,选择最优区域)对所有实例过滤并返回过滤后的实例清单,依次使用次过滤条件列表中的过滤条件对主过滤条件的结果进行过滤,判断最小过滤数(默认1)和最小过滤百分比(默认0),最后对满足条件的服务器则使用RoundRobinRule(轮询方式)选择一个服务器实例。
我们可以通过继承
ClientConfigEnabledRoundRobinRule
,来实现自己负载均衡策略。
这里,大家先对Ribbon提供的负载均衡有一个概念,后续我们再详细分析各个负载均衡策略的具体处理逻辑及配置方式。
6. 小结
Ribbon的主要功能是为REST客户端实现负载均衡,其工作原理可以概括为下面四个步骤:
- Ribbon首先根据其所在Zone优先选择一个负载较少的Eureka Server;
- 定期从Eureka Server更新并过滤服务实例列表;
- 根据指定的负载均衡策略,从可用的服务器列表中选择一个服务实例的地址;
- 然后通过RestClient进行服务调用。
这时我们系统的架构变成为:
转载于:https://www.cnblogs.com/lykbk/p/fghfghgfhfh654656565.html
Spring Cloud入门教程(二):客户端负载均衡(Ribbon)相关推荐
- Spring Cloud 入门教程(二): 配置管理
使用Config Server,您可以在所有环境中管理应用程序的外部属性.客户端和服务器上的概念映射与Spring Environment和PropertySource抽象相同,因此它们与Spring ...
- 客户端负载均衡Ribbon之一:Spring Cloud Netflix负载均衡组件Ribbon介绍
Netflix:['netfliːks] ribbon:英[ˈrɪbən]美[ˈrɪbən] n. 带; 绶带; (打印机的) 色带; 带状物; v. 把-撕成条带; 用缎带装饰; 形成带状; ...
- [学习笔记]Spring Cloud详细教程(二)
文章目录 服务调用Ribbon getForEntity Ribbon的负载均衡 更换负载均衡算法 手写一个轮询算法 服务调用OpenFeign OpenFeign的使用 OpenFeign的超时控制 ...
- 五、springcloud之客户端负载均衡Ribbon
一.简介 在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的.Spring cloud有两种服务调用方式: 一种是ribbon+restTemplate, ...
- Spring Cloud入门教程 - Zuul实现API网关和请求过滤
简介 Zuul是Spring Cloud提供的api网关和过滤组件,它提供如下功能: 认证 过滤 压力测试 Canary测试 动态路由 服务迁移 负载均衡 安全 静态请求处理 动态流量管理 在本教程中 ...
- Spring Cloud入门教程-Hystrix断路器实现容错和降级
简介 Spring cloud提供了Hystrix容错库用以在服务不可用时,对配置了断路器的方法实行降级策略,临时调用备用方法.这篇文章将创建一个产品微服务,注册到eureka服务注册中心,然后我们使 ...
- Spring Boot入门教程(二十八): 校验(validation)
validation主要是校验用户提交的数据的合法性,比如是否为空,密码是否符合规则,邮箱格式是否正确等等,校验框架比较多,用的比较多的是hibernate-validator, 也支持国际化,也可以 ...
- Spring Boot入门教程(二十五): Apache Shiro
1. pom.xml shiro并没有提供对应的Starter,而是使用的shiro-spring,其它的依赖都是辅助 <dependency><groupId>org.spr ...
- Spring Cloud微服务笔记(四)客户端负载均衡:Spring Cloud Ribbon
客户端负载均衡:Spring Cloud Ribbon 一.负载均衡概念 负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容.因为负载均衡对系统的高可用性. 网络压力的缓解和处理能力的扩容的 ...
最新文章
- linux下编译动态和静态链接库
- Docker selenium自动化 - 使用python操作docker,python运行、启用、停用和查询容器实例演示
- linux6.4 vnc安装与配置,Oracle Enterprise Linux 6.4 下配置vncserver
- 数据可视化组队学习:《Task05 - 样式色彩秀芳华》笔记
- 苏宁大促高并发要求下的售后服务运营能力承诺服务系统架构实战\n
- SRS流媒体服务器——Forward集群搭建和源码分析
- 杨超越微数据_资料来源同意:数据科学技能超越数据
- 如何给FormPanel表单中的元素赋值以及获取表单元素值
- linux java升级版本_为嵌入式Linux设备实现更新/升级系统
- python打代码运行图形_利用aardio给python编写图形界面
- 杨强教授领衔力作,《迁移学习》最新出炉,解决AI“最后一公里”问题 | 赠书...
- 计算机应用与维修专业主修,计算机应用与维修专业个人简历制作
- 基于OpenCV的三维数据点的曲面重构_MySurefaceReconstruction
- 微信小程序之 ----组件
- 互联网日报 | 8月3日 星期二 | 陌陌宣布更名为“Hello”集团;国家电网升至世界500强第二位;比亚迪总市值超8300亿...
- PS去除图片和PDF中的水印
- pix2pix、pix2pixHD 通过损失日志进行训练可视化
- Linux 硬盘读写测速
- TCP之Delay ACK在Linux和Windows上实现的异同-Linux的自适应ACK
- 战胜拖延症的利器—Product Backlog
热门文章
- 【CCF】201409-2 画图
- 漫步最优化十二——局部极小与极大的充分必要条件(下)
- tf.keras.layers.Attention 理解总结
- c++ idea 插件_IDEA的基本使用:让你的IDEA有飞一般的感觉 CSDN 博文精选
- python 3.5 format_Python3 format及字符串格式化
- Python下基于requests及BeautifulSoup构建网络爬虫
- C++/C--文件及函数注释【转载】
- FFMPEG针对视频操作的基本命令
- Mosquitto 0 15 开源MQTT v3 1 Broker
- 爬虫学习一:HTTP、网页基础、requests、API、JS