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实现服务调用,是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。借助于RestTemplate最终进行调用。
负载均衡:当有多个服务提供者时,Ribbon可以根据负载均衡的算法自动的选择需要调用的服务地址。
2.3 基于Ribbon实现订单微服务调用商品微服务
2.3.1 概述
- 不论是基于Eureka的注册中心还是基于Consul的注册中心,SpringCloud的Ribbon统一进行了封装,所以对于服务的调用,两者的方式是一样的。
2.3.2 改造步骤
在使用Eureka作为注册中心的时候,不需要再导入Ribbon的相关依赖,因为Eureka内部集成了Ribbon了。
在创建RestTemplate的时候,声明@LoadBalanced注解。
使用RestTemplate调用远程微服务的时候,不需要自己手动拼接远程微服务的URL,只需要用远程微服务的服务名替换IP地址即可。
2.3.3 实现
- 订单微服务:在创建RestTemplate的时候,声明@LoadBalanced注解
package com.sunxiaping.order.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;@Configurationpublic class SpringConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}}
- 订单微服务:使用RestTemplate调用远程微服务的时候,不需要自己手动拼接远程微服务的URL,只需要用远程微服务的服务名替换IP地址即可
package com.sunxiaping.order.controller;import com.sunxiaping.order.domain.Product;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cloud.client.discovery.DiscoveryClient;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;@RestController@RequestMapping(value = "/order")public class OrderController {@Autowiredprivate RestTemplate restTemplate;/*** SpringCloud提供的获取元数据的工具类* 调用方法获取服务的元数据*/@Autowiredprivate DiscoveryClient discoveryClient;/*** 基于Ribbon的形式调用远程的微服务** @param id* @return*/@GetMapping(value = "/buy/{id}")public Product buy(@PathVariable(value = "id") Long id) {Product product = restTemplate.getForObject("http://service-product/product/findById/" + id, Product.class);return product;}}

