前言
最近发现有人恶意暴力注册我的网站Seaurl,导致我的网站发送邮件近万条数据,为了防止该事件,我决定在网站上面添加限流以及IP黑名单功能,本篇文章主要讲如何限流,后面再写一篇如何设置IP黑名单。
准备
最流行的限流技术有:Sentinel、Hystrix、Resilience4J
,下面是他们的对比:
通过对比之后,我决定使用更加厉害的Sentinel,而且它是阿里出品的,又有双十一做过考验,接下来详解如何集成Sentinel
操作
1、引入Sentinel
依赖包
<properties>
<java.version>17</java.version>
<spring-boot.version>3.0.2</spring-boot.version>
<spring-cloud.version>2022.0.0</spring-cloud.version>
<spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
</properties>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.csp/sentinel-datasource-nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>2.0.0-alpha</version>
</dependency>
2、在Nacos
上面配置Sentinel
数据源
spring:
cloud:
sentinel:
transport:
//这个是sentinel控制台,需要手动下载sentinel.jar安装启动即可
dashboard: localhost:8080
datasource:
ds-flow:
nacos:
## nacos的地址
server-addr: ${server.nacos.addr}
namespace: ${server.nacos.ns}
## 配置ID
data-id: sentinel-service
## 配置分组,默认是DEFAULT_GROUP
group-id: DEFAULT_GROUP
## 默认提供两种内置的值,分别是 json 和 xml (不填默认是json)
data-type: json
## rule-type设置对应得规则类型,总共七大类型,在com.alibaba.cloud.sentinel.datasource.RuleType这个枚举类中有体现
rule-type: flow
nacos:
discovery:
server-addr: ${server.nacos.addr}
namespace: ${server.nacos.ns}
service: ${server.name}
config:
server-addr: ${server.nacos.addr}
namespace: ${server.nacos.ns}
prefix: ${server.name}
file-extension: yaml
注意:如果你的nacos有namespace
那么Sentinel
也必须设置namespace
,否则不起作用
3、设置 Sentinel的Resource
下面的webRegister
就是我们需要限流的resource
名称
@PostMapping("/web/register")
@SentinelResource(value = "webRegister")
public ResponseEntity<?> register(@RequestBody RegisterRequest registerRequest, ServerHttpRequest request) {
//省略
}
4、添加 CustomExceptionHandler
类
添加CustomExceptionHandler
异常类的目的是当限流的时候返回指定错误消息,如下代码所示:
package com.seaurl.userservice.exception;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.seaurl.common.result.ResultInfo;
import com.seaurl.common.result.ResultStatus;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class CustomExceptionHandler {
/**
* 限流全局异常
*/
@ExceptionHandler(FlowException.class)
public ResultInfo handlerFlowException() {
return new ResultInfo(ResultStatus.SERVER_Exception);
}
/**
* 熔断全局异常
*/
@ExceptionHandler(DegradeException.class)
public ResultInfo handlerDegradeException() {
return new ResultInfo(ResultStatus.SERVER_Degrade_Exception);
}
/**
* 热点限流异常
*/
@ExceptionHandler(ParamFlowException.class)
public ResultInfo handlerparamFlowException() {
return new ResultInfo(ResultStatus.SERVER_Exception);
}
/**
* Sentinel 权限拦截全局异常
*/
// @ExceptionHandler(AuthorityException.class)
// @ResponseBody
// public Map handlerAuthorityException() {
// return new HashMap() {{
// put("code", HttpStatus.UNAUTHORIZED.value());
// put("msg", "暂无权限");
// }};
// }
}
5、在Nacos
上面创建Sentinel
数据源
下面就是创建好的配置文件,以及Sentinel
配置的数据源:
下面说明一下上面的属性具体的作用:
- resource :资源名,资源名是限流规则的作用对象,比如请求资源 getUser 。
- grade :限流阈值类型,QPS 或线程数模式。0表示线程数,1表示QPS。默认为1,即 QPS 模式
- count :限流阈值。比如值为2表示1秒超过2个请求就限流。
- strategy :流控模式:直接、链路、关联,默认 直接 。0表示直接,1表示关联,2表示链路。
- controlBehavior :流控效果(直接拒绝 / 排队等待 / 慢启动模式),0表示快速失败,1表示Warm Up,2表示排队等待。
- limitApp :流控针对的调用来源。默认就是 default ,代表不区分调用来源.
5、下载Sentinel
并启动
Github下载地址:https://github.com/alibaba/Sentinel
下载好后运行jar包即可:
java -jar sentinel-dashboard-1.8.1.jar
启动好之后,我们打开浏览器,输入:localhost:8080
,出现如下界面:
这样就能清楚看到限流规则以及具体限流通过的QPS了,我们可以通过请求注册接口再查看sentinel控制台看看有没有显示成功!
SpringCloud Gateway+Redis限流
在网上也能看到其它的限流方式,如SpringCloud Gateway+Redis
限流,下面简单介绍一下
1、引入依赖包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
2、配置SpringCloud Gateway
- id: users-service
uri: lb:http://users-service # lb://serviceId
predicates:
- Path=/v1/users/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
key-resolver: "#{@ipAddressKeyResolver}"
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 1
3、添加IpAddressKeyResolver
实体类
@Component
public class IpAddressKeyResolver implements KeyResolver {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
InetSocketAddress remoteAddress = (InetSocketAddress) exchange.getRequest().getRemoteAddress();
return Mono.just(remoteAddress.getAddress().getHostAddress()); // 获取客户端 IP 地址
}
}
这样就能完成限流,官网介绍
总结
1、上面限流的配置有点复杂,大家注意每个细节点
2、需要下载个sentinel
jar包才能显示控制台数据
3、后面有时间把熔断也加上
引用
Spring Cloud(七)Sentinel
基于Nacos限流规则持久化Demo
Spring Cloud Alibaba:将 Sentinel 熔断限流规则持久化到 Nacos 配置中心
用Nacos存储Sentinel的限流规则
Spring Boot 通用限流方案,还可以这样玩!
只需三步实现Gateway结合Sentinel实现无侵入网关限流,注意避坑!
Sentinel系列(8)-Sentinel使用 Nacos 配置规则
「SpringCloud」Sentinel+Nacos配置持久化
限流降级组件Sentinel、Hystrix、Resilience4j对比
Spring Cloud Gateway 本地内存 IP 限流
GateWay网关应用案例(跨域、限流、黑白名单)
分布式限流之 - Spring Cloud Gateway层限流实现
Spring Cloud Gateway 限流实战,终于有人写清楚了!
Spring Cloud Gateway自带RequestRateLimiter限流应用及扩展 | Spring Cloud 16
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。