SpringCloud
- 用于实现“微服务”架构,以及解决其问题的技术生态
微服务
- 简而言之,即模块化开发方式,把之前all in one(一站式)的系统,垂直拆分为若干模块
- 以更好的利用服务器资源,以及更合理的组织开发活动,最终为用户提供更多的价值
微服务架构需要解决的问题
- 多个服务负载均衡的问题
- 服务之间通信的问题
- 服务崩溃的解决方法
微服务常见架构方案
- Spring Cloud NetFlix
- Apache Dubbo Zookeeper
- Spring Cloud Alibaba
技术栈一览
服务条目 | 落地技术 |
---|---|
服务开发 | SpringBoot、SpringMVC |
服务配置与管理 | Netfix的Archaius、阿里的Diamond |
服务注册与发现 | Eureka、Consul、Zookeeper |
服务调用 | Rest、RPC、gRPC |
服务熔断器 | Hystrix、Envoy |
负载均衡 | Ribbon、Nginx |
服务接口调用 | Feign |
消息队列 | Kafka、RabbitMQ、ActiveMQ |
服务配置中心管理 | SpringCloudConfig、Chef |
服务路由(API网关) | Zuul |
服务监控 | Zabbix、Nagios、Metrics、Specataor |
全链路追踪 | Zipkin、Brave、Dapper |
服务部署 | Docker、OpenStack、Kubernetes |
数据流操作开发包 | SpringCloud Stream |
事件消息总线 | SpringCloud Bus |
Spring Cloud NetFlix
- 一个一站式解决方案
- 使用api网关、zuul组件
- 服务之间使用Http通信
- 使用Eureka实现服务注册与发现
- 利用Hystrix实现熔断机制
对比Dubbo
- Dubbo底层是使用Netty这样的NIO框架,是基于TCP协议传输的,配合以Hession序列化完成RPC通信;而SpringCloud是基于Http协议+Rest接口调用远程过程的通信,相对来说,Http请求会有更大的报文,占的带宽也会更多
- REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更为合适
NetFlix项目架构图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pyBAPe4A-1626405799083)(https://img.wenhairu.com/images/2021/05/26/ue9sj.jpg)]
Eureka
概述
- Eureka是Netflix的一个子模块,是一个基于REST的服务,用于定位服务;实现了云端中层服务的发现和故障转移
- 功能类似于【注册中心】,同级产品还有Zookeeper
- 其采用了C-S的架构设计,EurekaServer作为服务注册功能的服务器,即服务注册中心
- 微服务模块使用Eureka的客户端连接到EurekaServer并维持心跳连接,系统维护人员可以通过EurekaServer来监控系统中各个模块是否正常运行
对比Zookeeper
- CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)、P(容错性)
- Zookeeper保证的是CP,而Eureka保证的是AP
- Zookeeper存在一种问题,当集群中master节点故障时,剩余节点会进行master节点的选举,在选举过程中,整个集群都是不可用的,就会导致整个系统的暂时瘫痪
- Eureka集群与Zookeeper不同,不存在master的概念,每个节点都是平等的,都可以进行服务的注册和查询,即只要有一个节点在,就可以保证可用性
Ribbon
概述
- Spring Cloud Ribbon是基于Netfilx Ribbon实现的一套客户端负载均衡工具
- 主要功能是提供客户端的软件负载均衡算法,将NetFilx的中间服务层服务连接在一起
对比Nginx
- Nginx属于集中式的负载均衡,是在消费方和提供方之间独立存在的,负责把访问请求通过某种策略转发至服务的提供方
- Ribbon属于进程式的负载均衡,是将其负载逻辑集成到消费方,消费方从注册中心获知有哪些地址可用,然后自己再从这些地址中选出一个合适的服务器
Feign
- 使编写Java Http客户端变得更容易
- 在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它,即可完成对服务提供方的接口绑定
- Feign集成了Ribbon
- Feign使代码的可读性提高,但会使程序的效率变低!
Hystrix
概述
- 分布式系统中,多个微服务之间调用的时候,如果某个调用的响应时间过长或不可用,对其前面的服务就会占用越来越多的系统资源,进而引起系统崩溃,即“雪崩效应”
- Hystrix(断路器)是一个用于处理分布式系统的延迟和容错的开源库,它能够保证在一个依赖出问题的情况下,不会导致整个服务失败,以提高分布式系统的弹性
- Hystrix的原理:当某个服务单元发生故障后,通过断路器的故障监测,向调用方返回一个服务预期的,可处理的备选响应,而不是长时间的等待或抛出异常
功能
-
服务熔断
当扇出链路的某个微服务不可用时,会熔断该节点微服务的调用,快速返回错误的响应信息。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,一般是5秒内20次调用失败就会启动熔断机制,熔断机制的注解是@HystrixCommand
-
服务降级
当遇到流量洪流时,由于服务器资源有限,可能需要暂停(关闭)一些服务,来为接收洪流或重要性更高的服务腾出空间,而为了避免雪崩以及给在此时访问被关闭服务的客户更好的体验,需要提供【降级服务】。
Zuul
一个路由网关。可以与Eureka整合在一起,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息。
功能
-
路由
将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础
-
过滤
对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础
Config
概述
- 由于微服务系统中有大量的服务,而且每个服务都需要自己的配置文件才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。SpringCloud提供了ConfigServer来解决这个问题
- Config为微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置
- Config分为服务端和客户端两部分。服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密、解密信息等访问接口
- 客户端通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息
- 配置服务器默认采用Git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过Git客户端来方便的管理和访问配置内容
特性
- 集中管理配置文件
- 不同环境,不同配置,动态化的配置更新,分环境部署
- 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
- 当配置发生变动时,服务不需要重启,即可感知到其变化,并应用新的配置
- 将配置信息以REST接口的形式暴露
SpringCloud——Demo
建立一个Maven父工程
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>cn.waston</groupId>
<artifactId>spring_cloud_test</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>spring_cloud_api</module>
<module>spring_cloud_provider</module>
</modules>
<!--打包方式为 pom-->
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
</properties>
<dependencyManagement>
<dependencies>
<!--springCloud的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springBoot的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--Mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
新建子模块spring_cloud_api
pom:
<?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">
<parent>
<artifactId>spring_cloud_test</artifactId>
<groupId>cn.waston</gro