1 前言

  • 前面的章节中,我们已经实现了服务的注册和服务发现。当启动某个服务的时候,可以通过HTTP的形式将信息注册到注册中心,并且可以通过SpringCloud提供的工具获取注册中心的服务列表。但是服务之间的调用还存在很多问题:如何更加方便的调用微服务,多个微服务的提供者如何选择,如何负载均衡等等。

2 Ribbon基础

2.1 什么是Ribbon?

  • Ribbon是Netflix公司发布的一个负载均衡器,有助于控制HTTP和TCP的客户端行为。在SpringCloud中,Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载均衡。
  • 在SpringCloud中可以将注册中心Eureka和Ribbon配合使用,Ribbon自动的从注册中心获取服务提供者的列表新,并基于内置的负载均衡算法,请求服务。

2.2 Ribbon的作用

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

2.3 基于Ribbon实现订单微服务调用商品微服务

2.3.1 概述

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

2.3.2 改造步骤

在使用Eureka作为注册中心的时候,不需要再导入Ribbon的相关依赖,因为Eureka内部集成了Ribbon了。

  • 负载均衡Ribbon基础(此版本不过时,后面的版本推荐使用Spring Cloud Loadbalancer) - 图3在创建RestTemplate的时候,声明@LoadBalanced注解。
  • 负载均衡Ribbon基础(此版本不过时,后面的版本推荐使用Spring Cloud Loadbalancer) - 图4使用RestTemplate调用远程微服务的时候,不需要自己手动拼接远程微服务的URL,只需要用远程微服务的服务名替换IP地址即可。

2.3.3 实现

  • 订单微服务:在创建RestTemplate的时候,声明@LoadBalanced注解
  1. package com.sunxiaping.order.config;
  2. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.client.RestTemplate;
  6. @Configuration
  7. public class SpringConfig {
  8. @Bean
  9. @LoadBalanced
  10. public RestTemplate restTemplate() {
  11. return new RestTemplate();
  12. }
  13. }
  • 订单微服务:使用RestTemplate调用远程微服务的时候,不需要自己手动拼接远程微服务的URL,只需要用远程微服务的服务名替换IP地址即可
  1. package com.sunxiaping.order.controller;
  2. import com.sunxiaping.order.domain.Product;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.cloud.client.discovery.DiscoveryClient;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.PathVariable;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import org.springframework.web.client.RestTemplate;
  10. @RestController
  11. @RequestMapping(value = "/order")
  12. public class OrderController {
  13. @Autowired
  14. private RestTemplate restTemplate;
  15. /**
  16. * SpringCloud提供的获取元数据的工具类
  17. * 调用方法获取服务的元数据
  18. */
  19. @Autowired
  20. private DiscoveryClient discoveryClient;
  21. /**
  22. * 基于Ribbon的形式调用远程的微服务
  23. *
  24. * @param id
  25. * @return
  26. */
  27. @GetMapping(value = "/buy/{id}")
  28. public Product buy(@PathVariable(value = "id") Long id) {
  29. Product product = restTemplate.getForObject("http://service-product/product/findById/" + id, Product.class);
  30. return product;
  31. }
  32. }

代码测试.png