前面我们讲解了Sentinel整合Spring Cloud Gateway,详细请查看文章:阿里Sentinel支持Spring Cloud Gateway啦!
目前来说,大部分公司线上的网关应该是Zuul,所以今天我们就来看看如何在Zuul中整合Sentinel。
本来想基于Spring Cloud Alibaba来进行整合讲解,整合的时候发现目前还没更新版本,依赖还是之前的版本,咱们就以最原生的方式进行整合吧,等Spring Cloud Alibaba更新之后,Sentinel的整合只会变得更简单。
加入zuul-adapter依赖:

1.  
2.      com.alibaba.csp
3.      sentinel-zuul-adapter
4.      1.6.0
5.  
配置Sentinel提供的限流过滤器和限流规则:
1.  @Configuration
2.  public class ZuulConfig {
3.  
4.      @Bean
5.      public ZuulFilter sentinelZuulPreFilter() {
6.          return new SentinelZuulPreFilter();
7.      }
8.  
9.      @Bean
10.     public ZuulFilter sentinelZuulPostFilter() {
11.         return new SentinelZuulPostFilter();
12.     }
13. 
14.     @Bean
15.     public ZuulFilter sentinelZuulErrorFilter() {
16.         return new SentinelZuulErrorFilter();
17.     }
18. 
19.     @PostConstruct
20.     public void doInit() {
21.         // 注册 FallbackProvider
22.         // ZuulBlockFallbackManager.registerProvider(new MyBlockFallbackProvider());
23.         initGatewayRules();
24.     }
25. 
26.     /**
27.      * 配置限流规则
28.      */
29.     private void initGatewayRules() {
30.         Set rules = new HashSet<>();
31.         rules.add(new GatewayFlowRule("yinjihuan").setCount(1) // 限流阈值
32.                 .setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒
33.         );
34. 
35.         GatewayRuleManager.loadRules(rules);
36.     }
37. }
  • SentinelZuulPreFilter pre过滤器,在请求路由之前匹配routeId和api,进行限流操作
  • SentinelZuulPostFilter post过滤器,路由之后恢复资源
  • SentinelZuulErrorFilter error过滤器,异常后的处理
    最后再配置一个简单的路由,路由名称yinjihuan,跟上面规则中的名称一致:
1.  zuul.routes.yinjihuan.path=/cxytiandi/**
2.  zuul.routes.yinjihuan.url=http://cxytiandi.com

触发限流后会返回固定的提示:

1.  {
2.      "code":429,
3.      "message":"Sentinel block exception",
4.      "route":"yinjihuan"
5.  }

如果想修改提示内容可以自己实现ZuulBlockFallbackProvider接口,框架默认提供的实现是DefaultBlockFallbackProvider,源码如下:

1.  public class DefaultBlockFallbackProvider implements ZuulBlockFallbackProvider {
2.  
3.      @Override
4.      public String getRoute() {
5.          return "*";
6.      }
7.  
8.      @Override
9.      public BlockResponse fallbackResponse(String route, Throwable cause) {
10.         if (cause instanceof BlockException) {
11.             return new BlockResponse(429, "Sentinel block exception", route);
12.         } else {
13.             return new BlockResponse(500, "System Error", route);
14.         }
15.     }
16. }

用法其实跟Zuul中的FallbackProvider一致,但是FallbackProvider比较好的是返回的ClientHttpResponse,我们可以自定义响应内容。
Sentinel提供的ZuulBlockFallbackProvider接口中定义的返回对象是BlockResponse ,也就意味着限制了响应的字段,BlockResponse中有code,message,route三个字段,如果我想返回status, msg这两个字段目前我没找到其它的方式,不知道后续会不会支持,其实最好的是也返回ClientHttpResponse,这样就可以自定义响应内容了。
这边有个小插曲,就是我们自定义fallbackResponse的时候如果用中文message的话,响应内容是乱码,如下:

1.  {
2.    code: 429,
3.    message: "??????",
4.    route: "yinjihuan"
5.  }

我看了下SentinelZuulPreFilter中的代码,如下:
阿里Sentinel整合Zuul网关详解_第1张图片
这边是构造了BlockResponse,然后设置到ResponseBody中,但是没有进行编码设置,我自己改了下源码,加了一行代码:

1. ctx.getResponse().setContentType("application/json; charset=utf-8");

加了上面的代码后,中文就不会乱码了,效果如下:

1.  {
2.    code: 429,
3.    message: "访问太频繁啦",
4.    route: "yinjihuan"
5.  }

不说了,我还是去提个issues吧: https://github.com/alibaba/Sentinel/issues/733
彩蛋来了:发文当天加入星球前三位的小伙伴,将获取神秘大礼
加入星球特权

1、从前端到后端玩转Spring Cloud
2、实战分库分表中间件Sharding-JDBC
3、实战分布式任务调度框架Elastic Job
4、配置中心Apollo实战
5、高并发解决方案之缓存
6、更多课程等你来解锁,20+课程

阿里Sentinel整合Zuul网关详解_第2张图片
尹吉欢
我不差钱啊
喜欢作者