sentinel源码分析-资源

1、sentinel中如何创建资源?

方式一:主流框架的默认适配

为了减少开发的复杂程度,sentinel 对大部分的主流框架,例如 Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor 等都做了适配。只需要引入对应的依赖即可方便地整合 Sentinel。针对不同框架,默认的资源统计会有所区别。

Web Servlet

所有访问的 Web URL 就会被自动统计为 Sentinel 的资源。

Dubbo

限流粒度可以是服务接口和服务方法两种粒度:

  • 服务接口:资源为 接口全限定名,如 com.alibaba.csp.sentinel.demo.dubbo.FooService
  • 服务方法:资源为 接口全限定名:方法签名,如 com.alibaba.csp.sentinel.demo.dubbo.FooService:sayHello(java.lang.String)

方式二:抛出异常的方式定义资源

SphU 包含了 try-catch 风格的 API。用这种方式,当资源发生了限流之后会抛出 BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理。示例代码如下:

// 1.5.0 版本开始可以利用 try-with-resources 特性
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
try (Entry entry = SphU.entry("resourceName")) {
  // 被保护的业务逻辑// do something here...
} catch (BlockException ex) {
  // 资源访问阻止,被限流或被降级// 在此处进行相应的处理操作
}

特别地,若 entry 的时候传入了热点参数,那么 exit 的时候也一定要带上对应的参数(exit(count, args)),否则可能会有统计错误。这个时候不能使用 try-with-resources 的方式。另外通过 Tracer.trace(ex) 来统计异常信息时,由于 try-with-resources 语法中 catch 调用顺序的问题,会导致无法正确统计异常数,因此统计异常信息时也不能在 try-with-resources 的 catch 块中调用 Tracer.trace(ex)。

1.5.0 之前的版本的示例:

Entry entry = null;
// 务必保证finally会被执行
try {
  // 资源名可使用任意有业务语义的字符串
  entry = SphU.entry("自定义资源名");
  // 被保护的业务逻辑
  // do something...
} catch (BlockException e1) {
  // 资源访问阻止,被限流或被降级
  // 进行相应的处理操作
} finally {
  if (entry != null) {
    entry.exit();
  }
}

注意: SphU.entry(xxx) 需要与 entry.exit() 方法成对出现,匹配调用,否则会导致调用链记录异常,抛出 ErrorEntryFreeException 异常。

方式三:返回布尔值方式定义资源

SphO 提供 if-else 风格的 API。用这种方式,当资源发生了限流之后会返回 false,这个时候可以根据返回值,进行限流之后的逻辑处理。示例代码如下:

  // 资源名可使用任意有业务语义的字符串
  if (SphO.entry("自定义资源名")) {
    // 务必保证finally会被执行try {
      /**
      * 被保护的业务逻辑
      */
    } finally {
      SphO.exit();
    }
  } else {
    // 资源访问阻止,被限流或被降级// 进行相应的处理操作
  }

方式四:注解方式定义资源

Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandler 和 fallback 函数来进行限流之后的处理。示例:

// 原本的业务方法.
@SentinelResource(blockHandler = "blockHandlerForGetUser")
public User getUserById(String id) {
    throw new RuntimeException("getUserById command failed");
}

// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
public User blockHandlerForGetUser(String id, BlockException ex) {
    return new User("admin");
}

注意 blockHandler 函数会在原方法被限流/降级/系统保护的时候调用,而 fallback 函数会针对所有类型的异常。请注意 blockHandler 和 fallback 函数的形式要求。

方式五:异步调用支持

Sentinel 支持异步调用链路的统计。在异步调用中,需要通过 SphU.asyncEntry(xxx) 方法定义资源,并通常需要在异步的回调函数中调用 exit 方法。以下是一个简单的示例:

try {
    AsyncEntry entry = SphU.asyncEntry(resourceName);

    // 异步调用.
    doAsync(userId, result -> {
        try {
            // 在此处处理异步调用的结果.
        } finally {
            // 在回调结束后 exit.
            entry.exit();
        }
    });
} catch (BlockException ex) {
    // Request blocked.// Handle the exception (e.g. retry or fallback).
}

2、主流框架的资源是怎么默认创建?

Dubbo:

1、添加依赖
sentinel-apache-dubbo3-adapter(兼容 Apache Dubbo 3.0.5 及以上版本,自 Sentinel 1.8.5 开始支持)
sentinel-apache-dubbo-adapter(兼容 Apache Dubbo 2.7.x 及以上版本,自 Sentinel 1.5.1 开始支持) 
sentinel-dubbo-adapter(兼容 Dubbo 2.6.x 版本)

SentinelDubboConsumerFilter类

在这里插入图片描述
可以看出,这种写法和方法二中1.5.0之前的写法是一样的。

Web Servlet:

1、添加依赖
sentinel-web-servlet

看清这段代码需要的前置知识:SpringMVC中的Interceptor拦截器是链式的,可以同时存在多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行。所有的Interceptor中的preHandle方法都会在Controller方法调用之前调用。afterCompletion该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行,也就是调用了controller方法中的业务代码后执行的。这个方法的主要作用是用于清理资源的。

从源码中可以看出,SpringMVC在创建sentinel的资源是在preHandle这个方法中,清除是在afterCompletion方法中。

AbstractSentinelInterceptor类

在这里插入图片描述
在这里插入图片描述

3、为什么清除sentinel资源是在调用方法之后?

在这里插入图片描述
1、这里对业务异常进行添加。
还记得sentinel中有针对异常数量的熔断机制,就是在这里添加业务异常,而sentinel的规则异常则在preHandle进行了捕获以及处理。
2、这里为什么要对entry进行退出呢?
因为sentinel在处理流程时是会用到一些使用了static修饰的map、list等集合,在entry退出时需要将这些数据清空,不然会造成内存溢出。

4、还有那些主流框架有适配?

可以从源码中查看以下框架都是有做适配的(截至1.8.5版本)
在这里插入图片描述

5、sentinel中资源都存在哪里?

sentinel中的资源都存在NodeSelectorSlot类中,
1、使用了双重校验的单例模式
2、为什么hashmap要重新创建,而不是直接新增呢?
个人觉得是节省内存,用多少就使用多少容量。因为hashmap的扩容是两倍扩容,所以越到后面,扩容的容量就越大,造成空闲内存的几率就越大。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sentinel-dashboard-1.8.2是一个开源的项目,用于监控和管理Sentinel的规则、实时流量、集群节点等信息。它是一个基于Java开发的Web应用程序,采用了Spring Boot框架和Vue.js前端框架。 首先,sentinel-dashboard-1.8.2源码的结构非常清晰和模块化。它分为后端和前端两部分,后端代码位于sentinel-dashboard模块,前端代码位于sentinel-dashboard-frontend模块。这种结构使得代码的维护和扩展变得更加容易。 在后端部分,sentinel-dashboard-1.8.2源码中包含了一系列的Java类,用于实现Sentinel的规则管理、实时数据统计和集群节点的管理等功能。它提供了RESTful的接口用于前端页面的数据获取和交互。这些Java类使用了Spring框架提供的注解和特性,使得代码简洁、易读和易于维护。 在前端部分,sentinel-dashboard-1.8.2源码中的前端代码采用了Vue.js框架进行开发。它使用了一系列的组件来实现不同的功能模块,如规则管理、流量统计、集群节点管理等。前端页面具有良好的交互性和可视化效果,可以方便地进行规则的配置和流量的监控。 另外,sentinel-dashboard-1.8.2源码还使用了一些开源的技术和库,如Redis、MyBatis等,以提供更好的性能和扩展性。 总结来说,sentinel-dashboard-1.8.2源码是一个功能丰富、结构清晰和易于维护的开源项目。通过深入研究和理解源码,开发人员可以对Sentinel的规则管理和流量监控等核心功能有更深入的了解,并根据自己的需求进行二次开发和定制化操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值