之前 https://blog.youkuaiyun.com/sdmanooo/article/details/115522607 这篇文章讲了zuul网关使用guava的RateLimiter令牌桶实现限流。
其实alibaba提供了sentinel组件,也可以支持限流、降级、熔断保护等。其官网使用说明:https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6
这里简单的介绍下在网关上的使用,代码上要比guava的令牌桶麻烦一些,直接上代码:
1、引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.1</version>
</dependency>
2、在网关的启动类中初始化令牌桶
@SpringBootApplication
@EnableZuulProxy
public class CloudZuulApplication {
public static void main(String[] args) {
init(); //初始化令牌桶
SpringApplication.run(CloudZuulApplication.class, args);
}
//生成限流令牌
private static void init(){
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule flowRule = new FlowRule();
//指定resource名称,自定义即可,限流时,根据resource名称进行限流
flowRule.setResource("HelloWorld");
//指定限流规则 使用qps方式限流 还可以根据自己需要定义其他的
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
//指定限流数量 此处就是1qps
flowRule.setCount(1);
rules.add(flowRule);
//加载规则
FlowRuleManager.loadRules(rules);
}
}
3、建Filter类,使用令牌桶
import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
/**
* 阿里sentinel限流组件实现限流
*
*/
@Component
public class SentinelFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return -20;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
//限流逻辑
Entry entry = null;
try {
entry = SphU.entry("HelloWorld"); //指定resource
System.out.println("请求通过");
} catch (BlockException e) {
System.out.println("被限流了");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
} finally {
if (entry!=null) {
entry.exit();
}
}
return null;
}
}
注意:SphU.entry("HelloWorld");和entry.exit()必须成对出现,这个官网也有说明。
至此结束。