Java之 Spring Cloud 微服务搭建Ribbon(第一个阶段)【三】【SpringBoot项目实现商品服务器端是调用】

x33g5p2x  于2021-11-18 转载在 Java  
字(7.2k)|赞(0)|评价(0)|浏览(539)

服务调用Ribbon入门

经过以上的学习,已经实现了服务的注册和服务发现。

当启动某个服务的时候,可以通过HTTP的形式将信息注册到注册中心,并且可以通过SpringCloud提供的工具获取注册中心的服务列表。

但是服务之间的调用还存在很多的问题,如何更加方便的调用微服务,多个微服务的提供者如何选择,如何负载均衡等。

1、Ribbon概述

(1) 什么是Ribbon

是 Netflixfa 发布的一个负载均衡器,有助于控制 HTTP 和 TCP客户端行为。

在 SpringCloud 中,Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载。

在SpringCloud中可以将注册中心和Ribbon配合使用,Ribbon自动的从注册中心中获取服务提供者的列表信息,并基于内置的负载均衡算法,请求服务

(2) Ribbon的主要作用

(1)服务调用
基于Ribbon实现服务调用, 是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。借助RestTemplate 最终进行调用
(2)负载均衡
当有多个服务提供者时,Ribbon可以根据负载均衡的算法自动的选择需要调用的服务地址

2、基于Ribbon实现订单调用商品服务

不论是基于Eureka的注册中心还是基于Consul的注册中心,SpringCloudRibbon统一进行了封装,所以对于服务调用,两者的方式是一样的。

(1)坐标依赖

在springcloud提供的服务发现的jar中以及包含了Ribbon的依赖。
所以这里不需要导入任何额外的坐标

(2)工程改造

在创建RestTemplate的时候,声明@LoadBalanced
使用restTemplate调用远程微服务:不需要拼接微服务的URL路径,以待请求的服务名替换IP地址

1)修改order_service当中的OrderApplication启动类

  1. package cn.itbluebox.order;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.boot.autoconfigure.domain.EntityScan;
  5. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.web.client.RestTemplate;
  8. @SpringBootApplication
  9. @EntityScan("cn.itbluebox.order.entity")
  10. public class OrderApplication {
  11. /* 使用Spring提供的 RestTemplate 发送http请求到商品服务 1、创建RestTemplate对象交给容器管理 2、在使用的时候,调用其方法完成操作(getXX,postXX) @LoadBalanced : 是Ribbon提供的负载均衡的注解 */
  12. @LoadBalanced
  13. @Bean
  14. public RestTemplate restTemplate(){
  15. return new RestTemplate();
  16. }
  17. public static void main(String[] args) {
  18. SpringApplication.run(OrderApplication.class,args);
  19. }
  20. }
2)修改OrderController

实现基于Ribbon的形式调用远程的微服务

  1. 1、使用@LoadBalanced声明RestTemplate
  2. 2、使用服务名称替换IP地址

  1. package cn.itbluebox.order.controller;
  2. import cn.itbluebox.order.entity.Product;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.cloud.client.ServiceInstance;
  5. import org.springframework.cloud.client.discovery.DiscoveryClient;
  6. import org.springframework.web.bind.annotation.*;
  7. import org.springframework.web.client.RestTemplate;
  8. import java.util.List;
  9. @RestController
  10. @RequestMapping("/order")
  11. public class OrderController {
  12. //注入RestTemplate对象
  13. @Autowired
  14. private RestTemplate restTemplate;
  15. /* 注入DiscoveryClient: SpringCloud 提供的获取原数组的工具类 调用方法获取服务的元数据信息 */
  16. @Autowired
  17. private DiscoveryClient discoveryClient;
  18. /* 参数:商品ID 通过订单系统,调用商品服务 1、需要配置商品对象 2、需要调用商品服务 3、entity.Product 使用java 当中的urlconnection,httpclient,okhttp */
  19. /* 实现基于Ribbon的形式调用远程的微服务 1、使用@LoadBalanced声明RestTemplate 2、使用服务名称替换IP地址 */
  20. @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
  21. public Product findById(@PathVariable Long id) {
  22. //如何调用商品服务?
  23. return restTemplate.getForObject("http://service-product/product/"+id,Product.class);
  24. }
  25. @RequestMapping(method = RequestMethod.POST)
  26. public String save(@RequestBody Product product) {
  27. restTemplate.postForObject("http://service-product/product/",product,Product.class);
  28. return "保存成功";
  29. }
  30. @RequestMapping(method = RequestMethod.PUT)
  31. public String update(@RequestBody Product product) {
  32. restTemplate.put("http://service-product/product/",product);
  33. return "更新成功";
  34. }
  35. @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
  36. public String delete(@PathVariable Long id) {
  37. restTemplate.delete("http://service-product/product/"+id);
  38. return "删除成功";
  39. }
  40. }

(3)运行测试

访问:http://localhost:9002/order/buy/1

七、服务调用Ribbon高级

1、负载均衡概述

(1)什么是负载均衡

在搭建网站时,如果单节点的 web服务性能和可靠性都无法达到要求;

或者是在使用外网服务时,经常担心被人攻破,一不小心就会有打开外网端口的情况,通常这个时候加入负载均衡就能有效解决服务问题。

负载均衡是一种基础的网络服务,其原理是通过运行在前面的负载均衡服务,按照指定的负载均衡算法,将流量分配到后端服务集群上,从而为系统提供并行扩展的能力。

负载均衡的应用场景包括流量包、转发规则以及后端服务,由于该服务有内外网个例、健康检查等功能,能够有效提供系统的安全性和可用性。

(2)客户端负载均衡与服务端负载均衡

服务端负载均衡
先发送请求到负载均衡服务器或者软件,然后通过负载均衡算法,在多个服务器之间选择一个进行访问;
即在服务器端再进行负载均衡算法分配

客户端负载均衡
客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,这是客户端负载均衡;
即在客户端就进行负载均衡算法分配

2、基于Ribbon实现负载均衡

(1)搭建多服务实例

Ribbon是一个典型的客户端负载均衡器,Ribbon会获取服务的所有地址,
根据内部的负载均衡算法,获取本次请求的有效地址

1)准备两个商品微服务(9001,9011 )

修改product_service当中的ProductController类,设置spring cloud 自动的获取当前应用的ip地址

  1. package cn.itbluebox.product.controller;
  2. import cn.itbluebox.product.entity.Product;
  3. import cn.itbluebox.product.service.ProductService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.beans.factory.annotation.Value;
  6. import org.springframework.web.bind.annotation.*;
  7. @RestController
  8. @RequestMapping("/product")
  9. public class ProductController {
  10. @Autowired
  11. private ProductService productService;
  12. @Value("${server.port}")
  13. private String port;
  14. @Value("${spring.cloud.client.ip-address}") //spring cloud 自动的获取当前应用的ip地址
  15. private String ip;
  16. @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  17. public Product findById(@PathVariable Long id) {
  18. Product product = productService.findByID(id);
  19. product.setProductName("访问的服务地址:"+ip+":"+port);
  20. return product;
  21. }
  22. @RequestMapping(method = RequestMethod.POST)
  23. public String save(@RequestBody Product product) {
  24. productService.save(product);
  25. return "保存成功";
  26. }
  27. @RequestMapping(method = RequestMethod.PUT)
  28. public String update(@RequestBody Product product) {
  29. productService.update(product);
  30. return "更新成功";
  31. }
  32. @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
  33. public String delete(@PathVariable Long id) {
  34. productService.delete(id);
  35. return "删除成功";
  36. }
  37. }
2)运行测试

访问:http://localhost:9001/product/1

3)设置复制另外一个启动方式
  • 修改端口号

  • 复制项目启动

  • 为了方便后期测试,将product_service当中的application.yml改回原来的配置

(2)在订单系统中远程以负载均衡的形式调用商品服务(order_service)

在之前在 @LoadBalanced已当中经配置了,直接启动就实现负载均衡

访问http://localhost:9002/order/buy/1
我们发现端口是9011

刷新页面
我们发现端口是9001

再次刷新页面
我们发现端口是9011

上述情况我们实现了负载均衡

(3)修改order_service设置application.yml修改Ribbon的策略配置

  • com.netflix.loadbalancer.RoundRobinRule :以轮询的方式进行负载均衡。
  • com.netflix.loadbalancer.RandomRule :随机策略
  • com.netflix.loadbalancer.RetryRule :重试策略。
  • com.netflix.loadbalancer.WeightedResponseTimeRule :权重策略。会计算每个服务的权重,越高的被调用的可能性越大。
  • com.netflix.loadbalancer.BestAvailableRule :最佳策略。遍历所有的服务实例,过滤掉故障实例,并返回请求数最小的实例返回。
  • com.netflix.loadbalancer.AvailabilityFilteringRule :可用过滤策略。过滤掉故障和请
    求数超过阈值的服务实例,再从剩下的实力中轮询调用。

  1. # 修改ribbon的负载均衡策略 服务名称 + ribbon - NFLoadBalancerRuleClassName : 策略
  2. service-product:
  3. ribbon:
  4. NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

程序启动order_service

访问:
http://localhost:9002/order/buy/1

刷新

刷新

1、如果每个机器配置一样,则建议不修改策略 (推荐)
2、如果部分机器配置强,则可以改为 WeightedResponseTimeRule

完善后面的测试设置上述的配置注释掉

(4)Ribbon:请求重试

1)完善后面的测试在order_service当中的application.yml设置上述的配置注释掉

设置打印日志

  1. logging:
  2. level:
  3. root: debug #使用ip地址注册

重新运行测试

访问:http://localhost:9002/order/buy/1

刷新

在这里我们关闭一台ProductApplication模拟网络波动

刷新页面

再次刷新

2)Ribbon重试机制

引入Spring的重试组件
对Ribbon进行重试的配置

01)引入Spring的重试组件,修改order_service的pom.xml

  1. <dependency>
  2. <groupId>org.springframework.retry</groupId>
  3. <artifactId>spring-retry</artifactId>
  4. </dependency>
02)设置重试机制

  1. service-product:
  2. ribbon:
  3. #NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
  4. ConnectTimeout: 250 # Ribbon的连接超时时间
  5. ReadTimeout: 1000 # Ribbon的数据读取超时时间
  6. OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
  7. MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
  8. MaxAutoRetries: 1 # 对当前实例的重试次数

访问测试:http://localhost:9002/order/buy/1

刷新

启动停掉的服务

刷新页面

刷新

现在我们关闭一个服务

刷新页面

再次刷新

3、Ribbon中负载均衡的源码解析

(1) Ribbon中的关键组件

  • ServerList:可以响应客户端的特定服务的服务器列表。
  • ServerListFilter:可以动态获得的具有所需特征的候选服务器列表的过滤器。
  • ServerListUpdater:用于执行动态服务器列表更新。
  • Rule:负载均衡策略,用于确定从服务器列表返回哪个服务器。
  • Ping:客户端用于快速检查服务器当时是否处于活动状态。
  • LoadBalancer:负载均衡器,负责负载均衡调度的管理。

(2) @LoadBalanced注解

相关文章

最新文章

更多