云原生微服务 第五章 Spring Cloud Netflix Eureka集成负载均衡组件Ribbon
作者:mmseoamin日期:2023-12-05

系列文章目录

第一章 Java线程池技术应用

第二章 CountDownLatch和Semaphone的应用

第三章 Spring Cloud 简介

第四章 Spring Cloud Netflix 之 Eureka

第五章 Spring Cloud Netflix 之 Ribbon

云原生微服务 第五章 Spring Cloud Netflix Eureka集成负载均衡组件Ribbon,在这里插入图片描述,第1张


文章目录

  • 系列文章目录
    • @[TOC](文章目录)
    • 前言
    • 1、负载均衡
      • 1.1、服务端负载均衡
      • 1.2、客户端负载均衡
      • 2、Ribbon实现服务间调用
        • 2.1、pom.xml配置
        • 2.2、application.yml配置
        • 2.3、bean配置类
        • 2.4、编写调用Eureka的代码
          • 2.4.1、定义用户服务接口
          • 2.4.2、编写用户服务实现类
          • 2.4.3、编写用户服务控制层代码
          • 2.4.4、统一返回结果
          • 2.4.5、统一异常处理
          • 2.5、启动项目,访问接口
            • 2.5.1、启动项目
            • 2.5.2、访问接口
            • 总结

              前言

              Spring Cloud Ribbon 是一套基于 Netflix Ribbon 实现的客户端负载均衡和服务调用工具,其主要功能是提供客户端的负载均衡算法和服务调用。

              今天我们以电商微服务为例,来讲解Eureka 、Ribbon在微服务治理方面的实战应用。

              云原生微服务 第五章 Spring Cloud Netflix Eureka集成负载均衡组件Ribbon,在这里插入图片描述,第2张

              云原生微服务 第五章 Spring Cloud Netflix Eureka集成负载均衡组件Ribbon,在这里插入图片描述,第1张

              1、负载均衡

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

              常见的负载均衡方式有两种:服务端负载均衡、客户端负载均衡

              1.1、服务端负载均衡

              云原生微服务 第五章 Spring Cloud Netflix Eureka集成负载均衡组件Ribbon,在这里插入图片描述,第4张

              1.2、客户端负载均衡

              云原生微服务 第五章 Spring Cloud Netflix Eureka集成负载均衡组件Ribbon,在这里插入图片描述,第5张

              2、Ribbon实现服务间调用

              Ribbon 可以与 RestTemplate(Rest 模板)配合使用,以实现微服务之间的调用

              示例:

              建立C端API工程customer-api

              2.1、pom.xml配置

              
              
                  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
                      
                  
              
              

              2.2、application.yml配置

              server:
                port: 80
              eureka:
                client:
                  register-with-eureka: false #本微服务为服务消费者,不需要将自己注册到服务注册中心
                  fetch-registry: true  #本微服务为服务消费者,需要到服务注册中心搜索服务
                  service-url:
                    defaultZone: http://localhost:7001/eureka
                    
              

              2.3、bean配置类

              配置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();
                  }
              }
              

              2.4、编写调用Eureka的代码

              2.4.1、定义用户服务接口

              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 List userInfoList();
              }
              

              2.4.2、编写用户服务实现类

              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);
                  }
              }
              

              2.4.3、编写用户服务控制层代码

              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();
                  }
              }
              

              2.4.4、统一返回结果

              在公共模块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;
              }
              

              2.4.5、统一异常处理

              实现 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 {
                  @Override
                  public boolean supports(MethodParameter returnType, Class> converterType) {
                      //true为织入通知
                      return true;
                  }
                  @Override
                  public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
                      ResponseDTO objectResponseDTO = new ResponseDTO<>();
                      objectResponseDTO.setCode(200);
                      objectResponseDTO.setData(body);
                      return objectResponseDTO;
                  }
                  /**
                   * 统一异常处理
                   * @param e
                   * @return
                   */
                  @ExceptionHandler(value = Exception.class)
                  public Object exception(Exception e){
                      log.error("系统异常",e);
                      ResponseDTO objectResponseDTO = new ResponseDTO<>();
                      objectResponseDTO.setCode(500);
                      objectResponseDTO.setMessage("系统异常");
                      return objectResponseDTO;
                  }
              }
               
              

              2.5、启动项目,访问接口

              2.5.1、启动项目

              需要上一章节的2个项目先运行

              云原生微服务 第五章 Spring Cloud Netflix Eureka集成负载均衡组件Ribbon,在这里插入图片描述,第6张

              2.5.2、访问接口

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

              云原生微服务 第五章 Spring Cloud Netflix Eureka集成负载均衡组件Ribbon,在这里插入图片描述,第7张


              总结

              在以前的分布式项目里,我们使用zookeeper、redis等来存放服务注册信息,在客户端调用服务时,需要自己手动获取可用服务清单,使用起来非常麻烦,对初级开发人员特别不友好,一不小心就犯错,比如zookeeper依赖版本冲突、zookeeper\redis集群地址填写错误、zookeeper\redis配置项缺失等。

              Ribbon的出现解决了上述部分问题,而且Ribbon属于Netflix生态里的组件,与Eureka可以很好的集成起来组合使用,非常方便。