Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件-Nacos 、Sentinel等
概述
- Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件。
- 方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
- 依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置。
- 就可以将 Spring Cloud 应用接入阿里分布式应用解决方案,通过阿里中间件来迅速搭建分布式应用系统。
版本介绍
组件关系
依赖关系
Nacos概述
什么是Nacos
- Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集。
- 帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
关键特性
搭建NacosServer
- 官网下载解压启动
- 打开浏览器, 在浏览器当中输入: http://localhost:8848/nacos/
- 账号:nacos
- 密码:nacos
服务注册与发现
工程准备
1.创建父工程 spring-cloud-alibaba-parent ,在父工程当中导入依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.3.RELEASE</version>
</parent>
<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR1</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.1.1.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
2.创建两个子工程 user 与 goods 工程
我创建一个user为例,goods就自己创建了
- 依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>
- controller
@RestController
public class UserController {@RequestMapping("/getUser")public ResponseResult getUser() {return ResponseResult.success("My User");}}
- util
public class ResponseResult extends HashMap {public static String SUCCESS_CODE = "200";public static String ERROR_CODE = "500";public static String DATA_KEY = "data";public static String MSG_KEY = "msg";private ResponseResult() {}public ResponseResult set(String key, Object object) {super.put(key, object);return this;}private static ResponseResult newResponseResult() {return new ResponseResult();}public static ResponseResult success() {return ResponseResult.newResponseResult().set("code", ResponseResult.SUCCESS_CODE).set(ResponseResult.MSG_KEY, "操作成功");}public static ResponseResult success(String msg) {return ResponseResult.newResponseResult().set("code", ResponseResult.SUCCESS_CODE).set(ResponseResult.MSG_KEY, msg);}public static ResponseResult success(String msg, Object object) {return ResponseResult.newResponseResult().set("code", ResponseResult.SUCCESS_CODE).set(ResponseResult.MSG_KEY, msg).set(ResponseResult.DATA_KEY, object);}public ResponseResult data(Object obj) {return this.set("data", obj);}public static ResponseResult error() {return ResponseResult.newResponseResult().set(ResponseResult.MSG_KEY, "操作失败").set("code", ResponseResult.ERROR_CODE);}public static ResponseResult error(String msg) {return ResponseResult.newResponseResult().set(ResponseResult.MSG_KEY, msg).set("code", ResponseResult.ERROR_CODE);}public static ResponseResult error(String msg, Object object) {return ResponseResult.newResponseResult().set(ResponseResult.MSG_KEY, msg).set(ResponseResult.DATA_KEY, object).set("code", ResponseResult.ERROR_CODE);}}
- 启动类
@SpringBootApplication
public class AppUser {public static void main(String[] args) {SpringApplication.run(AppUser.class, args);}
}
- 配置文件 application.yml
logging:level:cn.ddossec: debug # 日志级别
server:port: 5000 # 端口号
spring:application:name: consumption-user # 服务名称
- 在user工程当中添加依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
在启动类上添加注解 @EnableDiscoveryClient
在配置文件添加添加配置
cloud:nacos:discovery:server-addr: localhost:8848 #nacos服务的地址 不要加http
启动工程后, 在nacos当中查询服务列表
使用相同方式 把goods服务注册到nacos上
在 user 工程中通过服务发现调用goods工程
在启动类配置 RestTemplate
@Bean
public RestTemplate restTemplate(){return new RestTemplate();
}
- 服务发现调用
@RestController
public class UserController {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@RequestMapping("/getUser")public ResponseResult getUser() {List<ServiceInstance> instances = discoveryClient.getInstances("provide-goods");ServiceInstance serviceInstance = instances.get(0);System.out.println(serviceInstance);String url = serviceInstance.getUri() + "/getGoods".toString();return ResponseResult.success("调用成功",restTemplate.getForObject(url, Object.class));}}
nacos集群
1.编译源码, 支持mysql8数据库
1.下载nacos源码
2.下载后, 修改源码进行编译,把mysql数据库改为mysql8
修改pom文件修改 MysqlHealthCheckProcessor 导入的包为mysql8的驱动包
修改数据库连接配置为mysql8的配置
db.url.0=jdbc:mysql://11.162.196.161:3306/diamond_devtest?serverTimezone=GMT%2B8&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.url.1=jdbc:mysql://11.163.152.91:3306/diamond_devtest?serverTimezone=GMT%2B8&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
- 进入到源码根目录,使用mvn进行打包
mvn -Prelease-nacos clean install -U -Dmaven.skip.test=true
- 打包后, 找到nacos-1.1.4\distribution\target\nacos-server-1.1.4\nacos\conf
2.在数据库当中创建 nacos_config,导入nacos中sql数据
3.复制3份nacos工程,分别配置信息
- 设置端口号:8849、8850、8851
- 示例
分别设置每一个工程的端口号
设置数据库连接信息
指定数据源为
Mysqlspring.datasource.platform=mysql
数据库实例数量
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=1234
分别设置每一个工程的 application.properties 文件当中进行设置
集群信息
复制一份 cluster.conf.example 文件改为 cluster.conf 配置以下信息
192.168.43.95:8849
192.168.43.95:8850
192.168.43.95:8851
- 192.168.43.95:是本机IP
- 每一份工程复制一份过去就行
4.分别进入到每一份工程bin目录下,修改 startup.cmd
cluster
- 修改完毕后,开始分别启动每一个
5.在nginx当中配置反向代理
upstream nacos {server 169.254.108.9:8849;server 169.254.108.9:8850;server 169.254.108.9:8851;
}
location /nacos {proxy_pass http://nacos/nacos;
}
6.启动 nginx 地址栏访问: http://localhost/nacos/
7.将服务注册到Nacos当中,直接写上nginx的地址
集成Ribbon
使用Ribbon
1.不需要添加依赖
2.在 RestTemplate 上添加注解 @LoadBalanced
3.在调用时, 就可以使用服务名称来进行调用 , 和之前的使用方式 是一样的
@RequestMapping("/getGoods")
public ResponseResult getGoods() {String url = "http://provide-goods/getGoods";return ResponseResult.success("调用成功",restTemplate.getForObject(url, Object.class));
}
默认使用是 轮询 策略
自定义负载均衡策略
配置方式与之前一样
配置懒加载
ribbon:eager-load:enabled: trueclients: provide-goods #多个服务使用逗号隔开
Nacos集成Ribbon,支持权重的负载均衡算法
1.自定义权重算法
public class NacosWeightRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {}@Override
public Server choose(Object o) {BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();// 获取请求微服务的名称String name = loadBalancer.getName();// 获取nacos服务发现相关名称NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();// nacos client自动通过基于权重的负载均衡算法,选择实例try {Instance instance = namingService.selectOneHealthyInstance(name);return new NacosServer(instance);} catch (NacosException e) {e.printStackTrace();}return null;
}
}
2.配置使用自定义的算法
3.在nacos服务中心当中配置服务的权重
集成Feign
使用步骤
在客户端引入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在启动类上面加上注解 @EnableFeignClients
创建服务 FeignClient
创建一个 service 文件夹,在该文件下创建一个接口
在接口加上添加 @FeignClient() 注解,参数就是你的微服务名字
示例
@FeignClient(name = "provide-goods")
public interface GoodsFeignClient {@RequestMapping("/getGoods")public Object getGoods();}
控制器调用
单个参数请求
goods工程
@RequestMapping("/getGoodsWithID/{id}")
public ResponseResult getGoodsWithID(@PathVariable Integer id){return ResponseResult.success("goods___id="+id);
}
Feign客户端
@RequestMapping("/getGoodsWithID/{id}")
public ResponseResult getGoodsWithID(@PathVariable Integer id);
user工程调用
多个参数请求
goods工程
Feign客户端
user工程调用
Sentinel
什么是 Sentinel
Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。
使用 Sentinel
下载 sentinel 控制台服务器
在 jar 目录当中打开控制台,输入 java -jar sentinel-dashboard-1.7.0.jar
- 可以修改端口号:
java -Dserver.port=8088 -Dcsp.sentinel.dashboard.server=localhost:8088 -jar sentinel-dashboard-1.7.0.jar
在浏览器当中输入:localhost:8080
用户名和密码为 sentinel
- 添加依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 添加配置
sentinel:transport:dashboard: localhost:8080
在浏览器当中进行访问:http://localhost:5000/getGoodsWithId/1
访问完成后,再次查看控制台
功能介绍
实时监控
1、 实时监控aip的执行通过/拒绝和对应响应时长簇点链路
1、曾经被访问过的路径
2、流控资源名称,访问的路径,唯一名称
针对来源
1、可以针对调用者进行限流
2、假设两个微服务a和b调用,可以对a和b单独的设置限流规则
3、default为不区别来源阈值类型
1、QPS:当调用api的QPS达到阈值时,就去做限流
2、线程数:当调用api的线程数达到一定的域值时就去做限流
3、是否集群
4、流控模式
4.1、直接:当违反定义的api规则时, 直接快速失败
示例
一秒种超过一次时, 就会触发限流
4.2、关联
当关联的资源达到阈值时, 限流自己
示例
http://localhost:5000/getGoodsWithObj?name=leader_tblog&id=18 访问时, 就会被限流
查询接口调用过快, 如果影响修改接口,或者修改接口影响查询接口, 根据业务需求,来进行关联限流
4.3、链路
指定资源从入口资源进来的流量,如果达到阈值,就开启限流
4.4、流控效果
- 快速失败
直接失败,抛出异常信息 - Warm Up
1、根据 codeFactor 从设置的阈值除以codeFactor,经过预热时长,才到达设置的QPS阈值
2、假设设置的阈值为90 那么就会90/3(默认) 30 作为最初的阈值 ,预热指定的时长 才去达到90的值限流 - 排队等待
1、匀速排队,让请求以均匀的速度通过,阈值类型必须设置成QPS,否则无效
2、超过了定义的时长, 就会抛出异常
代码配置
引入依赖
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.7.0</version>
</dependency>
- 定义资源名称
private static final String GET_GOODS_KEY = "getMyGoods";
- 定义限流规则
@RequestMapping("/initFlowRules")
public void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//设置资源名称rule.setResource(GET_GOODS_KEY);//设置针对来源rule.setLimitApp("default");//设置阈值类型rule.setGrade(RuleConstant.FLOW_GRADE_QPS);// 设置阈值rule.setCount(1);rules.add(rule);FlowRuleManager.loadRules(rules);
}
- 应用到被限流的接口上
@RequestMapping("/getMyGoods")
public String getMyGoods(){try (Entry entry = SphU.entry(GET_GOODS_KEY)) {// 被保护的逻辑return "getMyGoods";} catch (BlockException ex) {// 处理被流控的逻辑return "被限流了";}
}
自动执行流控代码
使用 springboot 自带的 ApplicationRunner 接口
使用方式,实现 ApplicationRunner 接口,在 run 方法当中执行流控代码
示例
@Component
public class SentinelRunner implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {initFlowRules();}private static final String GET_GOODS_KEY = "getMyGoods";public void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//设置资源名称rule.setResource(GET_GOODS_KEY);//设置针对来源rule.setLimitApp("default");//设置阈值类型rule.setGrade(RuleConstant.FLOW_GRADE_QPS);// 设置阈值rule.setCount(1);rules.add(rule);FlowRuleManager.loadRules(rules);}
}
使用注解改进代码
- Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandler 和 fallback 函数来进行限流之后的处理
- blockHandler 函数会在原方法被限流/降级/系统保护的时候调用
- fallback 函数会针对所有类型的异常
示例
private static final String GET_GOODS_KEY = "getMyGoods";@SentinelResource(value = GET_GOODS_KEY, blockHandler = "blockHandlerMethod")
@RequestMapping("/getMyGoods")
public String getMyGoods() {return "getMyGoods";
}public String blockHandlerMethod(BlockException e) {e.printStackTrace();return "被限流了----";
}
降级规则
降级策略
RT
平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 5 个请求,
对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位)
那么在接下的时间窗口之内,对这个方法的调用都会自动地熔断
异常比例
当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后
资源进入降级状态
异常次数
当资源近 1 分钟的异常数目超过阈值之后会进行熔断。
注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
热点规则
指定索引参数,如果在时间窗口内超过了指定的阈值,就会触发熔断
- 参数例外项
1、可以对指定的参数再进行设置限流
2、参数级别
对指定的参数限流,甚至对指定参数的值进行限流
注意事项
参数必须是基本数据类型或String类型
系统规则
和其他的规则不太一样,它是针对应用来设的
前面设置的都是争对某一个资源。某一个方法来设置的
阈值类型
load: load是负载,只有在linux机器上才会生效。根据当前系统的负载来决定是不是触发保护。
RT: 这个应用上所有的流量的平均的响应时间,所有服务的平均响应时间超过一个值,那么我就停止接收新的请求。
线程数: 所有服务访问的线程数加起来。
入口qps: 所有服务的qps加起来达到一个值。
cpu使用率: cpu的使用率超过一个百分比
发生以上这些情况的时候把你整个应用给你断掉。所有服务都不提供了
授权规则
使用授权时要先指定来源,对指定来源的内容进行限流
指定来源方式
@Component
public class RequestOrigin implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {//从请求参数中获取origin的参数并返回String origin = httpServletRequest.getParameter("origin");//如果获取不到origin 就抛出异常if (StringUtils.isBlank(origin)){throw new IllegalArgumentException("必须指定origin");}return origin;}
}
整合Feign
开启 feign 与 Sentinel 集成
feign:sentinel:enabled: true
整合方式与 Hystrix 一样
规则持久化
使用 Nacos 配置中心实现规则持久化
- 在 nacos 配置中心当中添加配置 json 规则
[{"resource": "getMyGoods2","limitApp": "default","grade": 1,"count": 5,"strategy": 0,"controlBehavior": 0,"clusterMode": false}
]
- 在工程当中添加依赖
<!--添加此依赖,项目一启动时, 就去到nacos当中读取配置中心-->
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId><version>1.7.0</version>
</dependency>
在配置文件当中添加 sentinel 读取 nacos 地址
eager: true
datasource:ds:nacos:server-addr: localhost:8849group-id: DEFAULT_GROUPrule-type: flowdata-id: my-goods-sentineldata-type: json
Spring-Cloud-GateWay
概述
什么是 Spring-Cloud-GateWay
Spring Cloud Gateway 基于 Spring Boot 2, 是 Spring Cloud 的 全新 项目, 该项 目 提供 了 一个 构建 在 Spring 生态 之上 的 API 网关
Spring Cloud Gateway 旨在 提供 一种 简单 而 有效 的 途径 来 转发 请求, 并为 它们 提供 横 切 关注 点, 例如: 安全性、 监控/ 指标 和 弹性
优点
性能比较高, 是第一代网关 zuul 的 1.6 倍
功能强大, 内置了很多功能,转发/监控/限流
容易扩展
缺点
实现依赖 Netty 和 WebFlux,不是传统的 Servet 模型
不能将其部署在 Tomcat,Jetty 等 Servelt 容器当中,只能打成 Jar 包执行
需要 springboot2.0 及以上版本才支持
词汇
Route路由: 路由网关的基本构建块。 它由ID,目标URI,谓词集合和过滤器集合定义。 如果聚合谓词为真,则匹配路由
Predicate谓词: 对请求的内容进行匹配,条件筛选
Filter过滤器: 可以对请求进行过滤,在发送下游请求之前或之后修改请求和响应
快速入门
创建 gateWay 服务
添加依赖
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>io.projectreactor.netty</groupId><artifactId>reactor-netty</artifactId><version>0.9.4.RELEASE</version></dependency>
</dependencies>
创建 启动类
@SpringBootApplication
public class AppGateWay {public static void main(String[] args) {SpringApplication.run(AppGateWay.class,args);}
}
添加 配置文件
logging:pattern:console: "%d{HH:mm:ss.SSS} %clr(%5p) %clr(-){faint} %clr(%-80.80logger{79}){cyan} %clr(:) %m%n"server:port: 9000spring:application:name: api-gatewaycloud:gateway:routes: #当请求满足要求时,转发到指定的服务当中- id: goods_route #唯一标识,默认是uuiduri: http://localhost:5000/ #请求要转发的地址order: 1 #路由优先级 越小, 优先级越高predicates: #谓词,断言(条件判断 转发请求要满足什么条件)- Path=/consumer-user/** #当路径中有指定内容时, 才会转发到指定urifilters: #过滤器,拦截请求做一些额外处理- StripPrefix=1 #去掉添加的path内容
在浏览器 当中访问
http://localhost:9000/consumer-user/getGoodsWithId/1
GateWay整合Nacos
- 在配置文件中添加 Nacos 的依赖, 把 gatWay 注册到 Nacos 当中
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- 在配置文件当中添加 nacos 的地址
cloud:nacos:discovery:server-addr: localhost:80 #nacos服务的地址 不要加http
- 在启动类上添加注解
@EnableDiscoveryClient - 配置 gateWay 从 nacos 中获取服务信息
discovery:locator:enabled: true #从nacos当中获取服务信息
- 信息 uri 为服务地址
lb: //服务名称
lb: 为负载均衡调用
lb: //consumer-user
谓词
什么是谓词 ( 断言 )
用于对请求进行判断 ,只有断言都返回值,才会真正的执行路由
满足条件,才能进行过滤,转发
内置断言工厂
基于 Datetime
AfterRoutePredicateFactory
判断请求日期是否晚于指定的日期
参数: 传递一个日期
示例
- After=2020-12-30T23:59:59.789+08:00[Asia/Shanghai]
BeforeRoutePredicateFactory
判断请求日期是否早于指定日期
参数: 传递一个日期
BetweenRoutePredicateFactory
判断请求日期是否在指定日期之间
参数: 传递两个日期
基于远程地址
RemoteAddrRoutePredicateFactory
判断请求主机地址是否在指定地址段时
参数: IP地址段
示例
- RemoteAddr=192.168.1.1/24
基于 Cookie 的断言
CookieRoutePredicateFactory
判断请求 cookie 是否具有给定名称且值与正则表达式匹配
参数: cookie 名称 , 正则表达式
示例
- Cookie=myCookName,[^gao]
基于 header
HeaderRoutePredicateFactory
判断请求 Header 是否具有给定名称且值与正则表达式匹配
参数: 标题名称 , 正则表达式
示例
- Header=Request-Id,\d+
基于 Host
HostRoutePredicateFactory
判断请求的 Host 是否满足匹配条件
参数: 主机名模式
示例
- Host=**.testhost.org
基于 Methods
MethodRoutePredicateFactory
判断请求类型是否为指定的类型
参数: 请求类型
示例
- Method=GET
基于 Query 请求参数
QueryRouterPredicateFactory
判断请求参数是否具有给定名称且值与正则表达式匹配
参数: 请求参数名,正则表达式
示例
- Query=name,test.
基于权重的断言工厂
WeightRoutePredicateFactory
对于同一组内容的路由,按权重进行转发
参数 : 组名,权重
示例
两个对于 / weight/** 路径转发的路由定义,这两个路由是同一个权重分组,且 weight_ route1 权重为 1, weight_ route2 权重为 9
对于 10 个访问 /weight/** 路径的请求来说,将会有 9 个路由到 weight_ route2,1 个路由到 weight_ route1
自定义谓词工厂
要求
名字必须是 配置+RoutePredicateFactory
必须继承 AbstractRoutePredicateFactory
方法介绍
List shortcutFieldOrder()
读取配置文件当中的参数,赋值到配置类中的属性上
要求和配置类当中的属性名称一致
Predicate apply
断言逻辑
class Config 内部类
接收配置文件当中对应的参数
示例
package cn.ddossec.factory;import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;@Component
class AppTypeRoutePredicateFactory extends AbstractRoutePredicateFactory<AppTypeRoutePredicateFactory.Config> {//构造器public AppTypeRoutePredicateFactory() {super(AppTypeRoutePredicateFactory.Config.class);}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("appType");}@Overridepublic Predicate<ServerWebExchange> apply(AppTypeRoutePredicateFactory.Config config) {return new Predicate<ServerWebExchange>() {@Overridepublic boolean test(ServerWebExchange serverWebExchange) {//接收参数String app = serverWebExchange.getRequest().getQueryParams().getFirst("app");if (StringUtils.isNotEmpty(app)) {if (config.getAppType().equals(app))return true;elsereturn false;}return false;}};}public static class Config {private String appType;public Config(String appType) {this.appType = appType;}public String getAppType() {return appType;}public void setAppType(String appType) {this.appType = appType;}}}
过滤器
什么是过滤器
GatewayFilter 网关过滤器用于拦截并链式处理 web 请求,可以实现横切的与应用无关的需求,比如:安全、访问超时的设置等
在请求传递过程当中,对请求和响应进行一些额外的处理
生命周期
pre
在 pre 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等
post
在 post 类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等
分类
局部过滤器
只作用在某 一个路由上
全局过滤器
作用在全部路由上
内置局部过滤器
AddRequestHeader
为原始请求添加 Header
Header 名称及值AddRequestParameter
为原始请求添加请求参数
参数名及值AddResponseHeader
为原始响应添加Header
Header名称及值DedupeResponseHeader
剔除响应头中重复的值
需要去重的Header名称及重复策略Hystrix
为路由引入 Hystrix 的断路器保护
HystrixCommand 名称FallBackHeader
为fallbackUri的请求头中添加具体的异常信息
Header的名称PrefixPath
为原始请求添加前缀
前缀路径PreserveHostHeader
为请求添加一个PreservHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host
没有参数RequestRateLimiter
用于对请求限流RedirectTo
将原始请求重定向到指定的URL
http状态码及重定向的urlRemoveHopByHopHeadersFilter
为原始请求删除IETF组织规定的一系列Header
默认就会启用RewritePath
重写原始请求路径
原始路径正则表达式及重写后路径的正则表达式RewriteResponseHeader
重写原始请求中的某个Header
Header名称,值的正则表达式,重写后的值SaveSession
在请求转发之前,强制执行webSession::save操作secureHeaders
为原始响应添加一系列安全作用的响应头SetStatus
修改响应的状态码
HTTP状态码,可以是数字也可以是字符串StripPrefix
用于截断原始请求的路径
使用数字表示要截断的路径的数量Retry
针对不同的响应进行重试RequestSize
设置允许接收最大请求包的大小
请求包大小,单位为字节ModifyRequestBody
在转发请求之前修改原始请求体内容
修改后的请求体内容ModifyResponseBody
修改原始响应体的内容
修改后的响应体内容
自定义局部过滤器
与自定义谓词方式大致一样
@Component
public class LogStatusGatewayFilterFactory extends AbstractGatewayFilterFactory<LogStatusGatewayFilterFactory.Config> {public LogStatusGatewayFilterFactory() {super(LogStatusGatewayFilterFactory.Config.class);}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("cacheStatus", "consoleStatus");}@Overridepublic GatewayFilter apply(Config config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {if (config.getCacheStatus())System.out.println("缓存状态");if (config.getConsoleStatus())System.out.println("控制台状态");return chain.filter(exchange);}};}@Validatedpublic static class Config {private Boolean cacheStatus;private Boolean consoleStatus;public Boolean getCacheStatus() {return cacheStatus;}public void setCacheStatus(Boolean cacheStatus) {this.cacheStatus = cacheStatus;}public Boolean getConsoleStatus() {return consoleStatus;}public void setConsoleStatus(Boolean consoleStatus) {this.consoleStatus = consoleStatus;}}
}
全局内置过滤器
@Component
public class TokenClobalFilter implements GlobalFilter, Ordered {/*** 过滤器执行的顺序* @return*/@Overridepublic int getOrder() {return 0;}/*** 执行过滤器逻辑* @param exchange* @param chain* @return*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String token = exchange.getRequest().getQueryParams().getFirst("token");if(!"admin".equals(token)){exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}return chain.filter(exchange);}
}
工作流程
示例图
介绍
DispatcherHandler
所有请求的调度器,负载请求分发
RoutePredicateHandlerMapping
路由谓语匹配器,用于路由的查找,以及找到路由后返回对应的 WebHandler
DispatcherHandler 会依次遍历 HandlerMapping 集合进行处理
FilteringWebHandler
使用Filter链表处理请求的 WebHandler
RoutePredicateHandlerMapping 找到路由后返回对应的 FilteringWebHandler 对请求进行处理。
FilteringWebHandler 负责组装Filter链表并调用链表处理请求。
Nacos配置中心
概述
Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持。
使用 Spring Cloud Alibaba Nacos Config,您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。
快速入门
- 客户端使用方式
添加依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
编写 bootstrap.yml 配置文件
spring:profiles:active: dev #${spring.profile.active}application:name: consumer-user #${prefix}cloud:nacos:config:server-addr: localhost:80file-extension: yaml #${file-extension}
- 在 Nacos 管理中心添加配置
动态刷新
@Value("${user.name}")
private String username;@RequestMapping("/getUserName")
public String getUserName(){return username;
}
在控制器当中添加注解 @RefreshScope
命名空间与分组
namespace 命名空间
用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。
Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
在没有明确指定 ${spring.cloud.nacos.config.namespace} 配置的情况下, 默认使用的是 Nacos 上 Public 这个namespae。
Group 分组
将不同的微服务划分到不同的分组当中
DataID
具体的配置文件地址
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:SpringCloud-Ali
如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件-Nacos 、Sentinel等的更多相关文章
- 今天介绍一下自己的开源项目,一款以spring cloud alibaba为核心的微服务架构项目,为给企业与个人提供一个零开发基础的微服务架构。
LaoCat-Spring-Cloud-Scaffold 一款以spring cloud alibab 为核心的微服务框架,主要目标为了提升自己的相关技术,也为了给企业与个人提供一个零开发基础的微服务 ...
- 基于Spring Cloud和Netflix OSS构建微服务,Part 2
在上一篇文章中,我们已使用Spring Cloud和Netflix OSS中的核心组件,如Eureka.Ribbon和Zuul,部分实现了操作模型(operations model),允许单独部署的微 ...
- Spring Cloud(Dalston.SR5)--Zuul 网关-微服务集群
通过 url 映射的方式来实现 zuul 的转发有局限性,比如每增加一个服务就需要配置一条内容,另外后端的服务如果是动态来提供,就不能采用这种方案来配置了.实际上在实现微服务架构时,服务名与服务实例地 ...
- Spring Cloud Alibaba学习笔记(12) - 使用Spring Cloud Stream 构建消息驱动微服务
什么是Spring Cloud Stream 一个用于构建消息驱动的微服务的框架 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互, ...
- 基于Spring Cloud和Netflix OSS 构建微服务-Part 1
前一篇文章<微服务操作模型>中,我们定义了微服务使用的操作模型.这篇文章中,我们将开始使用Spring Cloud和Netflix OSS实现这一模型,包含核心部分:服务发现(Servic ...
- SpringCloud(10)使用Spring Cloud OAuth2和JWT保护微服务
采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...
- spring cloud 入门,看一个微服务框架的「五脏六腑」
Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件. 注:Spring Boot 简单理解就是简化 Spring 项目的搭建.配置.组 ...
- 使用 Spring Cloud Stream 构建消息驱动微服务
相关源码: spring cloud demo 微服务的目的: 松耦合 事件驱动的优势:高度解耦 Spring Cloud Stream 的几个概念 Spring Cloud Stream is a ...
- 在IDEA编辑器中建立Spring Cloud的子项目包(构建微服务)
本文介绍在IDEA编辑器中建立Spring Cloud的子项目包 总共分为5个包: 外层使用maven quickstart建立,子modules直接选择了springboot
- 使用Spring Cloud OAuth2和JWT保护微服务
采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...
随机推荐
- SQL SERVER——高可用技术概述
自从SQL Server 2005以来,微软已经提供了多种高可用性技术来减少宕机时间和增加对业务数据的保护,而随着SQL Server 2008,SQL Server 2008 R2,SQL Serv ...
- 想做大模型开发前,先来了解一下MoE
为了实现大模型的高效训练和推理,混合专家模型MoE便横空出世. 大模型发展即将进入下一阶段但目前仍面临众多难题.为满足与日俱增的实际需求,大模型参数会越来越大,数据集类型越来越多,从而导致训练难度大增 ...
- POM模式核心思想?
对页面元素进行封装为类的属性 对用例执行流程设计成类的实例方法 通过定义好的页面类实例化一个对象,通过对象调用实例方法执行用例 核心作用: 可以较少代码的冗余,方便后面维护,如果页面元素发生改变, 只 ...
- 关于api的表优化及代码优化小结
提示:近期有空整理下mysql设计注意点吧 文章目录 一.表设计方面 二.代码设计方面 总结 一.表设计方面 建表要求三范式 5个必须字段is_del,create_time(CURRENT_TIME ...
- hibernate之createQuery与createSQLQuery
信息: java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.miracle.dm.doc.catalog.m ...
- spring 整体框架介绍
一.什么是Spring? 二.Spring能够解决什么问题? 三.Spring整体架构
- 智慧公安!3DCAT实时云渲染助力某公安机关打造数字孪生可视化系统
近年来,随着大数据.数字孪生.云计算.人工智能等技术的飞速发展,数字化浪潮席卷全国各地公安系统.2022年全国公安工作会议中也提到,数字化改革是推动公安工作创新发展的大引擎.培育战斗力生成新的增长点. ...
- HTML(表格、列表、表单)
表格 表格的主要作用 1.表格主要用于显示.展示数据,因为它可以让数据显示的非常的规整,可读性非常好.特别是后台展示数据的时候,能够熟练运用表格就显得很重要.一个清爽简约的表格能够把繁杂的数据表现得很 ...
- 浅析倾斜摄影三维模型(3D)几何坐标精度偏差的几个因素
浅析倾斜摄影三维模型(3D)几何坐标精度偏差的几个因素 倾斜摄影是一种通过倾斜角度较大的相机拍摄建筑物.地形等场景,从而生成高精度的三维模型的技术.然而,在进行倾斜摄影操作时,由于多种因素的影响,导致 ...
- C++ Concurrency in Action 读书笔记一:thread的管理
为避免混淆,用thread表示std::thread及其对象实例,用线程表示操作系统概念下的线程 Chapter 2 thread的管理 2.1 thread的创建(构造函数) a. 默认构造函数 d ...