基本概念
SpringCloud是一个基于Spring Boot的微服务架构解决方案,它提供了一系列的工具和组件来帮助开发者构建和管理微服务系统。以下是对SpringCloud中注册中心、OpenFeign、网关、配置中心、服务保护、分布式事务的详细介绍:
注册中心
注册中心是微服务架构中的服务发现机制的核心实现。它允许服务在启动时将自身信息(如IP地址和端口)注册到注册中心,其他服务通过注册中心查找服务实例,实现服务间的动态通信。注册中心的主要功能包括服务注册、服务发现以及健康检查。常见的注册中心组件有Eureka、Consul、Zookeeper和Nacos等。
- Eureka:是Spring Cloud官方推荐的注册中心,具有轻量级实现的特点。Eureka Server作为注册中心,管理所有服务的注册信息;Eureka Client作为微服务的客户端,通过Eureka Server注册和获取服务。
- Consul:支持健康检查和键值存储,功能较为丰富。
- Zookeeper:一致性保证较强,但复杂度较高,适用于对一致性要求较高的场景。
- Nacos:由阿里巴巴开源,支持配置管理和服务发现,是近年来较为流行的注册中心之一。
OpenFeign
OpenFeign是Spring Cloud生态系统中的一个声明式Web服务客户端,它使得编写Web服务客户端变得更加容易。
- 特点:OpenFeign允许开发者通过定义Java接口和使用注解的方式来声明HTTP请求,从而简化了与HTTP服务的交互。开发者只需定义一个接口并使用注解来声明请求参数、请求方式、请求头等信息,OpenFeign会自动生成代理对象来处理HTTP请求。此外,OpenFeign还支持可插拔的编码器和解码器、多种注解以及集成Spring MVC注解等特性。
- 集成:Spring Cloud OpenFeign集成了Eureka、Spring Cloud CircuitBreaker以及Spring Cloud LoadBalancer等组件,以便在使用Feign时提供一个负载均衡的HTTP客户端。
- 使用:在Spring Boot项目中,可以通过添加spring-cloud-starter-openfeign依赖,并在主启动类上添加@EnableFeignClients注解来启用OpenFeign。然后,通过创建一个接口并使用@FeignClient注解来声明远程服务的调用即可。
网关
Spring Cloud Gateway是一个基于Spring和Spring Boot构建的轻量级网关服务,用于构建微服务架构中的API网关。
- 功能:Spring Cloud Gateway支持动态路由、过滤器、负载均衡、集成服务发现以及安全认证等功能。它可以根据不同的请求路径将请求转发到不同的目标服务,并通过过滤器链对请求和响应进行处理和修改。
- 使用:在Spring Boot项目中,可以通过添加spring-cloud-starter-gateway依赖来引入Spring Cloud Gateway。然后,在配置文件中添加路由配置,指定请求的匹配规则和目标服务的转发地址。最后,在主启动类上添加@EnableGateway注解(注意:实际上应为@SpringBootApplication注解,因为Spring Cloud Gateway的自动配置已经包含了网关的启用逻辑)来启用Spring Cloud Gateway的功能。
配置中心
Spring Cloud配置中心(Spring Cloud Config)是用于管理分布式系统中的外部配置的解决方案。
- 功能:Spring Cloud Config提供了服务器端和客户端支持,用于集中化的外部配置。它支持集中管理配置、实时刷新配置、版本管理以及环境隔离等功能。
- 架构:Spring Cloud Config分为Config Server和Config Client两部分。Config Server作为配置服务器,集中管理配置文件,并向客户端提供配置;Config Client作为配置客户端,从配置服务器获取并应用配置。
- 使用:在搭建Config Server时,需要创建一个Spring Boot项目,并添加spring-cloud-config-server等依赖。然后,在配置文件中指定配置文件的存储位置(如Git仓库)。在搭建Config Client时,需要添加spring-cloud-starter-config等依赖,并在bootstrap.yml或application.yml配置文件中指定Config Server的地址和要获取的配置信息。(也可采用Nacos做配置中心)
服务保护
服务保护是微服务架构中保障服务稳定性和可用性的重要手段。Spring Cloud提供了多种服务保护组件和策略,如断路器(Hystrix)、限流器(Sentinel)等。
- 断路器:断路器是一种用于防止分布式系统中出现级联故障的保护机制。当某个服务调用失败或响应时间过长时,断路器会迅速切断对该服务的调用请求,从而避免整个系统崩溃。Spring Cloud Hystrix是一个常用的断路器实现。
- 限流器:限流器用于控制服务的并发请求数量,防止服务因过载而崩溃。通过限制并发请求的数量,可以确保服务在合理的负载范围内运行。Spring Cloud Alibaba Sentinel是一个常用的限流器实现。
分布式事务
分布式事务是指涉及多个数据源或服务的事务处理机制。在微服务架构中,由于服务之间的调用是异步的、去中心化的,因此分布式事务的处理变得尤为复杂。Spring Cloud提供了多种分布式事务解决方案,如基于消息的最终一致性方案(如Seata)、基于数据库的事务管理器(如Atomikos、Bitronix)等。
- Seata:Seata是一款开源的分布式事务解决方案,提供了AT、TCC、SAGA和XA事务模式。它通过全局事务ID和分支事务ID来管理分布式事务的执行和回滚。
- Atomikos:Atomikos是一个提供分布式事务管理的Java库,它支持XA协议和两阶段提交协议(2PC)。通过Atomikos,可以在多个数据源之间实现分布式事务的一致性。
- Bitronix:Bitronix是另一个提供分布式事务管理的Java库,它也支持XA协议和两阶段提交协议。与Atomikos相比,Bitronix具有更轻量级、更易用的特点。
SpringCloud提供了一套完整的微服务架构解决方案,包括注册中心、OpenFeign、网关、配置中心、服务保护以及分布式事务等组件和特性。这些组件和特性相互协作,共同保障了微服务系统的稳定性、可用性和可扩展性。
实战
父maven依赖
java
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.6.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
1、注册中心
bash
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
java
spring:
cloud:
nacos:
server-addr: localhost:8848
2、OpenFeign
bash
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
java
@SpringBootApplication
// 开启
@EnableFeignClients(basePackages = "com.api.client", defaultConfiguration = DefaultFeignConfig.class)
public class Goods {
public static void main(String[] args) {
SpringApplication.run(Goods.class, args);
}
}
java
@FeignClient("cart")
public interface CartClient {
@GetMapping("/cart/ok/{id}")
String ok(@PathVariable("id") Long id);
}
java
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Resource
private CartClient cartClient;
@GetMapping("/ok/{id}")
public String ok(@PathVariable("id") Long id) {
System.out.println(cartClient.ok(id));
return "goods ok " + id;
}
}
默认实现不支持连接池
a. 引入连接池
bash
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
java
feign:
httpclient:
enabled: true
b. 日志
只在FeignClient所在包的日志级别为debug时,才输出日志
- none:不记录日志(默认)
- basic:记录请求方法、URL、响应状态码、执行时间
- headers:在basic基础上,额外记录请求和响应的头信息
- full:记录所有信息
java
public class DefaultFeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
// 请求拦截器
public RequestInterceptor tokenRequestInterceptor() {
return template -> template.header("userId", "900");
}
}
java
@FeignClient(configuration = )也可以配置
3、网关
bash
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
a. 路由
bash
spring:
main:
# 不使用SpringMVC那一套
web-application-type: reactive
cloud:
gateway:
routes:
# 路由规则唯一标识
- id: goods
# 路由目标微服务地址
uri: lb://goods
# 路由判断条件
predicates:
# 路由规则名=参数,路由规则名=参数,...,路由规则名=参数(多个)
# 多个也可以使用yaml的列表语法
# - Path=/test1/**
# - Path=/test2/**
- Path=/goods/** # 以此前缀即符合
# 路由过滤器(处理请求或响应)
filters:
# 过滤器名=参数
- AddRequestHeader=a,b
- id: cart
uri: lb://cart
predicates:
- Path=/cart/**
# 默认过滤器,对所有路由生效
default-filters:
- AddRequestHeader=x,y
# 自定义的
- LogAll=100,200,300


b. 登录校验
java
@Component
// 全局过滤器,作用在所有路由,声明后自动生效
public class GF implements GlobalFilter, Ordered {
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
// 不是调用链最后一个就行
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
/*
参数:
请求上下文,包含整个过滤器链内共享数据
过滤器链,当前过滤器执行完后,要调用过滤器链中的下一个过滤器
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
System.out.println(request.getHeaders());
// 路径格式是否符合
System.out.println(antPathMatcher.match("/goods/**", request.getPath().toString()));
// 新增请求头(可以传递解析出来的用户信息)
exchange = exchange.mutate().request(builder -> builder.header("userId", "90")).build();
// 放行
return chain.filter(exchange);
// 拦截终止
// ServerHttpResponse response = exchange.getResponse();
// return response.setComplete();
}
}
java
@Component
/*
路由过滤器,作用在任意指定的路由,默认不生效,需配置到路由
固定类名后缀,方便配置
*/
public class LogAllGatewayFilterFactory extends AbstractGatewayFilterFactory<LogAllGatewayFilterFactory.ABC> {
public LogAllGatewayFilterFactory() {
// 父类负责读配置
super(ABC.class);
}
// 配置无参只需实现这一个方法就好了,否则需要再实现一个方法,并定义一个构造器
@Override
public GatewayFilter apply(ABC config) {
return new OrderedGatewayFilter((exchange, chain) -> {
System.out.println("路由过滤器执行 " + config);
return chain.filter(exchange);
}, 1);
}
@Override
public List<String> shortcutFieldOrder() {
// 将成员变量名称依次返回,注意顺序,将来读取参数时也按照此顺序
return Arrays.asList("a", "b", "c");
}
// 自定义配置属性,注意成员变量名称
@Data
public static class ABC {
private String a;
private String b;
private String c;
}
}
4、配置中心

bash
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
a. 共享配置
bootstrap.yml
bash
spring:
cloud:
nacos:
server-addr: localhost:8848
config:
# 要读的文件后缀名
file-extension: yaml
# 共享配置
shared-configs:
- data-id: same-config-mvc.yaml
- data-id: same-config-log.yaml
application:
name: goods
b. 配置热更新
spring.application.name(微服务名称) - spring.active.profile(项目环境,可选). file-extension(文件后缀名)
使用@ConfigurationProperties加载属性
c. 网关动态路由
bash
[
{
"id": "goods",
"uri": "lb://goods",
"predicates": [
{
"name": "Path",
"args": {
"_genkey_0": "/goods/**"
}
}
],
"filters": []
}
,
{
"id": "cart",
"uri": "lb://cart",
"predicates": [
{
"name": "Path",
"args": {
"_genkey_0": "/cart/**"
}
}
],
"filters": []
}
]
java
@Component
public class DynamicRouter {
private final Set<String> routeIdSet = new HashSet<>();
@Resource
private NacosConfigManager nacosConfigManager;
@Resource
private RouteDefinitionWriter routeDefinitionWriter;
@Resource
private ApplicationEventPublisher applicationEventPublisher;
@PostConstruct
private void init() throws NacosException {
// 项目启动时,先拉取配置并添加监听器
String config = nacosConfigManager.getConfigService()
.getConfigAndSignListener(
"gateway-dynamic-route.json",
"DEFAULT_GROUP",
5000,
new Listener() {
// 定义一个线程池
@Override
public Executor getExecutor() {
return null;
}
// 当配置变更时,需要做的事情
@Override
public void receiveConfigInfo(String configInfo) {
// 更新路由表
updateRoutes(configInfo);
}
}
);
// 第一次读取到的配置,也需要更新到路由表
updateRoutes(config);
}
private void updateRoutes(String config) {
if (!StringUtils.hasText(config)) {
return;
}
List<RouteDefinition> routeDefinitions = JSON.parseArray(config, RouteDefinition.class);
// 先删旧路由表
for (String i : routeIdSet) {
routeDefinitionWriter.delete(Mono.just(i)).subscribe();
}
// 清空旧路由id集
routeIdSet.clear();
for (RouteDefinition routeDefinition : routeDefinitions) {
// 更新路由表
routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
// 记录路由id,便于下一次更新删除
routeIdSet.add(routeDefinition.getId());
}
// 通知网关更新路由
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(routeDefinitionWriter));
}
}
5、服务保护
-
雪崩:微服务调用链路中某个服务故障,引起整个链路中所有微服务都不可用(级联失败)
-
请求限流:限制访问微服务的请求并发量(流量整形)
-
线程隔离(舱壁模式):限定每个业务能使用的线程数量而将故障业务隔离,避免故障扩散
-
服务熔断:由断路器统计请求异常比或慢调用比,如果超出阈值则熔断业务,拦截该接口的请求;当服务恢复时,断路器会放行访问该服务的请求
-
失败处理:熔断期间,所有请求快速失败,全都走fallback逻辑
bash
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
bash
spring:
cloud:
sentinel:
transport:
# 控制台地址
dashboard: localhost:8080
# 簇点链路中,将请求方式+请求路径作为簇点资源名称(开启请求方式前缀)
http-method-specify: true
a. fallback
bash
feign:
sentinel:
enabled: true
java
public class CartClientFallbackFactory implements FallbackFactory<CartClient> {
@Override
public CartClient create(Throwable cause) {
System.out.println(cause.getMessage());
return id -> "wrong call " + id;
}
}
java
@Bean
public CartClientFallbackFactory cartClientFallbackFactory() {
return new CartClientFallbackFactory();
}
java
@FeignClient(value = "cart", fallbackFactory = CartClientFallbackFactory.class)

6、分布式事务
bash
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
bash
seata:
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace:
group: SEATA_GROUP
application: seata-server
username:
password:
# 事务组名称
tx-service-group: mall
service:
# 事务组与tc集群的映射
vgroup-mapping:
mall: default
# data-source-proxy-mode: XA
data-source-proxy-mode: AT
java
// 全局事务的入口方法添加
@GlobalTransactional
