feat(master):sentinel gateway 相关逻辑

代码完成
master
土豆兄弟 3 days ago
parent 07e7e978dc
commit 03aa1d6f03

@ -77,6 +77,22 @@
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!-- 有关限流相关的代码引入 start -->
<!-- 集成 Sentinel, 在网关层面实现限流 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!-- Sentinel 使用 Nacos 存储规则 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- 有关限流相关的代码引入 end -->
</dependencies>
<!--

@ -0,0 +1,210 @@
package org.example.conf;
import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
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 com.alibaba.csp.sentinel.slots.block.RuleConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
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.*;
/**
* <h1>Gateway Sentinel </h1>
*
* , 使
* */
@Slf4j
@Configuration
public class SentinelGatewayConfiguration {
/** 视图解析器 */
private final List<ViewResolver> viewResolvers;
/** HTTP 请求和响应数据的编解码配置 */
private final ServerCodecConfigurer serverCodecConfigurer;
/**
* <h2></h2>
* */
public SentinelGatewayConfiguration(
ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer
) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
/**
* <h2>, , handler</h2>
* */
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// 默认会返回错误 message, code 429
return new SentinelGatewayBlockExceptionHandler(
this.viewResolvers,
this.serverCodecConfigurer
);
}
/**
* <h2>, Gateway , </h2>
* */
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
/**
* <h2></h2>
* */
// @PostConstruct //fixme 注释掉这个, 就可以取消硬编码模式
public void doInit() {
log.info("---------------------------------------------------");
// 1. 加载网关限流规则
log.info("load sentinel gateway rules (code define)");
initGatewayRules();
// 2. 加载自定义限流异常处理器
initBlockHandler();
log.info("---------------------------------------------------");
}
/**
* <h2></h2>
* */
private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
GatewayFlowRule rule = new GatewayFlowRule();
// 指定限流模式, 根据 route_id 做限流, 默认的模式
rule.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID);
// 指定 route_id -> service id, 指定要限流的服务
rule.setResource("dev-protocol-springcloud-nacos");
// 按照 QPS 限流
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 统计窗口和限流阈值 60s内3个请求通过
rule.setIntervalSec(60);
rule.setCount(3);
// 1. 硬编码模式
// rules.add(rule);
// 3. 限流分组, Sentinel 先去找规则定义, 再去找规则中定义的分组
rules.add(
new GatewayFlowRule("nacos-client-api-1")
.setCount(3).setIntervalSec(60)
);
rules.add(
new GatewayFlowRule("nacos-client-api-2")
.setCount(1).setIntervalSec(60)
);
// 加载到网关中
GatewayRuleManager.loadRules(rules);
// 3. 加载限流分组
initCustomizedApis();
}
/**
* <h2></h2>
* */
private void initBlockHandler() {
// 自定义 BlockRequestHandler
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange,
Throwable throwable) {
log.error("------------- trigger gateway sentinel rule -------------");
Map<String, String> result = new HashMap<>();
result.put("code", String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));
result.put("message", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
result.put("route", "dev-protocol-springcloud-nacos");
return ServerResponse
.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(result));
}
};
// 设置自定义限流异常处理器
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
/**
* <h2></h2>
* 1. -
* 2.
* */
private void initCustomizedApis() {
Set<ApiDefinition> definitions = new HashSet<>();
// stream-client-api 组, 最大的限制, 只是用作演示, 一种模糊的定义
ApiDefinition api = new ApiDefinition("nacos-client-api")
// {{}} 可以直接用作给集合初始化
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
// 模糊匹配 /dev-protocol-springcloud-gateway/dev-protocol-springcloud-nacos/ 及其子路径的所有请求
add(new ApiPathPredicateItem()
.setPattern("/dev-protocol-springcloud-gateway/dev-protocol-springcloud-nacos/**")
// 根据前缀匹配
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
// nacos-client-api-1 分组
ApiDefinition api1 = new ApiDefinition("nacos-client-api-1")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem()
// 精确匹配 /dev-protocol-springcloud-gateway/dev-protocol-springcloud-nacos/nacos-client/service-instance
.setPattern("/dev-protocol-springcloud-gateway/dev-protocol-springcloud-nacos" +
"/nacos-client/service-instance"));
}});
// nacos-client-api-2 分组
ApiDefinition api2 = new ApiDefinition("nacos-client-api-2")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem()
// 精确匹配 /dev-protocol-springcloud-gateway/dev-protocol-springcloud-nacos/nacos-client/project-config
.setPattern("/dev-protocol-springcloud-gateway/dev-protocol-springcloud-nacos" +
"/nacos-client/project-config"));
}});
definitions.add(api1);
definitions.add(api2);
// 加载限流分组
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
}

@ -15,6 +15,41 @@ spring:
metadata:
management:
context-path: ${server.servlet.context-path}/actuator
# 限流
sentinel:
eager: true
transport:
port: 8720
dashboard: 127.0.0.1:7777
datasource:
# 通过本地文件方式, 基于服务级别的配置
# ds1.file:
# file: classpath:gateway-flow-rule-sentinel.json
# # 代表服务级别的限流, 一步步点进去看, 文件类型
# ruleType: gw-flow
# # 通过本地文件方式, 细粒度对指定 api 进行配置
# ds2.file:
# file: classpath:gateway-flow-rule-api-sentinel.json
# # 代表 API 分组, 一步步点进去看, 文件类型
# ruleType: gw-api-group
# 集成 Nacos - 配置文件在 Nacos 中
ds1:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: ${spring.cloud.nacos.discovery.namespace}
# 测试时, 看看 Nacos 中修改是否能让 dashboard 生效, 就把第二个 count 也修改为 3
data-id: gateway-flow-rule-sentinel
group-id: DEFAULT_GROUP
data-type: json
rule-type: gw-flow
ds2:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: ${spring.cloud.nacos.discovery.namespace}
data-id: gateway-flow-rule-api-sentinel
group-id: DEFAULT_GROUP
data-type: json
rule-type: gw-api-group
# 静态路由
# gateway:
# routes:

@ -0,0 +1,14 @@
[
{
"apiName": "nacos-client-api",
"predicateItems": [
{
"pattern": "/dev-protocol-springcloud-gateway/dev-protocol-springcloud-nacos/nacos-client/project-config"
},
{
"pattern": "/dev-protocol-springcloud-gateway/dev-protocol-springcloud-nacos/**",
"matchStrategy": 1
}
]
}
]

@ -0,0 +1,14 @@
[
{
"resource": "dev-protocol-springcloud-nacos",
"resourceMode": 0,
"count": 3,
"intervalSec": 60
},
{
"resource": "nacos-client-api",
"resourceMode": 1,
"count": 1,
"intervalSec": 60
}
]

@ -1,5 +1,6 @@
### 查询服务 - (测试gateway)
GET http://127.0.0.1:9001/dev-protocol-springcloud-gateway/ecommerce-nacos-client/nacos-client/service-instance?serviceId=e-commerce-gateway
# 测试之前的 token 可以重新获取生成
GET http://127.0.0.1:9001/dev-protocol-springcloud-gateway/dev-protocol-springcloud-nacos/nacos-client/service-instance?serviceId=e-commerce-gateway
Accept: application/json
e-commerce-user: eyJhbGciOiJSUzI1NiJ9.eyJlLWNvbW1lcmNlLXVzZXIiOiJ7XCJpZFwiOjE3LFwidXNlcm5hbWVcIjpcIkltb29jUWlueWlAaW1vb2MuY29tXCJ9IiwianRpIjoiMGIxNzQyYWItMWU3OC00OTZjLWIyNTAtMjNkZGQ1ZGEyZTU1IiwiZXhwIjoxNjI0MjA0ODAwfQ.QKGHzohSHdYDHzUVHpe9gNPUgzfkPwrSbB-WiMWYjLlt2tr9BufzZM8bSt-whb_bd0hKoC6rkYYO0WUVR67uSML-2yaTL1xMIn8GH9Flyig3rpO4vefL3Hp2TXIpwHHa7WlKsLzcUpNk9lxWs2B5k0ICdYCH_jD5Tx6N7CzfSUG9u4fOnVeM9UFE2nX_DURupUh_DKCc2oOoMeyCSR7Ma8-Ab4WQU3r-U0YivR8G1A0kmKOIoTeRhM3LcPuxUPh3rCbrjzMg--fexRGw0O38Qsby6pz-ku2IlTyFXY6_jNOG1BZR34-jBOnaIciP1TExw9bFumeuC2GcowTHJVH1Nw
token: imooc

@ -0,0 +1,14 @@
[
{
"apiName": "nacos-client-api",
"predicateItems": [
{
"pattern": "/imooc/ecommerce-nacos-client/nacos-client/project-config"
},
{
"pattern": "/imooc/ecommerce-nacos-client/**",
"matchStrategy": 1
}
]
}
]

@ -0,0 +1,14 @@
[
{
"resource": "e-commerce-nacos-client",
"resourceMode": 0,
"count": 3,
"intervalSec": 60
},
{
"resource": "nacos-client-api",
"resourceMode": 1,
"count": 1,
"intervalSec": 60
}
]

@ -0,0 +1,56 @@
# 风控说明
> 本风控规则集合多家经验的总结,仅供参考
<font color="red">强烈建议不要异地登录!!!</font>
## 0. 参考文档
- 友军1
- https://www.apifox.cn/apidoc/shared-71b9855b-693c-48fc-858b-cde2c5afe5a8/doc-1674150
## 1. 基本风控规则
### 1.0 设备及账号相关
- 使用本服务进行登录均为副设备登录,使用账号密码进行登录的为主设备,副设备大概率 24 小时内掉线一次防盗号机制为正常现象二次登录即可执行历史快捷登陆API以保证复用历史设备信息挂机常用设备 。
- 为了账号稳定,推荐登录新设备后进行 3 - 5 小时的挂机养号操作,在此时间段内限制或者禁止操作,以提高设备的稳定性,可以避免很多风控。
### 1.1 行为相关
- 新设备登录 24 小时1天内不能发送朋友圈部分账号 72 小时3天内不能发朋友圈如发送朋友圈手机会收到安全告警。
- 发朋友圈每条间隔建议10分钟以上 / 条,单天建议不超过 100 条,点赞和评论建议间隔为 3~5s 单天上限为500 次,获取朋友圈间隔为 5s 以上,单天上限为 200 次。
- 主动添加好友单天上限为 15 个,扫码方式添加和通过好友请求上限为 25 个1 小时内上限为 5 个,超过上限时,无法发出好友请求,也收不到好友请求。
- 发送消息 1 分钟内不能超过 40 条,给相同对象(同一个好友,同一个群)发消息时,建议间隔为 1 ~ 3s / 条,给不同对象(不同的群,不同的好友)发消息时,每个对象之间建议间隔为 3 ~ 5s。
- 创建群聊单天上限为 10~15 个,且两次创建群聊的间隔不要低于 10 分钟,频繁建群,或频繁拉人入群是极度高危操作,建议使用主设备进行创建群聊。新群不建议直接拉人,可使用多个机器人在群里随意发几天消息后再拉人,新号建议 1 小时内拉人数不要超过 6 个,老号可适当放宽,但不宜超过 15 个。
- 下载图片,视频等,需在消息收到后 1s 后进行下载,每次下载之间间隔需超过 3s失败重试间隔最低 1s 每条消息请只下载一次,多次下载有一定风险,需要永久保存的文件请自行保存,下载链接仅 3 天有效。
- 定时业务请注意让定时任务有一定的时间波动,太规律的行为在风控严格时期,可能会被警告。
## 2. 加好友
### 2.0 总规则
- 一个微信号能加的好友上限是5000人建议加3000人就够了。
- 微信好友3000人以上约有15%-20%的好友看不到你发的发朋友圈。
- 微信好友接近5000人约有30%的好友看不到你发的发朋友圈。
### 2.1 微信主动添加好友
- 一个微信号一天主动添加好友不能超过30人
### 2.2 微信被动添加为好友
- 一个微信号一天只能被动加300人左右的好友。 超过了,会提示操作频繁,加不上。
### 2.3 微信添加好友的方式和安全人数详解
- 扫一扫加好友每天每个微信号最多加30人
- 通讯录导入每天最多加3次每次最多加10人每次间隔时间最少2小时
- 搜索加好友每天最多加3次每次最多加10人每次间隔时间最少2小时
- 微信群内加好友每天最多加3次每次最多加10人每次间隔时间最少2小时
- 附近的人加好友每天最多加3次每次最多加8个人每次间隔时间最少2小时
- 摇一摇加好友每天最多加2次每次最多加5个人每次间隔时间最少2小时
- 加微信名片每天每个微信号最多加20人
- 被动加好友每天每个微信号最多被动加300人左右
- 1年老号被动通粉间隔 1-3min, 每天 200 测试稳定 - 测试时间: 2024年9月30日记录
> 微信申请添加好友请求有效期为10天若验证时间超过10天就会显示“接受好友验证请求已过期“。</br>
> 显示已过期需要用户或者对方重新发起验证请求。如果添加同一个好友连续发送请求数6-8次而堆放一直没有通过验证的时候系统将不再接受请求将提示发送失败
Loading…
Cancel
Save