第一章 Java线程池技术应用
第二章 CountDownLatch和Semaphone的应用
第三章 Spring Cloud 简介
第四章 Spring Cloud Netflix 之 Eureka
第五章 Spring Cloud Netflix 之 Ribbon

Spring Cloud Ribbon 是一套基于 Netflix Ribbon 实现的客户端负载均衡和服务调用工具,其主要功能是提供客户端的负载均衡算法和服务调用。
今天我们以电商微服务为例,来讲解Eureka 、Ribbon在微服务治理方面的实战应用。


负载均衡(Load Balance) ,简单点说就是将用户的请求平摊分配到多个服务器上运行,以达到扩展服务器带宽、增强数据处理能力、增加吞吐量、提高网络的可用性和灵活性的目的。
常见的负载均衡方式有两种:服务端负载均衡、客户端负载均衡


Ribbon 可以与 RestTemplate(Rest 模板)配合使用,以实现微服务之间的调用
示例:
建立C端API工程customer-api
4.0.0 com.hqyj SpringCloud 0.0.1-SNAPSHOT customer-api customer-api customer-api 1.8 8 8 org.projectlombok lombok true org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime true org.springframework.boot spring-boot-starter-test test junit junit 4.12 org.springframework springloaded 1.2.8.RELEASE org.springframework.cloud spring-cloud-starter-netflix-eureka-client com.hqyj common-api 0.0.1-SNAPSHOT 
server:
  port: 80
eureka:
  client:
    register-with-eureka: false #本微服务为服务消费者,不需要将自己注册到服务注册中心
    fetch-registry: true  #本微服务为服务消费者,需要到服务注册中心搜索服务
    service-url:
      defaultZone: http://localhost:7001/eureka
      
 
配置RestTemplate、开启负载均衡
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;
/***
 * @title bean配置类
 * @desctption 配置RestTemplate、开启负载均衡
 * @author kelvin
 * @create 2023/5/11 14:33
 **/
@Configuration
public class ConfigBean {
    @Bean //将 RestTemplate 注入到容器中
    @LoadBalanced //在客户端使用 RestTemplate 请求服务端时,开启负载均衡(Ribbon)
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}
 
import com.hqyj.common.model.UserInfo; import java.util.List; /*** * @title 用户服务 接口 * @desctption 用户服务 * @author kelvin * @create 2023/5/11 14:22 **/ public interface UserConsumerService { /** * 获取用户信息列表 * @return */ public ListuserInfoList(); } 
import com.hqyj.common.model.UserInfo;
import com.hqyj.customerapi.service.UserConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/***
 * @title 用户服务 实现类
 * @desctption 用户服务
 * @author kelvin
 * @create 2023/5/11 14:22
 **/
@Service
public class UserConsumerServiceImpl implements UserConsumerService {
    private String REST_URL_PROVIDER_PREFIX = "http://USER-SERVICE";
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 获取用户信息列表
     * @return
     */
    @Override
    public List userInfoList() {
        return this.restTemplate.getForObject(this.REST_URL_PROVIDER_PREFIX + "/user/userInfoList",List.class);
    }
}
  
import com.hqyj.common.model.UserInfo;
import com.hqyj.customerapi.service.UserConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/***
 * @title UserConsumerController
 * @desctption 用户控制层
 * @author kelvin
 * @create 2023/5/11 14:22
 **/
@RestController
@RequestMapping("/user")
public class UserConsumerController {
    @Autowired
    private UserConsumerService userConsumerService;
    @GetMapping("/userInfoList")
    public List userInfoList(){
        return userConsumerService.userInfoList();
    }
}
  
在公共模块common-api里面添加DTO
import lombok.Data; /*** * @title 统一返回格式类 * @param* @desctption 统一返回格式 * @author kelvin * @create 2023/5/11 14:28 **/ @Data public class ResponseDTO { /** * 返回编码 */ private Integer code; /** * 统一返回消息 */ private String message; /** * 统一返回数据体 */ private T data; } 
实现 ResponseBodyAdvice接口
import com.hqyj.common.dto.ResponseDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; /*** * @title 统一异常处理类 * @desctption 统一异常处理 * @author kelvin * @create 2023/5/11 14:33 **/ @RestControllerAdvice(basePackages = "com.hqyj.customerapi.controller") @Slf4j public class ControllerResponseAdvice implements ResponseBodyAdvice
需要上一章节的2个项目先运行

访问地址:http://localhost/user/userInfoList

在以前的分布式项目里,我们使用zookeeper、redis等来存放服务注册信息,在客户端调用服务时,需要自己手动获取可用服务清单,使用起来非常麻烦,对初级开发人员特别不友好,一不小心就犯错,比如zookeeper依赖版本冲突、zookeeper\redis集群地址填写错误、zookeeper\redis配置项缺失等。
Ribbon的出现解决了上述部分问题,而且Ribbon属于Netflix生态里的组件,与Eureka可以很好的集成起来组合使用,非常方便。