sentinel集成其他框架

打印 上一主题 下一主题

主题 920|帖子 920|积分 2760

通过前几章我们了解了 sentinel-core 的使用方法和部分实现原理,我们在现实应用中怎样使用 sentinel 呢?
在项目中一个个手动界说资源么,那有点繁琐,也不利于后续的维护。 在 sentinel 中提供了两种方法,一种我们可以通过注解的方式来界说资源,另一种是通过 filter 机制拦截全部流量作为资源。
sentinel 切面

如果项目中引入了 spring-aop,那么在注册 SentinelResourceAspect bean 后,项目中被 @Sentinel 注解修饰过的方法都将被界说为资源。通过阅读以下 SentinelResourceAspect 代码,我们可以了解 @Sentinel 注解的拦截处理处罚逻辑:
  1. @Configuration
  2. public class AopConfiguration {
  3.     @Bean
  4.     public SentinelResourceAspect sentinelResourceAspect() {
  5.         return new SentinelResourceAspect();
  6.     }
  7. }
  8. @Aspect
  9. public class SentinelResourceAspect extends AbstractSentinelAspectSupport {
  10.     @Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")
  11.     public void sentinelResourceAnnotationPointcut() {
  12.     }
  13.     @Around("sentinelResourceAnnotationPointcut()")
  14.     public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
  15.         Method originMethod = resolveMethod(pjp);
  16.         // 获取方法上的 sentinel 注解定义,转换为资源名
  17.         SentinelResource annotation = originMethod.getAnnotation(SentinelResource.class);
  18.         String resourceName = getResourceName(annotation.value(), originMethod);
  19.         EntryType entryType = annotation.entryType();
  20.         int resourceType = annotation.resourceType();
  21.         Entry entry = null;
  22.         try {
  23.             // 进入资源,成功则进行业务处理,失败则抛出异常
  24.             entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
  25.             return pjp.proceed();
  26.         } catch (BlockException ex) {
  27.             // 进入资源被拦截时的处理
  28.             return handleBlockException(pjp, annotation, ex);
  29.         } catch (Throwable ex) {
  30.             // ...
  31.             // 其他异常的降级(fallback)处理
  32.             if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {
  33.                 traceException(ex);
  34.                 return handleFallback(pjp, annotation, ex);
  35.             }
  36.             throw ex;
  37.         } finally {
  38.             // 资源的退出
  39.             if (entry != null) {
  40.                 entry.exit(1, pjp.getArgs());
  41.             }
  42.         }
  43.     }
  44. }
复制代码
sentinel adapter 原理

sentinel 中除了使用 aop 机制将 @Sentinel 注解修饰过的方法资源。还可以通过框架提供的 filter、interceptor 等机制将全部流量拦截,全部作为资源(将全部的流量都作为资源,迟早会突破 sentinel 中的资源上限,所以 sentinel 中支持 url 合并,以缩减资源的数目,后文我们将会先容)。
目前 sentinel adapter 模块支持集成 servlet、spring mvc、dubbo 等 20 种主流框架,对应实现的 adapter 实现原理根本相似。下面我们以 sentinel-web-servlet 为例,讲解 sentinel 怎样和 java servlet 举行集成,其大抵示意图如下:

1,引入 sentinel-web-servlet 依靠后
2,在 web.xml 界说 sentinel filter
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  3. <filter>
  4.         <filter-name>sentinel-filter</filter-name>
  5.         <filter-class>com.alibaba.csp.sentinel.adapter.servlet.CommonFilter</filter-class>
  6.     </filter>
  7.     <filter-mapping>
  8.         <filter-name>myFilter</filter-name>
  9.         <url-pattern>/</url-pattern>
  10.     </filter-mapping>
  11. </web-app>
复制代码
CommonFilter 中的代码逻辑同 SentinelResourceAspect 类似:
  1. class CommonFilter {
  2.     @Override
  3.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  4.             throws IOException, ServletException {
  5.         HttpServletRequest sRequest = (HttpServletRequest) request;
  6.         Entry urlEntry = null;
  7.         try {
  8.             String target = FilterUtil.filterTarget(sRequest);
  9.             // url 合并,返回为 "" 时代表该请求不被 sentinel 处理
  10.             UrlCleaner urlCleaner = WebCallbackManager.getUrlCleaner();
  11.             if (urlCleaner != null) {
  12.                 target = urlCleaner.clean(target);
  13.             }
  14.             if (!StringUtil.isEmpty(target)) {
  15.                 // 解析请求来源
  16.                 String origin = parseOrigin(sRequest);
  17.                 String contextName = webContextUnify ? WebServletConfig.WEB_SERVLET_CONTEXT_NAME : target;
  18.                 ContextUtil.enter(contextName, origin);
  19.                 // 是否将同 url 不同请求方式视为不同资源,如:GET:/foo 和 POST:/foo 是不同资源
  20.                 if (httpMethodSpecify) {
  21.                     String pathWithHttpMethod = sRequest.getMethod().toUpperCase() + COLON + target;
  22.                     urlEntry = SphU.entry(pathWithHttpMethod, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
  23.                 } else {
  24.                     // 进入资源
  25.                     urlEntry = SphU.entry(target, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
  26.                 }
  27.             }
  28.             chain.doFilter(request, response);
  29.         } catch (BlockException e) {
  30.             HttpServletResponse sResponse = (HttpServletResponse) response;
  31.             // Return the block page, or redirect to another URL.
  32.             WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse, e);
  33.         } catch (IOException | ServletException | RuntimeException e2) {
  34.             Tracer.traceEntry(e2, urlEntry);
  35.             throw e2;
  36.         } finally {
  37.             if (urlEntry != null) {
  38.                 urlEntry.exit();
  39.             }
  40.             ContextUtil.exit();
  41.         }
  42.     }
  43. }
复制代码
3,创建对应的配置,用于请求泉源解析、资源合并和阻塞的处理处罚
  1. class SentinelConfig {
  2.     static {
  3.         initConfig();
  4.     }
  5.    
  6.     public static void initConfig() {
  7.         // 用于将请求 url 进行合并
  8.         // 如:/page/1.html、/page/2.html 合并为 /page/*.html,可以减少资源的个数
  9.         WebCallbackManager.setUrlCleaner(new MyUrlCleaner());
  10.         // 用于解析请求中的来源,用于资源的白、黑名单访问控制
  11.         // 如:解析请求头中的来源 ip,使得部分资源只能被特定来源 ip 访问
  12.         // 当然这个来源不一定时 ip,也可以是 refer、host 等其他请求头或自定义请求头
  13.         WebCallbackManager.setRequestOriginParser(new MyRequestOriginParser());
  14.         // 用于资源访问时被拦截时处理逻辑
  15.         // 如:资源访问受限时,返回 429 响应,使得调用方知道系统当前请求过多
  16.         WebCallbackManager.setUrlBlockHandler(new MyUrlBlcokHandler());
  17.     }
  18. }
复制代码
总结

总而言之,sentinel 和我们应用中的框架集成后,要么通过 aop 的机订界说资源,要么通过框架提供的 filter、interceptor 机制拦截请求来界说资源。
这都比较方便的快速将项目中的业务逻辑界说为资源,但我们还需要为资源界说对应的规则,难道我们还是需要手动一个一个界说么?下章我们将先容怎样在 sentinel dashboard 中界说资源规则。
文章编写不易,如有帮助,欢迎 star:github 地址、gitee 地址

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小小小幸运

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表