本文实践了SpringCloud的核心功能,包括基于Eureka实现了服务注册和发现,基于Ribbon实现了客户端负载均衡的Rest远程调用,基于Hystrix实现了请求熔断,服务降级。相关代码已上传到github:https://github.com/leon2016/SpringCloudDemo.git
目录
一、Spring Cloud简介
1、常用的5个组件
2、主要组件
二、springcloud开发环境搭建
三、Eureka作为服务注册与发现的组件
1、Eureka 简介
2、官方架构图
3、工作原理
四、创建Eureka服务注册中心
五、创建多个Eureka服务提供者实例
六、服务注册和发现小结
七、基于Ribbon+rest实现远程调用
1、新建一个消费者module,pom引入ribbon
2、启动类加@LoadBalanced注解实现负载均衡
Ribbon 的运行原理
3、ribbon+rest远程调用开发实例(请求熔断、服务降级)
请求熔断
服务降级
4、远程调用负载均衡及故障转移恢复测试
参考文献
一、Spring Cloud简介
SpringCloud是微服务架构中的集成,将一系列优秀的组件进行了整合。基于SpringBoot构建, 通过简单的注解,就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。它可以将一个完整的应用从数据存储开始垂直拆分成多个不同的服务,每个服务都能独立部署、独立维护、独立扩展,服务与服务间通过诸如RESTful API的方式互相调用。
1、常用的5个组件
- Netflix Eureka - 服务发现
- Netflix Ribbon - 客户端负载均衡
- Netflix Hystrix - 断路器
- Netflix Zuul - 服务网关
- Spring Cloud Config - 分布式配置
2、主要组件
本次学习主要涉及了红框中的组件。
二、springcloud开发环境搭建
1、安装jdk
2、安装Tomcat
3、安装配置MAVEN
(1)下载maven:下载完成后解压,放到想放的位置。
(2)配置maven环境变量:/etc/profile
# java,tomcat,maven
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home
CATALINA_HOME=/Library/java/tomcat/apache-tomcat-8.0.50
M2_HOME=/Library/Java/maven/apache-maven-3.5.3
PATH=$JAVA_HOME/bin:$CATALINA_HOME/bin:$M2_HOME/bin:$PATH:.
CLASSPATH=JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export JAVA_HOME
export CATALINA_HOME
export M2_HOME
export PATH
export CLASSPATH
在终端输入 source /etc/profile 以使文件生效。
(3)验证:终端输入: mvn -v
(4)国内配置淘宝镜像:~/.m2/setting.xml
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
4、安装IDE
核心配置:
(1)配置默认jdk:preferences->java->installed jres 选择默认jdk1.8;compiler中level对应选1.8
(2)配置maven:preferences->maven->installations 添加自己安装的maven
三、Eureka作为服务注册与发现的组件
1、Eureka 简介
Eureka 是 Netflix 出品的用于实现服务注册和发现的工具。 Spring Cloud 集成了 Eureka,并提供了开箱即用的支持。其中, Eureka 又可细分为 Eureka Server 和 Eureka Client。
2、官方架构图
3、工作原理
处于不同节点的eureka通过Replicate进行数据同步
- Application Service为服务提供者
- Application Client为服务消费者
- Make Remote Call完成一次服务调用
服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。
当服务注册中心Eureka Server检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为DOWN状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。
服务提供者在启动后,周期性(默认30秒)向Eureka Server发送心跳,以证明当前服务是可用状态。Eureka Server在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例。
四、创建Eureka服务注册中心
下面是关键步骤和配置,详情见源代码:https://github.com/leon2016/SpringCloudDemo.git
1、创建首先创建一个主Maven工程springcloud2020
注意packaging要选择pom.xml
2. pom文件引入依赖
spring Boot版本为2.0.3.RELEASE,Spring Cloud版本为Finchley.RELEASE。这个pom文件作为父pom文件,起到依赖版本控制的作用,其他module工程继承该pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wangang</groupId>
<artifactId>springcloud2020</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>springcloud2020</name>
<description>spring cloud 研究2020</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/>
</parent>
<modules>
<module>eureka-server</module>
<module>service-hi</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.创建module项目eureka-server
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server</artifactId>
<packaging>jar</packaging>
<name>eureka-server</name>
<description>spring cloud 研究2020</description>
<parent>
<groupId>com.wangang</groupId>
<artifactId>springcloud2020</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
4.配置文件
通过eureka.client.registerWithEureka:false和fetchRegistry:false来表明自己是一个eureka server.
5.配置启动类
启动一个服务注册中心,只需要一个注解@EnableEurekaServer,这个注解需要在springboot工程的启动application类上
6.eureka server监控
eureka server 是有界面的,启动工程,打开浏览器访问:
此时,如红框显示,当前没有服务实例注册
五、创建多个Eureka服务提供者实例
1、创建module项目eureka-client
其pom继承父springcoloud2020的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>service-hi</artifactId>
<packaging>jar</packaging>
<name>service-hi</name>
<description>spring cloud 研究2020</description>
<parent>
<groupId>com.wangang</groupId>
<artifactId>springcloud2020</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、配置文件
application.yml:
server:
port: 8762
spring:
application:
name: service-hi
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
3、配置启动类
通过注解@EnableEurekaClient 表明自己是一个eurekaclient
4、eclipse启动两个server-hi实例,访问注册中心
这时候看下图,server-hi已经有两个服务注册成功了。
六、服务注册和发现小结
总结:
(1)Eureka服务端:也称服务注册中心,同其他服务注册中心一样,支持高可用配置。如果Eureka以集群模式部署,当集群中有分片出现故障时,那么Eureka就转入自我保护模式。它允许在分片故障期间继续提供服务的发现和注册,当故障分片恢复运行时,集群中其他分片会把它们的状态再次同步回来
(2)Eureka客户端:主要处理服务的注册与发现。客户端服务通过注解和参数配置的方式,嵌入在客户端应用程序的代码中,在应用程序运行时,Eureka客户端向注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态
(3)Eureka Server的高可用实际上就是将自己作为服务向其他注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用效果
源代码:https://github.com/leon2016/SpringCloudDemo.git
完整目录结构:
问题与解决:
出现下列红框警告的原因:这其实是eureka的自我保护机制导致的。
在默认配置中,Eureka Server在默认90s没有得到客户端的心跳,则注销该实例,但是往往因为微服务跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,但是因为网络分区故障时,Eureka Server注销服务实例则会让大部分微服务不可用,这很危险,因为服务明明没有问题。
为了解决这个问题,Eureka 有自我保护机制,通过在Eureka Server配置如下参数,可启动保护机制
eureka.server.enable-self-preservation=true (默认true,开启)
它的原理是,当Eureka Server节点在短时间内丢失过多的客户端时(可能发送了网络故障),那么这个节点将进入自我保护模式,不再注销任何微服务,当网络故障回复后,该节点会自动退出自我保护模式。
七、基于Ribbon+rest实现远程调用
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括Feign,它也是基于Ribbon实现的工具。
1、新建一个消费者module,pom引入ribbon
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>service-ribbon</artifactId>
<packaging>jar</packaging>
<name>service-ribbon</name>
<description>spring cloud 研究2020</description>
<parent>
<groupId>com.wangang</groupId>
<artifactId>springcloud2020</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
</project>
2、启动类加@LoadBalanced注解实现负载均衡
Ribbon 的运行原理
Ribbon 实现负载均衡,基本用法是注入一个 RestTemplate,并在 RestTemplate 上使用 @LoadBalanced,才能使 RestTemplate 具备负载均衡能力。 @LoadBalanced对应的拦截器实现具体的负载均衡策略。
3、ribbon+rest远程调用开发实例(请求熔断、服务降级)
关键是注入一个restTemplate,通过服务名+接口名调用远程服务,@HystrixCommand实现请求熔断和服务降级。
请求熔断
当Hystrix Command请求后端服务失败数量超过一定比例(默认50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认5秒), 自动切换到半开路状态(HALF-OPEN).这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.
服务降级
Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.告知后面的请求服务不可用了,不要再来了。
server层:
control层:
4、远程调用负载均衡及故障转移恢复测试
实验结果:同一请求多次,会自动分配到不同的服务器;当某一服务器宕机处理中时,该服务器会从eureka注册名单中移除,新请求会转到其他服务器,不会再转到该服务器;当宕机服务器恢复时,会自动重新在服务中心注册,新请求会重新转到该服务器。
参考文献