系列文章目录
第一章 Java线程池技术应用
第二章 CountDownLatch和Semaphone的应用
第三章 Spring Cloud 简介
第四章 Spring Cloud Netflix 之 Eureka
第四章 Spring Cloud Netflix 之 Ribbon
文章目录
前言
Spring Cloud Ribbon 是一套基于 Netflix Ribbon 实现的客户端负载均衡和服务调用工具,其主要功能是提供客户端的负载均衡算法和服务调用。
今天我们以电商微服务为例,来讲解Eureka 、Ribbon在微服务治理方面的实战应用。
1、负载均衡
负载均衡(Load Balance) ,简单点说就是将用户的请求平摊分配到多个服务器上运行,以达到扩展服务器带宽、增强数据处理能力、增加吞吐量、提高网络的可用性和灵活性的目的。
常见的负载均衡方式有两种:服务端负载均衡、客户端负载均衡
1.1、服务端负载均衡
1.2、客户端负载均衡
2、Ribbon实现服务间调用
Ribbon 可以与 RestTemplate(Rest 模板)配合使用,以实现微服务之间的调用
示例:
建立C端API工程customer-api
2.1、pom.xml配置
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hqyj</groupId><artifactId>SpringCloud</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>customer-api</artifactId><name>customer-api</name><description>customer-api</description><properties><java.version>1.8</java.version><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--devtools 开发工具--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><!--Spring Boot 测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--junit 测试--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><!-- 修改后立即生效,热部署 --><dependency><groupId>org.springframework</groupId><artifactId>springloaded</artifactId><version>1.2.8.RELEASE</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>com.hqyj</groupId><artifactId>common-api</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies></project>
2.2、application.yml配置
server:port:80eureka:client:register-with-eureka:false#本微服务为服务消费者,不需要将自己注册到服务注册中心fetch-registry:true#本微服务为服务消费者,需要到服务注册中心搜索服务service-url:defaultZone: http://localhost:7001/eureka
2.3、bean配置类
配置RestTemplate、开启负载均衡
importorg.springframework.cloud.client.loadbalancer.LoadBalanced;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.client.RestTemplate;/***
* @title bean配置类
* @desctption 配置RestTemplate、开启负载均衡
* @author kelvin
* @create 2023/5/11 14:33
**/@ConfigurationpublicclassConfigBean{@Bean//将 RestTemplate 注入到容器中@LoadBalanced//在客户端使用 RestTemplate 请求服务端时,开启负载均衡(Ribbon)publicRestTemplategetRestTemplate(){returnnewRestTemplate();}}
2.4、编写调用Eureka的代码
2.4.1、定义用户服务接口
importcom.hqyj.common.model.UserInfo;importjava.util.List;/***
* @title 用户服务 接口
* @desctption 用户服务
* @author kelvin
* @create 2023/5/11 14:22
**/publicinterfaceUserConsumerService{/**
* 获取用户信息列表
* @return
*/publicList<UserInfo>userInfoList();}
2.4.2、编写用户服务实现类
importcom.hqyj.common.model.UserInfo;importcom.hqyj.customerapi.service.UserConsumerService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.web.client.RestTemplate;importjava.util.List;/***
* @title 用户服务 实现类
* @desctption 用户服务
* @author kelvin
* @create 2023/5/11 14:22
**/@ServicepublicclassUserConsumerServiceImplimplementsUserConsumerService{privateStringREST_URL_PROVIDER_PREFIX="http://USER-SERVICE";@AutowiredprivateRestTemplate restTemplate;/**
* 获取用户信息列表
* @return
*/@OverridepublicList<UserInfo>userInfoList(){returnthis.restTemplate.getForObject(this.REST_URL_PROVIDER_PREFIX+"/user/userInfoList",List.class);}}
2.4.3、编写用户服务控制层代码
importcom.hqyj.common.model.UserInfo;importcom.hqyj.customerapi.service.UserConsumerService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.List;/***
* @title UserConsumerController
* @desctption 用户控制层
* @author kelvin
* @create 2023/5/11 14:22
**/@RestController@RequestMapping("/user")publicclassUserConsumerController{@AutowiredprivateUserConsumerService userConsumerService;@GetMapping("/userInfoList")publicList<UserInfo>userInfoList(){return userConsumerService.userInfoList();}}
2.4.4、统一返回结果
在公共模块common-api里面添加DTO
importlombok.Data;/***
* @title 统一返回格式类
* @param <T>
* @desctption 统一返回格式
* @author kelvin
* @create 2023/5/11 14:28
**/@DatapublicclassResponseDTO<T>{/**
* 返回编码
*/privateInteger code;/**
* 统一返回消息
*/privateString message;/**
* 统一返回数据体
*/privateT data;}
2.4.5、统一异常处理
实现 ResponseBodyAdvice接口
importcom.hqyj.common.dto.ResponseDTO;importlombok.extern.slf4j.Slf4j;importorg.springframework.core.MethodParameter;importorg.springframework.http.MediaType;importorg.springframework.http.converter.HttpMessageConverter;importorg.springframework.http.server.ServerHttpRequest;importorg.springframework.http.server.ServerHttpResponse;importorg.springframework.web.bind.annotation.ExceptionHandler;importorg.springframework.web.bind.annotation.RestControllerAdvice;importorg.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;/***
* @title 统一异常处理类
* @desctption 统一异常处理
* @author kelvin
* @create 2023/5/11 14:33
**/@RestControllerAdvice(basePackages ="com.hqyj.customerapi.controller")@Slf4jpublicclassControllerResponseAdviceimplementsResponseBodyAdvice<Object>{@Overridepublicbooleansupports(MethodParameter returnType,Class<?extendsHttpMessageConverter<?>> converterType){//true为织入通知returntrue;}@OverridepublicObjectbeforeBodyWrite(Object body,MethodParameter returnType,MediaType selectedContentType,Class<?extendsHttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request,ServerHttpResponse response){ResponseDTO<Object> objectResponseDTO =newResponseDTO<>();
objectResponseDTO.setCode(200);
objectResponseDTO.setData(body);return objectResponseDTO;}/**
* 统一异常处理
* @param e
* @return
*/@ExceptionHandler(value =Exception.class)publicObjectexception(Exception e){
log.error("系统异常",e);ResponseDTO<Object> objectResponseDTO =newResponseDTO<>();
objectResponseDTO.setCode(500);
objectResponseDTO.setMessage("系统异常");return objectResponseDTO;}}
2.5、启动项目,访问接口
2.5.1、启动项目
需要上一章节的2个项目先运行
2.5.2、访问接口
访问地址:http://localhost/user/userInfoList
总结
在以前的分布式项目里,我们使用zookeeper、redis等来存放服务注册信息,在客户端调用服务时,需要自己手动获取可用服务清单,使用起来非常麻烦,对初级开发人员特别不友好,一不小心就犯错,比如zookeeper依赖版本冲突、zookeeper\redis集群地址填写错误、zookeeper\redis配置项缺失等。
Ribbon的出现解决了上述部分问题,而且Ribbon属于Netflix生态里的组件,与Eureka可以很好的集成起来组合使用,非常方便。
版权归原作者 青花锁 所有, 如有侵权,请联系我们删除。