JAVA微服务_sentinel

Sentinel 以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应过载保护、热点流量防护等多个维度保护服务的稳定性。
同hystrix相比,除了服务熔断,还可以进行服务降级、服务流控等。
sentinel有多种使用方式,常见的有单独使用dashboard、同Gateway结合使用、同Spring Cloud/Alibaba结合使用、同RPC组件结合使用等。建议结合项目选择。开源项目Ruoyi-Cloud选择结合Gateway使用。

在服务端用maven引入jar包;
控制面板dashboard可以从https://github.com/alibaba/Sentinel/releases下载sentinel-dashboard-$version.jar包。

Sentinel基本概念

  • 资源 resource:Sentinel中一切抽象成资源,服务、服务中的方法,甚至是一段代码,都可以被定义成资源,然后被Sentinel管理;
  • 规则 rules : 流量规则,熔断规则,负载规则,,,

五大规则

流控规则

降级规则
监控应用中资源调用请求,达到阈值时自动触发熔断降级。
热点规则

系统规则
系统自适应限流
授权规则
黑白名单控制

快速开始

本文以Spring Cloud Alibaba中引入Sentinel为例,其他方式引入请参考官方wiki。
在服务中引入Sentinel,然后在dashboard中配置规则。

<!-- SpringCloud Alibaba Sentinel -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

在配置文件中开启Sentinel

spring.cloud.sentinel.enabled=true
# 指定sentinel dashboard web地址
spring.cloud.sentinel.transport.dashboard=  #dashboard的ip:端口
#  指定snetinel组件和sentinel dashboard组件通信地址(用tcp更高效的通信,端口默认为8719)
spring.cloud.sentinel.transport.port=8719

DashBoard控制台方式

使用java -jar命令启动dashboard控制台:

java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar D:\sentinel\sentinel-dashboard-1.8.0.jar

Sentinel提供了一个可视化的操作平台,安装好之后,在浏览器中输入(http://localhost:8718 (opens new window))就可以访问了,默认的用户名和密码都是sentinel

dashboard在有一次调用发生后,才能在web界面看到服务(这算懒加载么?)
调用后sentinel才会产生资源调用日志,有日志生成后才会dashboard出现服务,多调用几次才会出现qps等信息。

启动参数说明:
-Dserver.port:指定启动的端口,默认8080
-Dproject.name:指定本服务的名称
-Dcsp.sentinel.dashboard.server:指定sentinel控制台的地址,用于将自己注册进入实现监控自己
-Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 “sentinel”,默认值为 “sentinel”
-Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 “123456”,默认值为 “sentinel”
-Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟,需要注意的是,部署多台控制台时,session 默认不会在各实例之间共享,这一块需要自行改造。

熔断 降级规则

用来避免服务雪崩。触发熔断后对该服务的调用不可用。
在dashboard中选择“降级规则”

Sentinel熔断策略

触发熔断(断路器打开)的三种策略
RT 根据请求响应时间熔断
异常比例
抛出的异常的比例。如设置为0.1,则比例超过10%时触发熔断
异常数

时间窗口(单位:秒)结束后,断路器关闭。

热点规则

也成为热点参数限流,对携带了指定参数的资源进行限流。
https://editor.csdn.net/md/?articleId=131038775,参数为articleId
只能使用QPS模式。

不能使用资源路径的方式配置,只能使用资源别名。
资源别名:在处理请求的方法上使用@SentinelResource(value="别名")注解指定别名。mvc模式的话就放在controller层方法上。

在[统计窗口时长]内,对带有第[参数索引]个参数的请求,超过阈值时进行限流。
参数索引从0开始计数,代表请求中的第几个参数。

@SentinelResource定义资源

@SentinelResource(value=“别名”, fallback=“”, blcokHandler=“限流处理method名”)
fallback处理业务异常,blockHandler处理限流。两参数的值都是指定方法名。
限流处理method例子:
注:该例子中controller层方法带Integer id参数

@Controller
@SentinelResource(value="别名", fallback="", blcokHandler="限流处理method名"public String controllerMethod(Integer id){
	//Method body...
}

private String blockHandler(Integer id, BlockException e){
	if(e instanceof FlowException){
		return "当前请求过于火爆,已被降级";
	}
	if(e instanceof DegradeException){
		return "当前请求过于火爆,已被降级";
	}
	if(e instanceof ParaFlowException){
		return "当前请求过于火爆,已被参数热点限流";
	}
	return "服务器过于火爆,请稍后再试捏~(づ ̄3 ̄)づ╭❤~kira";
}

@SentinelResource 注解不支持 private 方法。默认情况下,Sentinel 对控制资源的保护处理是直接抛出异常,这样对用户不友好,所以我们需要通过可选的异常处理 blockHandler 和 fallback 配置项处理一下异常信息。

  • blockHandler/blockHandlerClass: blockHandler 指定函数负责处理 BlockException 异常,可选项。blockHandler 函数默认需要和原方法在同一个类中,通过指定 blockHandlerClass 为对应类的 Class 对象,则可以指定其他类中的函数,但注意对应的函数必需为 static 函数,否则无法解析。

    blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型必须和原方法一致并且最后加一个类型为 BlockException 的异常参数。

    可以通过这种方式拿到请求发来的参数。
    @SentinelResource和blockHandler都要求public,是因为反射吗?不过blockerHandler应该不用反射吧,,直接调用似乎可以,,
    
  • fallback /fallbackClass: fallback 指定的函数负责处理业务运行的异常,可选项,fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。fallback 函数默认需要和原方法在同一个类中,通过指定 fallbackClass 为对应类的 Class 对象,则可以指定指定为其他类的函数,但注意对应的函数必需为 static 函数,否则无法解析。

fallback 函数的返回值类型必须与原函数返回值类型一致;方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
@SentinelResource 的 fallback 负责业务运行的异常,blockHandler 负责 sentinel 配置的违规。

流量控制(限流)

原理是监控应用流量的 QPS 或 并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被顺势的流量高峰冲垮,从而保障应用的高可用性;

  • Q: 怎么控制
    • A: dashboard设置规则时选择高级选项-流控模式
      • 直接 返回Blocked by Sentinel
      • 关联
      • 链路

流控模式 三种

配置资源:在编辑规则时设置的资源
关联资源:和配置资源相关联的资源

直接

当对配置资源的请求超过阈值时,对配置资源的请求的处理(三种处理方式在本文下一小节)

关联

当所关联的资源的请求超过阈值后,对当前资源进行的处理
如在以下例子中,当关联的"/aa"资源访问次数超过阈值,则"/demo"资源要受到流控处理
在这里插入图片描述

链路

对链路上的资源的处理

流控效果/处理方式 三种

注意:只适用于QPS限流

  • 快速失败
    • 直接拒绝请求并抛出异常FlowExcrption
  • Warm up
    • 冷启动,预热
    • 在一定时间(预热时长)内将系统逐渐拉至高水位
  • 排队等待 Rate Limiter
    • 同Warm up相比,特点为始终匀速处理
      注意:这一效果只针对QPS流控,并发线程数流控不支持。

排队等待的方式会以匀速排队方式严格控制请求通过的间隔时间,也就是让请求以均匀的速度通过,其余的排队等待,它还会让设置一个超时时间,当请求超过超时间时间还未处理,则会被丢弃。

对应的是漏桶算法,源码对应得类:com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController。该方式的作用如下图:

图片该方式主要用于处理间隔性突发的流量。假设某时刻来了大流量的请求,如果此时要处理所有请求,很可能会导致系统负载过高,影响稳定性。

但其实接下来几秒可能系统处于空闲状态,若直接把多余的请求丢弃则没有充分利用系统的处理能力,所以我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。

Sentinel 的 Rate Limiter 模式能在某一段时间间隔内以匀速方式处理这样的请求, 充分利用系统的处理能力, 也就是削峰填谷, 保证资源的稳定性。

Sentinel会以固定的间隔时间让请求通过, 访问资源,当请求到来时,如果当前请求距离上个通过的请求通过的时间间隔不小于预设值,则让当前请求通过;否则,计算当前请求的预期通过时间,如果该请求的预期通过时间大于规则预设的 timeout 时间,则该请求会等待直到预设时间到来通过;反之,则马上抛出阻塞异常。

下图能很形象的展示这种场景的削峰填谷的作用:X轴代表时间,Y轴代表系统处理的请求

图片

结合Gateway

Sentinel 支持对 Spring Cloud Gateway、Netflix Zuul 等主流的 API Gateway 进行限流。

在Gateway模块中添加依赖:

<!-- SpringCloud Alibaba Sentinel -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
		
<!-- SpringCloud Alibaba Sentinel Gateway -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

限流

Gateway配置类中添加限流规则,注册全局SentinelGatewayFilter()过滤器,
以一分钟访问超过三次则限流为例:

import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;

/**
 * 网关限流配置
 * 
 */
@Configuration
public class GatewayConfig
{
    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter()
    {
        return new SentinelGatewayFilter();
    }

    @PostConstruct
    public void doInit()
    {
        // 加载网关限流规则
        initGatewayRules();
    }

    /**
     * 网关限流规则   
     */
    private void initGatewayRules()
    {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("ruoyi-system")
                .setCount(3) // 限流阈值
                .setIntervalSec(60)); // 统计时间窗口,单位是秒,默认是 1 秒
        // 加载网关限流规则
        GatewayRuleManager.loadRules(rules);
    }
}
  • 这种小事就不能交给配置文件吗?难道因为不是gateway自己的?
  • 为什么这里不用控制面板了
  • 那个异常处理可以在配置文件,详见“自定义异常”

分组限流

import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.ruoyi.gateway.handler.SentinelFallbackHandler;

/**
 * 网关限流配置
 * 
 */
@Configuration
public class GatewayConfig
{
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelFallbackHandler sentinelGatewayExceptionHandler()
    {
        return new SentinelFallbackHandler();
    }

    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter()
    {
        return new SentinelGatewayFilter();
    }

    @PostConstruct
    public void doInit()
    {
        // 加载网关限流规则
        initGatewayRules();
    }

    /**
     * 网关限流规则   
     */
    private void initGatewayRules()
    {
        Set<GatewayFlowRule> rules = new HashSet<>();
        rules.add(new GatewayFlowRule("system-api")
                .setCount(3) // 限流阈值
                .setIntervalSec(60)); // 统计时间窗口,单位是秒,默认是 1 秒
        rules.add(new GatewayFlowRule("code-api")
                .setCount(5) // 限流阈值
                .setIntervalSec(60));
        // 加载网关限流规则
        GatewayRuleManager.loadRules(rules);
        // 加载限流分组
        initCustomizedApis();
    }

    /**
     * 限流分组   
     */
    private void initCustomizedApis()
    {
        Set<ApiDefinition> definitions = new HashSet<>();
        // ruoyi-system 组
        ApiDefinition api1 = new ApiDefinition("system-api").setPredicateItems(new HashSet<ApiPredicateItem>()
        {
            private static final long serialVersionUID = 1L;
            {
                // 匹配 /user 以及其子路径的所有请求
                add(new ApiPathPredicateItem().setPattern("/system/user/**")
                        .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
            }
        });
        // ruoyi-gen 组
        ApiDefinition api2 = new ApiDefinition("code-api").setPredicateItems(new HashSet<ApiPredicateItem>()
        {
            private static final long serialVersionUID = 1L;
            {
                // 只匹配 /job/list
                add(new ApiPathPredicateItem().setPattern("/code/gen/list"));
            }
        });
        definitions.add(api1);
        definitions.add(api2);
        // 加载限流分组
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }
}
  • 不过这样的话,,路径就写死在代码里了

注解方式

sentinel 不仅支持通过硬代码方式进行资源的申明,还能通过注解方式进行声明,为了让注解生效,还需要配置切面类SentinelResourceAspect

   @Bean
  public SentinelResourceAspect sentinelResourceAspect() {
    return new SentinelResourceAspect();
  }

自定义异常

为了展示更加友好的限流提示, Sentinel支持自定义异常处理。

方案一:yml配置

# Spring
spring: 
  cloud:
    sentinel:
      scg:
        fallback:
          mode: response
          response-body: '{"code":403,"msg":"请求超过最大数,请稍后再试"}'

方案二:GatewayConfig注入Bean

@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelFallbackHandler sentinelGatewayExceptionHandler()
{
	return new SentinelFallbackHandler();
}

SentinelFallbackHandler.java

import java.nio.charset.StandardCharsets;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
import reactor.core.publisher.Mono;

/**
 * 自定义限流异常处理
 *
 */
public class SentinelFallbackHandler implements WebExceptionHandler
{
    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange)
    {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        byte[] datas = "{\"code\":429,\"msg\":\"请求超过最大数,请稍后再试\"}".getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(datas);
        return serverHttpResponse.writeWith(Mono.just(buffer));
    }

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex)
    {
        if (exchange.getResponse().isCommitted())
        {
            return Mono.error(ex);
        }
        if (!BlockException.isBlockException(ex))
        {
            return Mono.error(ex);
        }
        return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange));
    }

    private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable)
    {
        return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);
    }
}

实现原理

在 Sentinel 里面,所有的资源都对应一个资源名称以及一个 Entry。Entry 可以通过对主流框架的适配自动创建,也可以通过注解的方式或调用 API 显式创建;每一个 Entry 创建的时候,同时也会创建一系列功能插槽(slot chain)

这些功能插槽有些类似游戏或是组装电脑里“升级插槽”的概念,在原有基础上添加功能。可以自定义插槽

插槽介绍

NodeSelectorSlot

这个 slot 主要负责收集资源的路径,并将这些资源的调用路径,以树状结构存储起来,用于根据调用路径来限流降级。
资源确实是树状结构的,就像树形目录。结构上资源和url很像,也应当是树形结构

熔断降级设计理念
在限制的手段上,Sentinel 和 Hystrix 采取了完全不一样的方法。
Hystrix 通过线程池的方式,来对依赖(在我们的概念中对应资源)进行了隔离。这样做的好处是资源和资源之间做到了最彻底的隔离。
缺点:

  • 增加了线程切换的成本
  • 需要预先给各个资源做线程池大小的分配,容易导致碎片化
  • 怎么线程池隔离?不如说实际上隔离时怎么做到的?内存地址拒绝访问?

核心类解析

Sentinel 对这个问题采取了两种手段:
通过并发线程数进行限制
和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。
通过响应时间对资源进行降级
除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
系统负载保护
Sentinel 同时对系统的维度提供保护。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。
针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。

进一步学习

相关概念:

SPI:SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议,比如AT91RM9200。
官方文档:https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5

附录

@SentinelResource注解参数

① value: 资源名称,必需项
② entryType: entry 类型,可选项(默认为 EntryType.OUT)

⑤ defaultFallback(since 1.6.0): 默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑。defaultFallback 函数默认需要和原方法在同一个类中,通过指定 fallbackClass 为对应类的 Class 对象,则可以指定指定为其他类的函数,但注意对应的函数必需为 static 函数,否则无法解析。defaultFallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback和 defaultFallback,则只有 fallback会生效。

defaultFallback函数的返回值类型必须与原函数返回值类型一致;方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。

⑥ exceptionsToIgnore(since 1.6.0): 用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandler、fallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException)

流控规则

一条限流规则由以下属性组成:

① resource: 资源名,即限流规则的作用对象,默认请求路径。

② limitApp: 流控针对的调用来源,若为 default 则不区分调用来源,默认值default

③ count: 限流阈值

④ grade: 限流阈值类型(1代表 QPS,0 代表并发线程数),默认值QPS

⑤ strategy: 流控模式

直接拒绝(默认): 接口达到限流条件时,直接限流
关联: 当关联的资源达到阈值时,就限流自己(适合做应用让步)
链路: 只记录指定链路上的流量,指定资源从入口资源进来的流量,如果达到阈值,就可以限流
⑥ controlBehavior: 流控效果

快速失败(默认): 当 QPS 超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException
排队等待: 这种方式严格控制了请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
Warm Up: 该方式主要用于系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮的情况。预热底层是根据令牌桶算法实现的。
以上几种属性在 sentinel-dashboard 控制台对应的规则如下图:

图片

Spring事务失效

在AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法中有个判断,如果目标方法不是 public,则TransactionAttribute返回 null,即不支持事务。

    protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        // Don't allow no-public methods as required.
        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
          return null;
        }
     
        // The method may be on an interface, but we need attributes from the target class.
        // If the target class is null, the method will be unchanged.
        Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
     
        // First try is the method in the target class.
        TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
        if (txAttr != null) {
          return txAttr;
        }
     
        // Second try is the transaction attribute on the target class.
        txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
          return txAttr;
        }
     
        if (specificMethod != method) {
          // Fallback is to look at the original method.
          txAttr = findTransactionAttribute(method);
          if (txAttr != null) {
            return txAttr;
          }
          // Last fallback is the class of the original method.
          txAttr = findTransactionAttribute(method.getDeclaringClass());
          if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
            return txAttr;
          }
        }
        return null;
      }

也就是说,如果我们自定义的事务方法(即目标方法),它的访问权限不是public,而是 private、default 或 protected 的话,spring 则不会提供事务功能。
2. 方法用 final 修饰
spring 事务底层使用了 aop,也就是通过 jdk 动态代理或者 cglib,帮我们生成了代理类,在代理类中实现的事务功能。

但如果某个方法用 final 修饰了,那么在它的代理类中,就无法重写该方法,而添加事务功能。

    注意:如果某个方法是 static 的,同样无法通过动态代理,变成事务方法。
  • 但是sentinel却没提static和final,,如果只是私有方法,那么可能是其他类判断方法类型的,,为什么?是为了在反射的情况下仍然能保证访问权限吗?

控制台模式存在的问题

优点是方便。缺点是:
通过 Sentinel-Dashboard 控制台配置的规则依然要推送到微服务应用中 Sentinel 客户端本身才能生效,而微服务之间的调用链路等指标信息也需要推送给Sentinel控制台,才能比较方便地使用Sentinel提供的一些能力,因此在开源的架构版本中需要微服务应用本身开启独立端口与 sentinel-dashboard 进行通信,从而获取配置规则以及上送微服务应用的各类指标信息。

而这显然也会占用微服务额外的资源,并且由于 sentinel-dashboard 在此条件下并不具备集群部署能力,因此也会形成一个单节点问题。

在开源版本架构中,通过 sentinel-dashboard 控制台配置的限流、熔断降级等规则都是存储于 Sentinel-Dashboard 控制台服务的内存之中,如果控制台服务重启或者微服务应用重启都会导致规则丢失,而这在生产环境下显然是不能接受的,因此 Sentinel 官方推荐在生产架构中使用第三方数据源作为永久存储中心,比如 nacos、apollo、zookeeper,这样各个微服务的限流、降级规则都可以永久存储。

sentinel 整合 openFeign:

上文介绍的都是在单个模块间的进行 fallback 和 blockhandler 测试,但在实际的 SpringCloud 微服务开发场景中肯定会遇到服务间远程服务调用的问题,而目前最主流的远程调用组件就是 openFeign 了,那接下来我们看看 sentinel 如何整合 openFeign 进行熔断降级。

1、引入 openFeign 的依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、配置文件中开启 openFeign 对 sentinel 熔断降级的支持:

feign.sentinel.enabled=true

3、消费者主启动类添加注解 @EnableFeignClients 激活 openFeign

4、消费者声明接口,标识要调用提供方模块的哪个方法,并在 @FeignClient 注解中使用 fallback 属性指定熔断降级类:

@FeignClient(value = "payment-provider", fallback = PaymentServiceImpl.class)
public interface PaymentService {
 
    @GetMapping("/payment/get/{id}")
    public CommonResult paymentSql(@PathVariable("id")Long id);
}

5、添加降级类:实现第4步的定义的接口,并添加降级逻辑:

@Component
public class PaymentServiceFallback implements PaymentService {
 
    @Override
    public CommonResult paymentSql(Long id) {
        return new CommonResult(414, "open-feign 整合 sentinel 实现的全局服务降级策略",null);
    }
}

PaymentServiceFallback 是 PaymentService 的降级回调类,一旦PaymentService 中对应得接口出现了异常,则会调用PaymentServiceFallback类中对应得方法进行降级处理。

  • 为什么fallback指定的是ServiceImpl的类?
  • 没看出和Sentinel有什么关系?
  • feign不是还默认集成了Hystrix吗
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Sentinel Runtime是一个基于JVM的流量控制、熔断降级、系统负载保护和实时监控的开源组件。它提供了开箱即用的流量控制、熔断降级、系统负载保护能力,并且可以与Spring Cloud、Dubbo等主流的微服务框架无缝集成,支持多语言、多框架、多平台;同时,Sentinel还提供了实时监控、异常处理和统计告警等功能,帮助开发者快速定位和排除问题,从而提高应用程序的可靠性和稳定性。 Sentinel Runtime的核心是基于“流量控制拉锯机”算法实现的QPS(每秒请求数)控制模型,它通过在预热阶段和正式运行阶段对系统性能进行评估,自动调整阈值,从而达到精准控制系统的QPS,并且能够避免流量集中导致的系统宕机等问题。 总之,Sentinel Runtime是一个非常实用的组件,它能够为开发者提供快速、可靠的流量保障和实时监控能力,帮助企业实现高性能、高可用的APM(应用程序性能管理)和SRE(站点可靠性工程)管理。 ### 回答2: Sentinel是阿里巴巴公司开源的分布式系统的运行时保护组件。它可以提供实时的流量控制、熔断降级、参数限流等功能,帮助开发者在面对大流量、高并发等问题时保障系统的稳定性和可靠性。 Sentinel Runtime是Sentinel的核心组件,它通过拦截系统请求并对其进行实时的监控和保护来实现流量控制、熔断降级、参数限流等功能。它提供了丰富的API和插件机制,使得开发者可以根据自己的需求自由定制配置,并进行精细化的流量管控。 Sentinel Runtime基于Java的Instrumentation和字节码操纵技术实现,能够无侵入地对系统进行监控和保护,从而保证系统的健壮性和可靠性。同时它也可以和常见的Spring Cloud、Dubbo等常用框架无缝集成,提供完善的服务治理功能,为分布式系统的开发和维护带来了极大的便利性。 总之,Sentinel Runtime是Sentinel的基础组件,它提供了实时的流量控制、熔断降级、参数限流等功能,可以帮助开发者实现系统的高效稳定和可靠性,是分布式系统开发和运维的重要工具之一。 ### 回答3: Sentinel Runtime是开源的、用于Java、Go、PHP等语言的运行时保护框架。它主要用于解决在分布式微服务环境下的服务保护问题。 Sentinel Runtime的主要功能包括流量控制、熔断降级、系统保护、授权访问等。它能够根据应用程序运行时的状态和负载情况,对服务的访问进行动态调整和限制,从而保证应用程序的高可用性、高可靠性和高性能。 Sentinel Runtime基于AOP(面向切面编程)思想,通过注入切面逻辑,实现对服务的实时监控和保护。它可以集成到Spring Cloud、Dubbo等主流的微服务框架中,与这些框架协同工作,在保证应用程序功能完整性的同时,提供更可靠的服务保障。 总之,Sentinel Runtime是一个非常实用的运行时保护框架,可以帮助开发人员在分布式微服务环境下,保证服务的高可用性、高可靠性和高性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值