java中sentinel是啥_Sentinel之重要类介绍

微信公众号: 房东的小黑黑

路途随遥远,将来更美好

学海无涯,大家一起加油!

该篇是分析Sentinel原理的第一篇文章。由于接触该中间件的时间较短,可能会出现一些理解偏差。希望大家积极交流改正。文章主要内容主要是阅读了一些大神的文章,并加上自己的理解写的。

主要参考的文章是在Sentinel的github中找到的,具体地址如下: 参考文章

Sentinel的主要功能就是流量控制和熔断降级。具体概念在之前写的有关dubbo的限流和熔断中已介绍,这里就不再赘述了。

先简单举一个如何使用的例子。

public static void main(String[] args) {

try {

Context context=ContextUtil.enter("context1");

Entry entry=SphU.entry("HelloWorld");

entry.exit();

ContextUtil.exit();

} catch (BlockException ex) {

// 处理被流控的逻辑

System.out.println("blocked!");

}catch (Exception e){

e.printStackTrace();

}

}

复制代码

try (Entry entry = SphU.entry("HelloWorld")) {

// Your business logic here.

System.out.println("hello world");

} catch (BlockException e) {

// Handle rejected request.

e.printStackTrace();

}

复制代码

上面是两个典型的流量控制例子。读者会发现有一处很明显的不同,即Context类,它用来表示一个调用的上下文,实际不加也影响,具体的在后面分析。

例子中还有一个重要的类Entry,里面的参数HelloWorld可以看做一个资源名,在具体使用之前,我们需要自己定义一些规则。 可以使用下面的方法定义一个关于流量控制的规则:

private void initFlowQpsRule() {

List rules = new ArrayList<>();

FlowRule rule = new FlowRule(resourceName);

// set limit qps to 20

rule.setCount(20);

rule.setGrade(RuleConstant.FLOW_GRADE_QPS);

rule.setLimitApp("default");

rules.add(rule);

FlowRuleManager.loadRules(rules);

}

复制代码

当调用SphU.entry("HelloWorld")时,如果没有报异常,说明可以执行自己的业务代码;如果报错,说明当前不符合条件,拒绝执行后面的业务代码。

几个核心概念

Resource

资源是Sentinel中的一个核心概念,它可以是应用程序提供的服务,也可以是应用程序调用的其他服务,也可以是一段代码。当某个服务的请求非常多,经常被陡增的流量冲垮,造成性能降低或者不可用,这时我们可以定义一个Sentinel的资源,通过该资源对请求进行调整,进行流量控制和服务降级。

在Sentinel中表示具体资源的类是ResourceWrapper。

public abstract class ResourceWrapper {

# 资源名

protected final String name;

# 是入站还是出站

protected final EntryType entryType;

# 资源类型

protected final int resourceType;

复制代码

Entry

entry是sentinel中用来表示是否通过限流的一个凭证,如果能正常返回,则说明你可以访问被sentinel保护的后方服务,否则sentinel会抛出一个BlockException。另外,它保存了本次执行entry()方法的一些基本信息。每一次资源调用都会创建一个Entry。

public abstract class Entry implements AutoCloseable {

# 当前Entry的创建时间,主要用来后期计算rt

private long createTime;

# 当前Entry所关联的node,该node主要是记录了当前context下该资源的统计信息

private Node curNode;

# 当前Entry的调用来源,通常是调用方的应用名称

private Node originNode;

private Throwable error;

# 当前Entry所关联的资源

protected ResourceWrapper resourceWrapper;

复制代码

class CtEntry extends Entry {

protected Entry parent = null;

protected Entry child = null;

protected ProcessorSlot chain;

protected Context context;

复制代码

可能这样介绍有些抽象,我借鉴一个别人的例子,很形象。

b1776135c22fb51405e465c634a7358b.png

49fb8bbf52a03774b3c896e2feb1ccdb.png

从图中我们可以看出有一个user-center --> getUserInfo --> getOrderInfo的调用链路。根据代码,我们知道user-center是一个上下文名称,getUserInfo和getOrderInfo是两个资源名称。

上面例子中在一个Entry中又调用了一个Entry,存在链路,当在一个上下文中多次调用Sphu.entry()方法,就会创建一个调用树,这个树的节点之间是通过parent和child关系维持的。

Node

node中保存了资源的实时统计数据,例如:passQps,blockQps,rt等实时数据。

c1161de32fbdc39236842b2b965023a0.png

node是一个接口,它有一个实现类StatisticNode,但是StatisticNode本身也有两个子类,一个是DefaultNode,另一个是ClusterNode,DefaultNode又有一个子类叫EntranceNode。

EntranceNode是每个上下文的入口,该节点是直接挂在root下,是全局唯一的,每一个context都有一个对应的entranceNode。DefaultNode是记录当前实时数据的,每个DefaultNode都关联着一个资源和ClusterNode。有着相同资源的defaultNode,它们关联着同一个clusterNode。

public interface Node extends OccupySupport, DebugSupport {

long totalRequest();

long totalPass();

long totalSuccess();

复制代码

public class DefaultNode extends StatisticNode {

private ResourceWrapper id;

private volatile Set childList = new HashSet<>();

private ClusterNode clusterNode;

复制代码

Context

public class Context {

//上下文名称

private final String name;

//当前调用链的入口节点

private DefaultNode entranceNode;

//调用链中当前正在处理的entry

private Entry curEntry;

//此上下文的来源(通常表示不同的调用方,例如服务使用者名称或来源IP)

private String origin = "";

复制代码

Context代表调用链路上下文,贯穿一次调用链路中的所有Entry。

每次调用SphU.entry()都需要在一个context中执行,如果没有当前执行时还没有context,那么框架会使用默认的context,即sentinel_default_context。

Context是保存在ThreadLocal中的,每次执行的时候会优先到ThreadLocal中获取。如果Context为null才会再次去创建一个context。

当Entry执行exit方法时,当当前的entry的parent为null时,说明当前entry是最上层的节点,该上下文的entry已执行完,所以在此时需要将context设置为null,从ThreadLocal中清除。

以上就是比较重要的实体类介绍。

参考文章:

Sentinel核心类解析

Sentinel原理-实体类

阿里Sentinel源码解析

本文使用 mdnice 排版

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sentinel是一款开源的分布式系统的流量控制和熔断降级工具,可以帮助我们快速地实现系统的高可用和稳定性。在Java使用Sentinel需要进行如下步骤: 1. 引入Sentinel的依赖 在pom.xml添加如下依赖: ```xml <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> <version>1.8.0</version> </dependency> ``` 2. 配置Sentinel的规则 在resources目录下新建一个sentinel目录,在其创建一个block.qps文件,用于配置流量控制规则,示例代码如下: ```json [ { "resource": "com.example.demo.controller.UserController:queryUser", "limitApp": "default", "grade": 1, "count": 10, "strategy": 0, "controlBehavior": 0, "clusterMode": false } ] ``` 在上面的代码,我们配置了一个名为com.example.demo.controller.UserController:queryUser的资源,限制每秒请求次数不超过10次,如果超过了这个限制,则采用直接拒绝的方式进行流量控制。 3. 在代码使用Sentinel 在需要进行流量控制的方法上添加@SentinelResource注解,示例代码如下: ```java @RestController public class UserController { @GetMapping("/queryUser") @SentinelResource(value = "com.example.demo.controller.UserController:queryUser", blockHandler = "handleBlock") public String queryUser() { // 查询用户信息 return "User Info"; } public String handleBlock(BlockException ex) { // 处理流量控制的逻辑 return "请求过于频繁,请稍后再试!"; } } ``` 在上面的代码,我们在queryUser方法上添加了@SentinelResource注解,并指定了资源名称,同时指定了当该资源被流量控制时的处理方法handleBlock,该方法会返回一个提示信息。 4. 启动Sentinel Dashboard Sentinel Dashboard是一个可视化的管理界面,可以方便地查看系统的流量控制规则和熔断降级状态,需要在网上下载Sentinel Dashboard的jar包并启动,启动命令如下: ```shell java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar ``` 其-Dcsp.sentinel.dashboard.server参数用于指定Sentinel Dashboard的地址,-Dproject.name参数用于指定当前项目的名称。 5. 验证流量控制效果 启动项目并访问http://localhost:8080/queryUser,当请求次数超过10次时,会返回“请求过于频繁,请稍后再试!”的提示信息。在Sentinel Dashboard的流量控制页面可以看到对应的流量控制记录。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值