文章目录
- Spring Cloud Alibaba
- 1 介绍
- 2 Nacos(注册中心和配置中心)
- 2.1 示例
- 3 Sentinel(流量控制和熔断降级)
- 3.1 流量控制示例
- 4 GateWay
- 4.1 断言
- 4.2 过滤器
- 4.2.1 局部过滤器
- 4.2.2 全局过滤器
- 4.3 网关限流
- 5 链路追踪Sleuth
Spring Cloud Alibaba
1 介绍
Spring Cloud Alibaba 是 Spring Cloud 的一个子项目,它为基于 Spring Cloud 的微服务架构提供了丰富的生态系统和工具,同时与阿里巴巴的一些开源产品(如 Nacos、Sentinel 等)深度集成,以提供更全面的解决方案。
以下是 Spring Cloud Alibaba 的一些主要组件和特性:
-
Nacos(注册中心和配置中心): Nacos 是一个动态服务发现、配置管理和服务管理平台。Spring Cloud Alibaba 使用 Nacos 作为注册中心和配置中心,使得微服务实例的注册、发现和配置管理更加方便。
-
Sentinel(流量控制和熔断降级): Sentinel 是一种流量控制、熔断降级的解决方案,可以保障微服务的稳定性。Spring Cloud Alibaba 集成了 Sentinel,使得开发者可以在微服务中方便地实现流量控制、熔断降级等功能。
-
RocketMQ(消息驱动): RocketMQ 是阿里巴巴开源的消息中间件,支持分布式事务消息。Spring Cloud Alibaba 集成了 RocketMQ,为微服务架构提供了可靠的消息驱动能力。
-
Seata(分布式事务): Seata 是一款开源的分布式事务解决方案,可以解决微服务架构中分布式事务的问题。Spring Cloud Alibaba 集成了 Seata,为开发者提供了分布式事务的支持。
-
Dubbo(RPC通信): Spring Cloud Alibaba 提供了 Dubbo 的集成,使得开发者可以选择使用 Dubbo 作为微服务之间的 RPC 通信框架。
-
Alibaba Cloud 支持: Spring Cloud Alibaba 与 Alibaba Cloud 紧密集成,提供了对阿里云服务的良好支持,包括配置中心、服务发现、负载均衡等。
总体而言,Spring Cloud Alibaba 通过整合阿里巴巴的开源产品,为基于 Spring Cloud 的微服务架构提供了一套全面的解决方案,帮助开发者构建和管理分布式系统。
2 Nacos(注册中心和配置中心)
Nacos(官方全称是 “Dynamic Naming and Configuration Service”)是阿里巴巴开源的一个动态服务发现、配置管理和服务治理平台。它提供了一种简单而强大的方式,帮助开发者实现微服务架构中的服务注册、发现、配置管理以及动态 DNS 服务等功能。以下是 Nacos 的一些主要特点和功能:
-
服务发现与注册: Nacos允许微服务应用在运行时进行服务注册和发现。服务提供者在启动时向 Nacos 注册自己的服务,而服务消费者可以通过 Nacos 查询并发现可用的服务实例。
-
配置管理: Nacos 提供了一套集中式的配置管理中心,可以帮助开发者集中管理应用的配置信息。Nacos 支持配置的版本管理、灰度发布等功能,使得配置的变更可以动态生效,而无需重启应用。
-
动态 DNS: Nacos 可以作为一个动态 DNS 服务,为微服务提供简单的域名解析。这样,服务之间可以通过域名进行通信,而无需硬编码 IP 地址。
-
服务健康检查: Nacos 通过心跳机制检测服务的健康状态,自动剔除不健康的实例,确保服务的可用性。
-
分布式系统支持: Nacos 是一个分布式系统的基础设施,支持多数据中心、多环境配置管理,以及集群部署,保障了高可用性和可扩展性。
-
开放API和插件扩展: Nacos 提供了 RESTful API,支持通过 API 进行服务注册、发现和配置管理。同时,Nacos 支持插件扩展,使得开发者可以根据自己的需求进行功能扩展。
-
轻量级和易集成: Nacos 设计为轻量级的系统,易于集成到不同的微服务架构中,包括 Spring Cloud、Dubbo、Kubernetes 等。
Nacos(Namespace and Configuration Service)是阿里巴巴开源的一个分布式服务和配置中心。它提供了服务发现、服务健康监测、动态配置管理等功能。以下是一个简单的示例,演示如何使用 Nacos 进行服务注册和配置管理。
2.1 示例
-
下载并启动 Nacos
首先,需要下载并启动 Nacos 服务器。可以从 Nacos GitHub Releases 页面下载最新版本的 Nacos,并按照 Nacos Quick Start 的说明进行部署。
-
创建 Spring Boot 项目
创建一个简单的 Spring Boot 项目,并添加以下 Maven 依赖:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> </dependencies>
-
配置应用信息和 Nacos 配置
在
application.properties
文件中配置应用信息和连接 Nacos 服务的信息:# 应用信息 spring.application.name=application server.port=8080 # Nacos 服务地址 spring.cloud.nacos.discovery.server-addr=localhost:8848
-
创建一个简单的控制器,演示从 Nacos 获取配置和服务注册的信息:
import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DemoController { @Value("${config.info:default-config}") private String configInfo; @GetMapping("/config") public String getConfigInfo() { return "Config Info: " + configInfo; } @GetMapping("/hello") public String sayHello() { return "Hello from Nacos"; } }
-
启动应用
运行应用,应用会自动注册到 Nacos,并提供/config
和/hello
两个接口。可以在 Nacos 控制台中查看注册的服务和配置信息。可以根据 Nacos 文档 进一步了解和使用 Nacos。
3 Sentinel(流量控制和熔断降级)
Sentinel(中文名“哨兵”)是一款由阿里巴巴开源的分布式系统的流量防卫工具。它旨在提供高可用性和高稳定性的服务,通过实时的流量控制、熔断降级、系统负载保护等手段,确保分布式系统在面临大流量、复杂业务场景时仍能保持稳定。
以下是 Sentinel 的一些主要特点和功能:
-
流量控制: Sentinel 提供实时的流量控制功能,可以根据系统的实际情况对入口流量进行控制,防止系统因过载而崩溃。
-
熔断降级: Sentinel 支持熔断降级功能,当系统的某个服务出现问题或不可用时,可以迅速切断对该服务的请求,防止故障蔓延,提高系统的整体稳定性。
-
系统负载保护: Sentinel 可以根据系统负载情况进行保护,避免系统因过度负载而崩溃。它可以通过控制并发线程数、QPS(每秒查询数)等方式来保护系统。
-
实时监控和统计: Sentinel 提供实时的监控和统计功能,可以查看系统的实时运行情况、异常情况和流量等信息,帮助开发者及时发现和解决问题。
-
规则配置: Sentinel 允许开发者通过配置规则来定义流量控制、熔断降级等策略,使其更加灵活适应不同的业务场景。
-
集成 Spring Cloud、Dubbo 等: Sentinel 提供了对多种框架的集成支持,包括 Spring Cloud、Dubbo 等,使其在微服务架构中的使用更加方便。
-
广泛的应用场景: Sentinel 可以应用于各种场景,包括网关限流、服务降级、热点参数限流等,适用于互联网、金融、电商等多个领域。
总体而言,Sentinel 是一款强大的分布式系统流量防卫工具,通过对流量进行实时控制和监控,可以帮助开发者构建稳定、高可用的分布式系统。.
3.1 流量控制示例
cmd命令框执行
java -jar sentinel-dashboard-1.8.1.jar
打开浏览器输入http://localhost:8080:
用户名和密码都为sentinel,输入后跳转,先执行:
点击流控规则
第一次访问:
再次访问,被限流:
4 GateWay
4.1 断言
application.yml添加内容:
predicates:
- Path=/order-ser/** # 如果要访问我们的order-server的微服务,请求路径中必须携带 order-ser
- Before=2023-12-08T00:00:00.000+08:00[Asia/Shanghai] #限制请求时间在 2023-12-08之前
- Method=GET #限制请求方式只能是 GET请求
- Age=20,60 #限制年龄是20岁到60岁可以访问
浏览器输入http://localhost:7000/order-ser/order/prod/1:
发现行不通,由于加入了年龄断言工厂,并且设置可访问的年龄区间为20到60岁。
浏览器输入http://localhost:7000/order-ser/order/prod/1?age=18:
由于18不在规定的年龄范围,所以访问失败,将18改为28:
访问成功!断言设置成功!
4.2 过滤器
4.2.1 局部过滤器
application.yml添加内容:
filters:
- StripPrefix=1 #请求转发之前去掉一层路径
- Log=true,false #日志是否开启
浏览器输入http://localhost:7000/order-ser/order/prod/1?age=28,访问成功后查看控制台打印:
4.2.2 全局过滤器
先注释掉- Age 和 - Log
predicates:
- Path=/order-ser/** # 如果要访问我们的order-server的微服务,请求路径中必须携带 order-ser
- Before=2023-12-08T00:00:00.000+08:00[Asia/Shanghai] #限制请求时间在 2023-12-08之前
- Method=GET #限制请求方式只能是 GET请求
# - Age=20,60 #限制年龄是20岁到60岁可以访问
filters:
- StripPrefix=1 #请求转发之前去掉一层路径
# - Log=true,false #日志是否开启
自定义 AuthGlobalFilter 网关全局过滤器:
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
//全局的权限过滤器
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
//完成逻辑判断
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取浏览器传递过来的token
String token = exchange.getRequest().getQueryParams().getFirst("token");
//实际可以注入 userService.findUserByName()获取token
if(!StringUtils.equals(token,"admin")){ // import org.apache.commons.lang3.StringUtils;
System.out.println("鉴权失败!");
//设置没有权限
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
//就不能往下面的流程
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
//优先级 ,数字越小 级别越高
@Override
public int getOrder() {
return 0;
}
}
浏览器输入http://localhost:7000/order-ser/order/prod/1?token=admin
浏览器输入http://localhost:7000/order-ser/order/prod/1?token=ad:
查看控制台打印:
全局的权限过滤器设置成功!
4.3 网关限流
添加依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
网关限流配置类GatewayConfiguration:
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.*;
//网关限流配置类
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolvers;
this.serverCodecConfigurer = serverCodecConfigurer;
}
//初始化限流的过滤器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)//Spring 4.0中默认情况下遵循从低到高的顺序,即最低值具有高优先级。
//这意味着它们首先出现在列表或数组中
public GlobalFilter sentinelGatewayFilter(){
return new SentinelGatewayFilter();
}
// 配置初始化的限流参数
@PostConstruct
public void initGatewayRules(){
Set<GatewayFlowRule> rules = new HashSet<>();
//添加资源名,对应的是路由id
rules.add(new GatewayFlowRule("order_route").setCount(1).setIntervalSec(1));//统计时间窗口,单位是秒
//加入网关
GatewayRuleManager.loadRules(rules);
}
//配置限流异常处理接口
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(){
return new SentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer);
}
//自定义一个处理异常的页面
@PostConstruct
public void initBlockExceptionHandler(){
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map map = new HashMap();
map.put("code",500012);
map.put("message","接口已被限流了");
return ServerResponse.status(HttpStatus.OK).
contentType(MediaType.APPLICATION_JSON_UTF8).
body(BodyInserters.fromObject(map));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
第一次访问http://localhost:7000/order-ser/order/prod/1:
第二次访问http://localhost:7000/order-ser/order/prod/1:
5 链路追踪Sleuth
SpringCloud Alibaba技术栈中没有自己的链路追踪,可以用 Sleuth + Zipkin 来做链路追踪技术
添加依赖
<!--链路追踪-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
在zipkin-server-2.12.9-exec.jar目录下的cmd命令框执行
java -jar zipkin-server-2.12.9-exec.jar
浏览器访问http://localhost:9411:
然后浏览器访问http://localhost:7000/order-ser/order/prod/1:
刷新http://localhost:9411页面,点击查找:
点击下面的蓝条:
可以看到明显的调用关系,点击任意一个服务(这里点击的是order-server):
可以清晰的看到
zipkin 持久化命令行:
java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=zipkin --MYSQL_USER=root --MYSQL_PASS=kdx010908
在zipkin-server-2.12.9-exec.jar目录下的cmd命令框执行该命令
然后浏览器访问http://localhost:7000/order-ser/order/prod/1,查看数据库表zipkin_spans:
查看数据库表zipkin_annotations:
实现了zipkin 持久化