Código fuente de Sentinel 9-sistema de protección SystemSlot y control de autoridad AuthoritySlot

Bienvenidos a todos a prestar atención a  github.com/hsfxuebao  , espero que les sea útil. Si creen que es posible, hagan clic en Estrella.

1. Ranura del sistema

La limitación de corriente adaptable del sistema Sentinel controla el tráfico de ingreso de la aplicación desde la dimensión general, combinado con los indicadores de monitoreo de varias dimensiones, como la carga de la aplicación, el uso de la CPU, el RT promedio general, el QPS de ingreso y la cantidad de subprocesos simultáneos, a través de una estrategia de control de flujo adaptable. , 让系统的入口流量和系统的负载达到一个平衡, para que el sistema pueda funcionar con el máximo rendimiento tanto como sea posible mientras se garantiza la estabilidad general del sistema.

La limitación de corriente adaptativa del sistema Sentinel se refiere a la TCP BBRimplementación y hace un balance de acuerdo con las solicitudes que el sistema puede manejar y las solicitudes entrantes, en lugar de limitar la corriente a través de una carga del sistema, su objetivo final es evitar que el sistema sea abrumado. , mejorar el rendimiento del sistema, en lugar de que la carga debe ser inferior a un cierto umbral

1.1 Reglas del sistema

Las reglas de protección del sistema se controlan desde el tráfico de entrada a nivel de la aplicación, y los indicadores de la aplicación se monitorean desde varias dimensiones, como la carga de una sola máquina, el uso de la CPU, el RT promedio, el QPS de entrada y la cantidad de subprocesos simultáneos, de modo que el sistema puede funcionar al máximo rendimiento tanto como sea posible, al tiempo que garantiza la estabilidad general del sistema.

Se aplican reglas de protección del sistema 整体维度, no de recursos dimensionales, y 仅对入口流量生效. El tráfico de ingreso se refiere al tráfico ( EntryType.IN) que ingresa a la aplicación, como las solicitudes recibidas por los servicios web o los servidores Dubbo, que son todos tráfico de ingreso.

índice ilustrar
Adaptable a la carga (solo válido para máquinas tipo Linux/Unix) La carga 1 del sistema se utiliza como índice heurístico para realizar la protección adaptativa del sistema. Cuando la carga1 del sistema supera el valor heurístico establecido y el número actual de subprocesos simultáneos del sistema supera la capacidad estimada del sistema, se activará la protección del sistema (fase BBR). La capacidad del sistema se calcula mediante maxQps * minRt del sistema. El valor de referencia de configuración es generalmente núcleos de CPU * 2.5.
Uso de CPU (versión 1.5.0+) Cuando el uso de la CPU del sistema supere el umbral, se activará la protección del sistema (rango de valores 0,0-1,0), que es más sensible.
TR medio La protección del sistema se activa cuando el RT promedio de todo el tráfico de entrada en una sola máquina alcanza el umbral, en milisegundos.
Número de subprocesos simultáneos La protección del sistema se activa cuando la cantidad de subprocesos simultáneos de todo el tráfico de entrada en una sola máquina alcanza el umbral.
QPS de ingreso La protección del sistema se activa cuando el QPS de todo el tráfico de entrada en una sola máquina alcanza el umbral.

1.2 Principio

imagen.pngImaginamos el proceso del sistema procesando solicitudes como una tubería de agua. La solicitud entrante es para verter agua en esta tubería de agua. Cuando el sistema procesa sin problemas, la solicitud no necesita ponerse en cola y pasa directamente a través de la tubería de agua. El RT de esta solicitud es el más corto; de lo contrario, cuando la solicitud se acumula, el tiempo para procesar la solicitud se convierte en: 排队时间 + 最短处理时间.

Si podemos asegurar la cantidad de agua en la tubería de agua y permitir que el agua fluya sin problemas, no habrá un aumento en las solicitudes en cola, es decir, la carga del sistema en este momento no se deteriorará más.

Usamos Tpara representar (la cantidad de agua dentro de la tubería de agua), RTpara representar el tiempo de procesamiento de la solicitud, y usamos P para representar el número de solicitudes entrantes, luego una solicitud desde que ingresa a la tubería de agua hasta que sale del agua. tubería, esta tubería de agua tendrá P * RT una solicitud. En otras palabras, cuando T ≈ QPS * Avg(RT)es , podemos pensar que la capacidad de procesamiento del sistema y la cantidad de solicitudes entrantes han alcanzado un equilibrio, y la carga del sistema no se deteriorará más.

El siguiente problema es que el nivel de agua de la tubería de agua puede alcanzar un punto de equilibrio, pero este punto de equilibrio solo puede garantizar que el nivel de agua de la tubería de agua no continúe aumentando, pero todavía hay un problema, es decir, antes llegando al punto de equilibrio, la tubería de agua ha acumulado la cantidad de agua. Si el agua en la tubería de agua ya está en un orden de magnitud, entonces la cantidad de agua permitida por el sistema en este momento solo puede pasar lentamente, el RT será grande y el agua acumulada en la tubería de agua permanecerá; entonces desperdiciará la potencia de procesamiento del sistema.

Cuando el caudal en la entrada se mantiene en el valor máximo del caudal que sale de la tubería de agua, se puede maximizar la capacidad de procesamiento de la tubería de agua.

1.3 Ejemplo de uso de limitación de corriente adaptable

public class SystemGuardDemo {
 
    private static AtomicInteger pass = new AtomicInteger();
    private static AtomicInteger block = new AtomicInteger();
    private static AtomicInteger total = new AtomicInteger();
 
    private static volatile boolean stop = false;
    private static final int threadCount = 100;
 
    private static int seconds = 60 + 40;
 
    public static void main(String[] args) throws Exception {
        
        tick();
        //初始化规则参数
        initSystemRule();
        //开启线程执行流量调用
        for (int i = 0; i < threadCount; i++) {
            Thread entryThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        Entry entry = null;
                        try {
                            entry = SphU.entry("methodA", EntryType.IN);
                            pass.incrementAndGet();
                            try {
                                TimeUnit.MILLISECONDS.sleep(20);
                            } catch (InterruptedException e) {
                                // ignore
                            }
                        } catch (BlockException e1) {
                            block.incrementAndGet();
                            try {
                                TimeUnit.MILLISECONDS.sleep(20);
                            } catch (InterruptedException e) {
                                // ignore
                            }
                        } catch (Exception e2) {
                            // biz exception
                        } finally {
                            total.incrementAndGet();
                            if (entry != null) {
                                entry.exit();
                            }
                        }
                    }
                }
 
            });
            entryThread.setName("working-thread");
            entryThread.start();
        }
    }
 
    private static void initSystemRule() {
        List<SystemRule> rules = new ArrayList<SystemRule>();
        SystemRule rule = new SystemRule();
        // max load is 3
        rule.setHighestSystemLoad(3.0);
        // max cpu usage is 60%
        rule.setHighestCpuUsage(0.6);
        // max avg rt of all request is 10 ms
        rule.setAvgRt(10);
        // max total qps is 20
        rule.setQps(20);
        // max parallel working thread is 10
        rule.setMaxThread(10);
 
        rules.add(rule);
        SystemRuleManager.loadRules(Collections.singletonList(rule));
    }
 
    private static void tick() {
        Thread timer = new Thread(new TimerTask());
        timer.setName("sentinel-timer-task");
        timer.start();
    }
 
    static class TimerTask implements Runnable {
        @Override
        public void run() {
            System.out.println("begin to statistic!!!");
            long oldTotal = 0;
            long oldPass = 0;
            long oldBlock = 0;
            while (!stop) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                }
                long globalTotal = total.get();
                long oneSecondTotal = globalTotal - oldTotal;
                oldTotal = globalTotal;
 
                long globalPass = pass.get();
                long oneSecondPass = globalPass - oldPass;
                oldPass = globalPass;
 
                long globalBlock = block.get();
                long oneSecondBlock = globalBlock - oldBlock;
                oldBlock = globalBlock;
 
                System.out.println(seconds + ", " + TimeUtil.currentTimeMillis() + ", total:"
                    + oneSecondTotal + ", pass:"
                    + oneSecondPass + ", block:" + oneSecondBlock);
                if (seconds-- <= 0) {
                    stop = true;
                }
            }
            System.exit(0);
        }
    }
}
复制代码

1.4 Análisis del código fuente

1.4.1 Entrada de limitación de corriente adaptativa SystemSlot

@Spi(order = Constants.ORDER_SYSTEM_SLOT)
public class SystemSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
                      boolean prioritized, Object... args) throws Throwable {
        // todo entry方法中调用SystemRuleManager.checkSystem方法,这里是自适应限流的关键点
        SystemRuleManager.checkSystem(resourceWrapper, count);
        // 在职责链上继续调用下一个slot节点。
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }

    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
        fireExit(context, resourceWrapper, count, args);
    }

}
复制代码

1.4.2 Administrador de reglas del sistema

1.4.2.1 Diagrama de clases

sentinel自适应限流通过SystemRuleManager类来实现,它里面封装了BBR算法的实现,以及系统指标的采集,接下来我们看下它的类图以及核心属性。 imagen.png

我们来看下SystemRuleManager的一些属性:

//系统最大负载
private static volatile double highestSystemLoad = Double.MAX_VALUE;
/**
 * cpu usage, between [0, 1]
 */
 //CPU使用率,介于[0,1]之间
private static volatile double highestCpuUsage = Double.MAX_VALUE;
private static volatile double qps = Double.MAX_VALUE;
//最大延迟
private static volatile long maxRt = Long.MAX_VALUE;
//最大线程数
private static volatile long maxThread = Long.MAX_VALUE;
//采集系统cpu load、cpu使用率的实现。
private static SystemStatusListener statusListener = null;
复制代码

1.4.2.2 核心方法源码分析

  • checkSystem:

    public static void checkSystem(ResourceWrapper resourceWrapper, int count) throws BlockException {
        // 检查资源是否为空,如果为空直接返回
        if (resourceWrapper == null) {
            return;
        }
        // Ensure the checking switch is on.
        // 判断系统自适应限流是否开启,未开启直接返回。
        if (!checkSystemStatus.get()) {
            return;
        }
    
        // for inbound traffic only
        // 判断资源的流量是否为入口流量,Sentinel系统自适应限流只对入口流量生效
        if (resourceWrapper.getEntryType() != EntryType.IN) {
            return;
        }
    
        // total qps
        // 从Constants.ENTRY_NODE获取当前qps,如果当前qps大于SystemRule配置的阈值,直接抛SystemBlockException异常
        double currentQps = Constants.ENTRY_NODE == null ? 0.0 : Constants.ENTRY_NODE.passQps();
        if (currentQps + count > qps) {
            throw new SystemBlockException(resourceWrapper.getName(), "qps");
        }
    
        // total thread
        // 从Constants.ENTRY_NODE获取当前thread,如果当前thread大于SystemRule配置的阈值,直接抛SystemBlockException 异常
        int currentThread = Constants.ENTRY_NODE == null ? 0 : Constants.ENTRY_NODE.curThreadNum();
        if (currentThread > maxThread) {
            throw new SystemBlockException(resourceWrapper.getName(), "thread");
        }
    
        // 从Constants.ENTRY_NODE获取当前avgRT,如果当前avgRT大于SystemRule配置的阈值,直接抛SystemBlockException异常
        double rt = Constants.ENTRY_NODE == null ? 0 : Constants.ENTRY_NODE.avgRt();
        if (rt > maxRt) {
            throw new SystemBlockException(resourceWrapper.getName(), "rt");
        }
    
        // load. BBR algorithm.
        // 进行bbr算法校验
        // 校验系统负载开关是否打开,当前系统load是否大于配置的系统load,如果都满足则继续校验
        if (highestSystemLoadIsSet && getCurrentSystemAvgLoad() > highestSystemLoad) {
            // 调用checkBbr方法,之前我们有说过系统通过流量:T ≈ QPS * Avg(RT)时
            // 我们可以认为系统的处理能力和允许进入的请求个数达到了平衡,所以checkBbr方法计算的公式以秒为单位:T=QPS*RT/1000。
            // 如果当前线程数大于T,则进行拦截
            if (!checkBbr(currentThread)) {
                throw new SystemBlockException(resourceWrapper.getName(), "load");
            }
        }
    
        // cpu usage
        // 判断当前CPU使用率是否大于SystemRule配置的阈值,如果是则抛出SystemBlockException异常
        if (highestCpuUsageIsSet && getCurrentCpuUsage() > highestCpuUsage) {
            throw new SystemBlockException(resourceWrapper.getName(), "cpu");
        }
    }
    
    //bbr算法
    private static boolean checkBbr(int currentThread) {
        if (currentThread > 1 &&
            currentThread > Constants.ENTRY_NODE.maxSuccessQps() * Constants.ENTRY_NODE.minRt() / 1000) {
            return false;
        }
        return true;
    }
    复制代码
  • Constants.ENTRY_NODE

    • 自适应限流使用的是全局的ClusterNode节点,这就是说自适应限流的维度是整个系统。
    public final static ClusterNode ENTRY_NODE = new ClusterNode(TOTAL_IN_RESOURCE_NAME, ResourceTypeConstants.COMMON);
    复制代码
  • 系统指标采集运行

    @SuppressWarnings("PMD.ThreadPoolCreationRule")
    private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1,
        new NamedThreadFactory("sentinel-system-status-record-task", true));
    
    static {
        checkSystemStatus.set(false);
        statusListener = new SystemStatusListener();
        scheduler.scheduleAtFixedRate(statusListener, 0, 1, TimeUnit.SECONDS);
        currentProperty.addListener(listener);
    }
    复制代码

    SystemRuleManager类中定义了ScheduledExecutorService线程池,在静态块里面触发SystemStatusListener类的运行,运行时间是1秒钟一次,这表示Sentinel的自适应保护信息采集为1秒钟采集系统load、cpu信息。

1.4.3 系统指标采集源码分析

SystemStatusListener 类图:

imagen.png

该类实现了runnable接口,他通过一个线程每隔一秒执行一次load、cpu usage信息的采集。

  • 源码分析
public class SystemStatusListener implements Runnable {

    volatile double currentLoad = -1;
    volatile double currentCpuUsage = -1;

    volatile String reason = StringUtil.EMPTY;

    volatile long processCpuTime = 0;
    volatile long processUpTime = 0;

    public double getSystemAverageLoad() {
        return currentLoad;
    }

    public double getCpuUsage() {
        return currentCpuUsage;
    }

    @Override
    public void run() {
        try {
            // Sentinel通过jdk:ManagementFactory类获取系统load、cpu等信息。
            OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class);
            // 获取当前系统load。
            currentLoad = osBean.getSystemLoadAverage();

            /*
             * Java Doc copied from {@link OperatingSystemMXBean#getSystemCpuLoad()}:</br>
             * Returns the "recent cpu usage" for the whole system. This value is a double in the [0.0,1.0] interval.
             * A value of 0.0 means that all CPUs were idle during the recent period of time observed, while a value
             * of 1.0 means that all CPUs were actively running 100% of the time during the recent period being
             * observed. All values between 0.0 and 1.0 are possible depending of the activities going on in the
             * system. If the system recent cpu usage is not available, the method returns a negative value.
             */

            // 获取当前系统cpu usage
            double systemCpuUsage = osBean.getSystemCpuLoad();

            // calculate process cpu usage to support application running in container environment
            RuntimeMXBean runtimeBean = ManagementFactory.getPlatformMXBean(RuntimeMXBean.class);
            // 获取系统cpu运行时间
            long newProcessCpuTime = osBean.getProcessCpuTime();
            // 获取当前jvm cpu运行时间
            long newProcessUpTime = runtimeBean.getUptime();
            // 获取系统cpu核心数
            int cpuCores = osBean.getAvailableProcessors();
            long processCpuTimeDiffInMs = TimeUnit.NANOSECONDS
                    .toMillis(newProcessCpuTime - processCpuTime);
            long processUpTimeDiffInMs = newProcessUpTime - processUpTime;
            // 计算CPU使用率
            double processCpuUsage = (double) processCpuTimeDiffInMs / processUpTimeDiffInMs / cpuCores;
            processCpuTime = newProcessCpuTime;
            processUpTime = newProcessUpTime;

            currentCpuUsage = Math.max(processCpuUsage, systemCpuUsage);

            if (currentLoad > SystemRuleManager.getSystemLoadThreshold()) {
                writeSystemStatusLog();
            }
        } catch (Throwable e) {
            RecordLog.warn("[SystemStatusListener] Failed to get system metrics from JMX", e);
        }
    }

    private void writeSystemStatusLog() {
        StringBuilder sb = new StringBuilder();
        sb.append("Load exceeds the threshold: ");
        sb.append("load:").append(String.format("%.4f", currentLoad)).append("; ");
        sb.append("cpuUsage:").append(String.format("%.4f", currentCpuUsage)).append("; ");
        sb.append("qps:").append(String.format("%.4f", Constants.ENTRY_NODE.passQps())).append("; ");
        sb.append("rt:").append(String.format("%.4f", Constants.ENTRY_NODE.avgRt())).append("; ");
        sb.append("thread:").append(Constants.ENTRY_NODE.curThreadNum()).append("; ");
        sb.append("success:").append(String.format("%.4f", Constants.ENTRY_NODE.successQps())).append("; ");
        sb.append("minRt:").append(String.format("%.2f", Constants.ENTRY_NODE.minRt())).append("; ");
        sb.append("maxSuccess:").append(String.format("%.2f", Constants.ENTRY_NODE.maxSuccessQps())).append("; ");
        RecordLog.info(sb.toString());
    }
}
复制代码

1.5 Sentinel后台配置

配置系统保护规则: imagen.png

那么,后台配置是怎么映射进入的呢?

SystemRuleManager中,有一个静态方法(loadRules(List<SystemRule> rules) )去初始化SystemRule配置。

  public static void loadRules(List<SystemRule> rules) {
        currentProperty.updateValue(rules);
  }
复制代码

而在更新currentProperty的时候,实质是通知观察者去更新,这里使用的是观察者模式

public class DynamicSentinelProperty<T> implements SentinelProperty<T> {
    //观察者
    protected Set<PropertyListener<T>> listeners = Collections.synchronizedSet(new HashSet<PropertyListener<T>>());
    //更新值
    @Override
    public boolean updateValue(T newValue) {
        //如果两个值一样,则返回false,不修改
        if (isEqual(value, newValue)) {
            return false;
        }
        value = newValue;
        //通知各个观察者
        for (PropertyListener<T> listener : listeners) {
            listener.configUpdate(newValue);
        }
        return true;
    }

    //判断两个对象是否一致
    private boolean isEqual(T oldValue, T newValue) {
        if (oldValue == null && newValue == null) {
            return true;
        }
        if (oldValue == null) {
            return false;
        }
        return oldValue.equals(newValue);
    }
    public void close() {
        listeners.clear();
    }
}
复制代码

这里的观察者为**SystemPropertyListener**,在SystemRuleManager的静态方法区已经添加进去。

public class SystemRuleManager {
    //观察者,当systemRule配置发生变更时,会通知该Listener
    private final static SystemPropertyListener listener = new SystemPropertyListener();
    static {
        checkSystemStatus.set(false);
        statusListener = new SystemStatusListener();
        scheduler.scheduleAtFixedRate(statusListener, 5, 1, TimeUnit.SECONDS);
        //添加观察者
        currentProperty.addListener(listener);
    }
}
复制代码

而在SystemPropertyListener更新的时候,会先关闭系统检查,当配置修改完成之后,再启用。

 static class SystemPropertyListener extends SimplePropertyListener<List<SystemRule>> {
    @Override
    public void configUpdate(List<SystemRule> rules) {
        //恢复到默认状态
        restoreSetting();
        if (rules != null && rules.size() >= 1) {
            for (SystemRule rule : rules) {
                //加载配置
                loadSystemConf(rule);
            }
        } else {
            checkSystemStatus.set(false);
        }
    }
    //重置配置信息
    protected void restoreSetting() {
        checkSystemStatus.set(false);
        // should restore changes
        highestSystemLoad = Double.MAX_VALUE;
        highestCpuUsage = Double.MAX_VALUE;
        maxRt = Long.MAX_VALUE;
        maxThread = Long.MAX_VALUE;
        qps = Double.MAX_VALUE;
        highestSystemLoadIsSet = false;
        maxRtIsSet = false;
        maxThreadIsSet = false;
        qpsIsSet = false;
    }
}
复制代码

修改则判断是否小于默认配置,由于之前已经重新初始化过了,所以如果有修改,肯定会比默认的值小。

public static void loadSystemConf(SystemRule rule) {
    boolean checkStatus = false;
    if (rule.getHighestSystemLoad() >= 0) {
        highestSystemLoad = Math.min(highestSystemLoad, rule.getHighestSystemLoad());
        highestSystemLoadIsSet = true;
        checkStatus = true;
    }
    if (rule.getHighestCpuUsage() >= 0) {
        highestCpuUsage = Math.min(highestCpuUsage, rule.getHighestCpuUsage());
        highestCpuUsageIsSet = true;
        checkStatus = true;
    }
    if (rule.getAvgRt() >= 0) {
        maxRt = Math.min(maxRt, rule.getAvgRt());
        maxRtIsSet = true;
        checkStatus = true;
    }
    if (rule.getMaxThread() >= 0) {
        maxThread = Math.min(maxThread, rule.getMaxThread());
        maxThreadIsSet = true;
        checkStatus = true;
    }
    if (rule.getQps() >= 0) {
        qps = Math.min(qps, rule.getQps());
        qpsIsSet = true;
        checkStatus = true;
    }
    checkSystemStatus.set(checkStatus);
}
复制代码

配置加载完毕,如果有SystemRule配置,则将checkSystemStatus改为true

1.6 总结

经过以上源码分析,我们可以得出几点结论:

  • Sentinel自适应限流原理采用了BBR算法
  • Sentinel自适应限流维度是整个系统,当系统负载过大时会触发限流。
  • Sentinel自适应限流信息采集指标为1秒钟一次。
  • Los indicadores recopilados por Sentinel se encuentran a nivel del sistema operativo, por lo que si desea utilizar la limitación de corriente adaptativa, se recomienda que el servidor de aplicaciones no implemente otros servicios con mucha carga.

2. Ranura de autoridad

AuthorizationSlotDe acuerdo con la lista blanca y negra, se realiza el control de la lista blanca y negra; si el recurso está configurado AuthorityRule, se juzga de acuerdo con la política si el origen de la solicitud (origen) de la solicitud del recurso está en la regla de configuración LimitApp( (,)隔开) y el criterio de política, si se pasa el cheque.

  • si está en la lista blanca

    • Determine si el origen está en limitApp, si lo está, devuelva verdadero, de lo contrario, devuelva falso
  • Si está en la lista negra

    • Determine si el origen está en limitApp, si lo está, devuelva falso, de lo contrario, devuelva verdadero
public class AuthoritySlot extends AbstractLinkedProcessorSlot<DefaultNode> {
    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args)
        throws Throwable {
        //检查黑白名单
        checkBlackWhiteAuthority(resourceWrapper, context);
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }

    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
        fireExit(context, resourceWrapper, count, args);
    }

    void checkBlackWhiteAuthority(ResourceWrapper resource, Context context) throws AuthorityException {
        //获取认证的规则
        Map<String, List<AuthorityRule>> authorityRules = AuthorityRuleManager.getAuthorityRules();
        if (authorityRules == null) {
            return;
        }
        //根据resourceName获取该资源下对应的规则
        List<AuthorityRule> rules = authorityRules.get(resource.getName());
        if (rules == null) {
            return;
        }
        for (AuthorityRule rule : rules) {
            //认证检查
            if (!AuthorityRuleChecker.passCheck(rule, context)) {
                throw new AuthorityException(context.getOrigin(), rule);
            }
        }
    }
}
复制代码

La lógica de verificación está en AuthorityRuleChecker:

final class AuthorityRuleChecker {

    static boolean passCheck(AuthorityRule rule, Context context) {

        String requester = context.getOrigin();
        // 获取orgin请求来源,如果为请求来源为null或者limitApp为null则直接返回通过
        if (StringUtil.isEmpty(requester) || StringUtil.isEmpty(rule.getLimitApp())) {
            return true;
        }

        //判断limitApp是否含有origin
        int pos = rule.getLimitApp().indexOf(requester);
        boolean contain = pos > -1;
        if (contain) {
            boolean exactlyMatch = false;
            String[] appArray = rule.getLimitApp().split(",");
            for (String app : appArray) {
                if (requester.equals(app)) {
                    exactlyMatch = true;
                    break;
                }
            }

            contain = exactlyMatch;
        }
        //根据策略处理是否包含,判断是否通过
        int strategy = rule.getStrategy();
        if (strategy == RuleConstant.AUTHORITY_BLACK && contain) {
            return false;
        }

        if (strategy == RuleConstant.AUTHORITY_WHITE && !contain) {
            return false;
        }
        return true;
    }

    private AuthorityRuleChecker() {}
}
复制代码

AuthorityRuleLa actualización de la configuración es la misma que el método SystemSlotdependiente de AuthorityRuleManagerla actualización.loadRules

2.1 Configuración de fondo de Sentinel

imagen.png

En el código fuente de Sentinel versión 1.8, dado que orion es una cadena vacía por defecto cuando se crea Context, si queremos verificar el control de permisos, necesitamos cambiar esto a una fuente específica de orion. El código es el siguiente com.alibaba.csp.sentinel.CtSph.InternalContextUtil#internalEnter(java.lang.String):imagen.png

Artículo de referencia

Dirección de github del código fuente de Sentinel1.8.5 (nota)
Análisis del código fuente de
Sentinel Sitio web oficial de Sentinel Lectura del código fuente de Sentinel
:
el principio de la protección adaptativa del sistema en un lenguaje sencillo AuthoritySlot

Supongo que te gusta

Origin juejin.im/post/7150074488195907615
Recomendado
Clasificación