文章目录
- 一、SpringCloud介绍
- 二、SpringCloud子项目
- 三、Spring Cloud实战教程
- 1.搭建Springboot父子项目
- 2.Feign/Ribbon/OpenFeign
- (1)概念介绍
- (2)OpenFeign的基本使用方法
- 3.Hystrix
- (1)服务雪崩解决方案
- (2)Hystrix使用方法
- 4.Eureka/Nacos
- (1)常用的几种注册中心的区别
- Ⅰ.Eureka与Zookeeper
- Ⅱ.Eureka与Nacos
- (2)Eureka搭建使用
- (3)Nacos搭建使用
- a.Nacos单机+openFiegn+Hystrix
- b.Nacos集群+nginx负载均衡
- 5.Zuul
- (1)Zuul概念介绍
- (2)使用教程
- 6.SpringSecurity/SpringCloudSecurity
- (1)概念介绍
- (2)使用教程
- 1)SpringSecurity
- 2) SpringSecurity + Oauth2 + redis
- 四、SpringCloud常见报错解决
- 1.SpringBoot和SpringCloud版本对应错误
- 2.Eureka常见报错解决
- 3.Nacos常见报错解决(windows版)
- 4.Hystrix常见报错解决
- 5.SpringSecurity报错解决
- 6.Zuul报错解决
一、SpringCloud介绍
1.概念:Spring cloud 是一系列框架的有序集合。它利用 spring boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 spring boot 的开发风格做到一键启动和部署。
2.优缺点(主要针对微服务)
(1)优点
①每个服务足够内聚,足够小,代码容易理解、开发效率提高;
②服务之间可以独立部署,微服务架构让持续部署成为可能;
③精细度业务控制,每个服务可以各自进行负载均衡扩展和数据库扩展,而且,每个服务可以根据自己的需要部署到合适的硬件服务器上;
④容易扩大开发团队,可以针对每个服务组件开发团队;
⑤提高容错性,一个服务的内存泄露并不会让整个系统瘫痪;
⑥每个服务可以用不同的技术开发,系统不会被长期限制在某个技术栈上。
(2)缺点
①开发人员要处理分布式系统的复杂性:
设计服务之间的通信机制,需要考虑分布式事务等问题;
涉及多个服务直接的自动化测试;
服务管理的复杂性(PS:现在docker的出现适合解决这个问题);
②对于业务数据和处理能力不是很明确的创业公司,不适合微服务架构模式,这时候最重要的是快速开发、快速部署、快速试错。
3.应用场景
适合业务复杂度较大、并发量较高的场景
4.SpringCloud与Dubbo对比
(1)架构完整度上,Dubbo只有服务注册/服务治理(zookeeper)两个模块,SpringCloud已经有二十多个模块,而且还在增加;
(2)SpringCloud的社区活跃度高;但Dubbo有高质量的中文文档
(3)Dubbo服务间的通讯采用的RPC,SpringCloud则是Http的Rset,RPC对业务接口有强依赖性,需要通讯双方有一样的接口,REST更为轻量化,只通过一个约定进行规范,不存在代码间的耦合。
二、SpringCloud子项目
SpringCloud的子项目一直在持续更新,这里我把SpringCloud中文网首页的直接放上来了。
详情参照:https://www.springcloud.cc/
1.Spring Cloud Config(Spring)
配置管理工具包,让你可以把配置放到远程服务器,集中化管理集群配置,目前支持本地存储、Git以及Subversion。
2.Spring Cloud Bus(Spring)
事件、消息总线,用于在集群(例如,配置变化事件)中传播状态变化,可与Spring Cloud Config联合实现热部署。
3.Eureka(Netflix)
云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。
4.Hystrix(Netflix)
熔断器,容错管理工具,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。
5.Zuul(Netflix)
Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。
6.Archaius(Netflix)
配置管理API,包含一系列配置管理API,提供动态类型化属性、线程安全配置操作、轮询框架、回调机制等功能。
7.Consul(HashiCorp)
封装了Consul操作,consul是一个服务发现与配置工具,与Docker容器可以无缝集成。
8.Spring Cloud for Cloud Foundry(Pivotal)
通过Oauth2协议绑定服务到CloudFoundry,CloudFoundry是VMware推出的开源PaaS云平台。
9.Spring Cloud Sleuth(Spring)
日志收集工具包,封装了Dapper和log-based追踪以及Zipkin和HTrace操作,为SpringCloud应用实现了一种分布式追踪解决方案。
10.Spring Cloud Data Flow(Pivotal)
大数据操作工具,作为Spring XD的替代产品,它是一个混合计算模型,结合了流数据与批量数据的处理方式。
11.Spring Cloud Security(Spring)
基于spring security的安全工具包,为你的应用程序添加安全控制。
12.Spring Cloud Zookeeper(Spring)
操作Zookeeper的工具包,用于使用zookeeper方式的服务发现和配置管理。
13.Spring Cloud Stream(Spring)
数据流操作开发包,封装了与Redis,Rabbit、Kafka等发送接收消息。
14.Spring Cloud CLI(Spring)
基于 Spring Boot CLI,可以让你以命令行方式快速建立云组件。
15.Ribbon(Netflix)
提供云端负载均衡,有多种负载均衡策略可供选择,可配合服务发现和断路器使用。
16.Turbine(Netflix)
Turbine是聚合服务器发送事件流数据的一个工具,用来监控集群下hystrix的metrics情况。
17.Feign(OpenFeign)
Feign是一种声明式、模板化的HTTP客户端。
18.Spring Cloud Task(Spring)
提供云端计划任务管理、任务调度。
19.Spring Cloud Connectors(Spring)
便于云端应用程序在各种PaaS平台连接到后端,如:数据库和消息代理服务。
20.Spring Cloud Cluster(Spring)
提供Leadership选举,如:Zookeeper, Redis, Hazelcast, Consul等常见状态模式的抽象和实现。
21.Spring Cloud Starters(Pivotal)
Spring Boot式的启动项目,为Spring Cloud提供开箱即用的依赖管理。
三、Spring Cloud实战教程
这里我把部分代码传到github上了:https://github.com/tttalkR9/cloud/tree/cloud
1.搭建Springboot父子项目
(1)首先创建一个File-New-Project选择Spring Initializr,JDK你们可以选择1.8的
(2)修改项目名称,我这里叫springcloud
(3)选择一下基础依赖,这里选择web-spring web,右上角可以修改springboot版本。
(4)然后一个springboot基础的父项目就创建成功了
(5)右击项目,New-Module,同样选择Spring Initializr,项目名称为user,跟刚刚不同的是,我们这里不选择web了,可以直接从父项目获得web的依赖
(6)修改父项目的pom文件,添加packaging的方式和modules
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<modules>
<module>user</module>
</modules>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(7)修改子项目的pom文件
将以下父项目的配置放到子项目的parent标签中,并将子项目中多余的依赖删掉
<groupId>com.example</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
最后子项目的pom.xml如下:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<!--org.springframework.boot
spring-boot-starter-parent
2.6.3
<!– lookup parent from repository –>-->
<groupId>com.example</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>user</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<!--
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(8)添加controller文件,将properties文件替换成yml文件,项目结构如下:
(9)UserController.java和application.yml代码如下:
UserController.java
package com.example.user.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalTime;
import java.util.List;
@Controller
public class UserController {
@RequestMapping(value="/test")
@ResponseBody
public String test(){
return "test111";
}
}
application.yml
server:
port: 8030
spring:
application:
name: user-test
(10)右击启动UserApplication,进入http://localhost:8030/test,看到test111则验证成功
2.Feign/Ribbon/OpenFeign
(1)概念介绍
①Feign:声明式 REST 客户端–Feign 通过使用 JAX-RS(就是一种使用注解来实现 RESTful 的技术)或 SpringMVC 注解的装饰方式,生成接口的动态实现。旨在自动封装服务调用客户端,减少代码开发量
微服务中调用接口常见方式:
Ⅰ.通过http方式进行直接调用:即通过http+port的方式调用,可以使用okhttp、httpclient等进行接口的调用与解析,需要关注接口数据流、接口的数据转换等。
这种方式的缺点:接口调用有单点故障,对接口调用量大的情况没有熔断机制保护系统,防止雪崩效应。
Ⅱ.后端架设nginx服务做负载均衡。接口部署多路,此方式可避免单点故障但是要实现熔断机制等比较复杂,如:可以使用nginx+lua实现,或在代码层面实现限流机制算法。
Ⅲ.dubbo等其他服务治理架构方式请自行查阅资料。
Ⅳ.使用springcloud 家族的feign来实现接口调用。此方式可以解决单点故障和限流熔断,执行服务降级。
②Ribbon:实现负载均衡,从一个服务的多台机器中选择一台。
Nginx与Ribbon:
1)Nginx 是客户端所有请求统一交给 nginx,由 nginx 进行实现负载均衡请求转发,属于服务器端负载均衡。既请求由 nginx 服务器端进行转发。
2)Ribbon 是从 eureka 注册中心服务器端上获取服务注册信息列表,缓存到本地,然后在本地实现轮询负载均衡策略。
3)Nginx 适合于服务器端实现负载均衡 比如 Tomcat ,Ribbon 适合与在微服务中 RPC 远程调用实现本地服务负载均衡,比如 Dubbo、SpringCloud 中都是采用本地负载均衡。
Ribbon算法:实现Irule接口(choose方法),自带七种算法。
(1)RoundRobinRule:轮询;(默认)
(2)RandomRule:随机;
(3)AvailabilityFilteringRule:会先过滤掉由于多次访问故障而处于断路器状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问;
(4)WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应时间越快的服务权重越大被选中的概率越大。刚启动时如果统计信息不足,则使用RoundRobinRule(轮询)策略,等统计信息足够,会切换到WeightedResponseTimeRule;
(5)RetryRule:先按照RoundRobinRule(轮询)策略获取服务,如果获取服务失败则在指定时间内进行重试,获取可用的服务;
(6)BestAvailableRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务;
(7)ZoneAvoidanceRule:复合判断Server所在区域的性能和Server的可用性选择服务器。
③OpenFeign:Feign的强化版,内置了ribbon,简化了Eureka和Ribbon的使用。
(2)OpenFeign的基本使用方法
后面nacos的使用中会整合Feign+hystrix,有完整的代码实例,这里就只做介绍不贴代码
①首先,在pom.xml中引入openfeign和nacos的依赖
②在nacos注册中心端提供一个可以调用的接口,并在application中添加注释@EnableDiscoveryClient
③在nacosclient客户端入口建立一个接口,@FeignClient括号里填写的是注册中心的application-name(application.yml中配置的),然后在controller中调用这个客户端。application中添加注解@EnableDiscoveryClient和@EnableFeignClients
3.Hystrix
(1)服务雪崩解决方案
介绍Hystrix前,我们先了解一下它产生的背景–服务雪崩。
服务雪崩:一个服务失败(调用时间过长或失败),导致整条链路的服务都失败的情形,我们称之为服务雪崩。
解决服务雪崩的方式有下面几种:
1)应用扩容:加机器、升级硬件
2)流量控制: 限流(超出限定流量,返回让用户稍后再试)
3)缓存:将用户访问量大的数据放入缓存中,减少数据库访问。
4)服务降级:
①当下游的服务响应过慢,下游服务主动停掉一些不太重要的业务,释放出服务器资源,增加响应速度
②当下游的服务因为某种原因不可用,上游主动调用本地的一些降级逻辑,避免卡顿,迅速返回给用户
5) 服务熔断:不调用该失败的服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用
而Hystrix的出现为微服务提供了服务降级与熔断的方案。
(2)Hystrix使用方法
有两种方式实现,一个是通过Feign内置的hystrix实现:
1、导入依赖spring-cloud-starter-hystrix
2、启动类开启hystrix支持@EnableHystrix
3、配置yml文件feign.hystrix.enabled=true
4、实现FeignClient接口或FallbackFactory接口
另一种是通过注解@HystrixCommand完成,属于方法级别的降级,后面nacos的使用有代码实例:
1、导入依赖spring-cloud-starter-hystrix
2、启动类开启hystrix支持@EnableHystrix
3、在方法上添加注解@HystrixCommand并配置降级后的方法
4.Eureka/Nacos
(1)常用的几种注册中心的区别
Ⅰ.Eureka与Zookeeper
①Eureka常用于SpringCloud项目,Zookeeper常用于dubbo
②ZooKeeper保证的是CP(一致、分区容错但不保证可用),Eureka保证的是AP(可用、分区容错但不保证一致)
ZooKeeper在选举期间注册服务瘫痪,虽然服务最终会恢复,但是选举期间不可用的
Eureka各个节点是平等关系,只要有一台Eureka就可以保证服务可用,而查询到的数据并不是最新的
③ZooKeeper有Leader和Follower角色,Eureka各个节点平等
④ZooKeeper采用过半数存活原则,Eureka采用自我保护机制解决分区问题
Eureka 自我保护机制:通过在Eureka Server配置如下参数,可启动保护机制。
eureka.server.enable-self-preservation=true
它的原理是,当Eureka Server节点在短时间内丢失过多的客户端时(可能发送了网络故障),那么这个节点将进入自我保护模式,不再注销任何微服务,当网络故障回复后,该节点会自动退出自我保护模式。
Ⅱ.Eureka与Nacos
参考:https://www.cnblogs.com/huangwentian/p/14504473.html
总的来说,目前Nacos的功能更强大一些,Nacos = Spring Cloud Eureka + Spring Cloud Config +Spring Cloud Bus,不需要为配置中心新增集群,不需要MQ实现就能实现配置的中心动态刷新,如果考虑引入阿里巴巴生态,是一个不错的选择;
但是Eureka起步比较早,属于Spring Cloud原生全家桶,短期内更加稳定一些。
Spring Cloud Config:是一种用来动态获取Git、SVN、本地的配置文件的一种工具,为分布式系统中的外部配置提供服务器和客户端支持。官方使用说明文档:https://www.springcloud.cc/spring-cloud-config.html
Springcloud Bus:是springcloud中消息总线。用来将分布式系统的节点与轻量级消息系统链接起来,在微服务系统中实现远端配置更新时通过广播形式通知所有客户端刷新配置信息,避免手动重启服务的工作。常结合RabbitMq和Kafka使用。官方文档参考:https://www.springcloud.cc/spring-cloud-bus.html
(2)Eureka搭建使用
Ⅰ.新建子模块eureka,这里新建的是注册中心,后面还需要个客户端去调用,建立方法在上面介绍过了
Ⅱ.在父项目的pom文件添加相关依赖,主要是springcloud的依赖和eureka的依赖等,注意版本。修改后文件如下
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<modules>
<module>user</module>
<module>eureka</module>
</modules>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2021.0.1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</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>
Ⅲ.在子项目中新添加application.yml和修改EurekaApplication、pom.xml,项目结构如下
pom.xml:主要是修改parent标签
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.example</groupId>
<artifactId>eureka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>