Disyuntor AlibabaCloud-sentinel-getway (2)

Disyuntor AlibabaCloud-Sentinel (2)

En el artículo anterior, presentamos el uso de Sentinel para limitar la interfaz actual, pero la función de Sentinel, por supuesto, no se limita a la extracción de interfaz. En este momento, aparece la anotación @SentinelResource.

Echemos un vistazo a cómo lo usa.

El primer paso: primero inicie la consola centinela

java -Dserver.port=8889  -jar sentinel-dashboard-1.8.0.jar 

Paso 2: agregue la configuración para la compatibilidad con anotaciones:

    public static void main(String[] args) {
    
    
        new SpringApplicationBuilder(FebsServerTestApplication.class)
                .web(WebApplicationType.SERVLET)
                .run(args);
    }

    // 注解支持的配置Bean
    @Bean
    public SentinelResourceAspect sentinelResourceAspect(){
    
    
        return new SentinelResourceAspect();
    }

Paso 2: utilice @SentinelResourceanotaciones cuando necesite controlar el tráfico a través de Sentinel . Por ejemplo, utilice un método para controlar la capa lógica de servicio de la siguiente manera:

package cc.mrbird.febs.server.test.service.impl;

import cc.mrbird.febs.server.test.service.ITestService;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @author: craywen
 * @date: 2020-09-07 10:22
 * @desc:
 */
@Service
@Slf4j
public class TestServerImpl implements ITestService {
    
    

    @Override
    @SentinelResource(value = "sentinelTest")
    public void sentinelTest() {
    
    
     log.info("----------------限流方法测试------------");
    }
}

Hasta este punto es el límite actual para este método (denominado punto de recursos) .Después de definir el punto de recursos, se pueden implementar diferentes estrategias de protección, que incluyen: límite de corriente, degradación, etc.

Primero, echemos un vistazo al efecto: primero, establezca el límite actual en la consola

[Error en la transferencia de la imagen del enlace externo. El sitio de origen puede tener un mecanismo anti-hotlinking. Se recomienda guardar la imagen y subirla directamente (img-j818rsBf-1599451264306) (C: \ Users \ Administrator \ AppData \ Roaming \ Typora \ typora-user-images \ image-20200907105529843.png)]

Para demostrar el efecto, configúrelo dos veces por segundo.

Tabla de efectos de prueba de cartero:

1. Renderizado con un solo clic: [Error en la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo de enlace anti-sanguijuelas, se recomienda guardar la imagen y cargarla directamente (img-rHDbxSmb-1599451264309) (C: \ Users \ Administrador \ AppData \ Roaming \ Typora \ typora-user-images \ image-20200907105730789.png)]

2. Clic rápido: [Error en la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo de enlace anti-sanguijuelas, se recomienda guardar la imagen y cargarla directamente (img-F41cp2ip-1599451264310) (C: \ Users \ Administrator \ AppData \ Roaming \ Typora \ typora -user-images)]

Esto es muy obvio, la excepción 500 regresó directamente, para este tipo de cosas debemos sentarnos y lidiar con eso.

Realice el manejo de excepciones de límite actual

De forma predeterminada, Sentinel lanza directamente excepciones para el procesamiento del límite actual de los recursos de control, pero en circunstancias normales, para mejorar el negocio del usuario, se implementa un procesamiento especial después de que se implementa el límite actual, no queremos mostrar un error contundente. Entonces solo necesita hacer un procesamiento basado en el ejemplo anterior, como:


    @Override
    @SentinelResource(value = "sentinelTest",blockHandler = "exceptionHandler")
    public void sentinelTest() {
     log.info("----------------限流方法测试------------");
    }

    // 阻塞处理
    private  void exceptionHandler(BlockException ex){
        log.error( "blockHandler:" , ex);
    }
  • Desarrollar funciones de procesamiento específicas a través de los atributos @SentinelResourceanotados blockHandler(implementar excepciones personalizadas)
  • Para implementar la función de procesamiento, el paso de parámetro de la función debe ser el mismo que el del punto de recurso, y el BlockExceptionparámetro de excepción debe agregarse al final ; al mismo tiempo, el tipo de retorno también debe ser el mismo.

Lograr la degradación de fusibles

@SentinelResourceTenga en cuenta que la versión se puede utilizar para el control de limitación de corriente y también puede implementar una estrategia de degradación de fusibles similar a Hystrix.

  1. Primero transforma el método sentinelTest2

     // 熔断与降级处理
        @Override
        @SentinelResource(value = "sentinelTest2",fallback = "fallback")
        public void sentinelTest2() {
          
          
            log.info("sentinelTest2-------",new Date());
            throw new RuntimeException("发生异常");
        }
    
        public void fallback(){
          
          
            log.error("fallbackHandler:" +new Date());
        }
    

2. Configure la estrategia de fusión [La transferencia de la imagen del enlace externo falla, el sitio de origen puede tener un mecanismo de enlace antirrobo, se recomienda guardar la imagen y cargarla directamente (img-UHhSQdmt-1599451264312) (C: \ Users \ Administrator \ AppData \ Roaming \ Typora \ typora-user-images)]
para que el efecto sea más obvio, configure el tiempo de fusión en 10S , lo que significa que la proporción anormal de este método se solicita Más del 50% activará el mecanismo de fusible, y la solicitud mínima puede entenderse como un ciclo de cinco solicitudes.

Después de completar la transformación anterior, reinicie la aplicación y configure la estrategia de degradación de fusibles de los recursos de sentinelTest2 (usando un porcentaje anormal), y luego solicite con frecuencia el /sentinelTest2接口。在QPS>=5之后,由于这个接口一直在抛出异常,所以一定会满足熔断降级条件,这时候就会执行método fallbackHandler` e imprima continuamente los siguientes registros:

3. Para ser efectivos, usamos Apache jmeter para probar: preparar 20 solicitudes

Primero observe el efecto de colocar el fusible:

[Error en la transferencia de la imagen del enlace externo. El sitio de origen puede tener un mecanismo anti-hotlinking. Se recomienda guardar la imagen y subirla directamente (img-LLbsqybk-1599451264313) (C: \ Users \ Administrator \ AppData \ Roaming \ Typora \ typora-user-images)]

Efecto fusible:

[Error en la transferencia de la imagen del enlace externo. El sitio de origen puede tener un mecanismo anti-hotlinking. Se recomienda guardar la imagen y subirla directamente (img-ahWDJfvd-1599451264314) (C: \ Users \ Administrator \ AppData \ Roaming \ Typora \ typora-user-images)]

No hay mucho que decir, obviamente, llame al método alternativo directamente.

Más descripción del atributo de anotación

@SentinelResourceSe introducen los dos usos principales de las anotaciones: los casos de uso específicos de control de límite de corriente y degradación de fusibles. Además, esta anotación también tiene algunas otras configuraciones más refinadas, como ignorar ciertas configuraciones anormales, funciones degradantes predeterminadas, etc., para obtener más detalles, consulte la siguiente descripción:

  • value: Nombre del recurso, elemento obligatorio (no puede estar vacío)

  • entryType: Tipo de entrada, opcional (el predeterminado es EntryType.OUT)

  • blockHandler/ blockHandlerClass: Nombre de la función de blockHandlerprocesamiento de correspondencia BlockException, opciones. El alcance de acceso de la función blockHandler debe ser publicque el tipo de retorno debe coincidir con el método original, el tipo de parámetro debe coincidir con el método original y se agrega un parámetro adicional al final, el tipo es BlockException. La función blockHandler debe estar en la misma clase que el método original de forma predeterminada. Si desea utilizar otro tipo de funciones, puede especificar blockHandlerClassla clase de los Classobjetos correspondientes , prestar atención a la función correspondiente es necesaria para la función estática, no se puede resolver de otra manera.

  • fallback
    

    : Nombre de la función de reserva, opcional, que se utiliza para proporcionar lógica de procesamiento de reserva cuando se lanza una excepción. La función de reserva puede apuntar a todo tipo de excepciones (excepto

    exceptionsToIgnore
    

    Se procesan los tipos de excepción excluidos en el interior). Requisitos de ubicación y firma de la función de reserva:

    • El tipo de valor de retorno debe ser coherente con el tipo de valor de retorno de la función original;
    • El método requiere una lista de parámetros y funciones consistentes con el original, o puede ser un Throwabletipo adicional de anormalidad correspondiente al parámetro recibido.
    • La función de reserva debe estar en la misma clase que el método original de forma predeterminada. Si desea utilizar otro tipo de funciones, puede especificar fallbackClassla clase de los Classobjetos correspondientes , prestar atención a la función correspondiente es necesaria para la función estática, no se puede resolver de otra manera.
  • defaultFallback
    

    (A partir de 1.6.0): el nombre de la función de respaldo predeterminado, opcional, generalmente se usa para la lógica de respaldo general (es decir, se puede usar para muchos servicios o métodos). La función de reserva predeterminada puede apuntar a todo tipo de excepciones (excepto

    exceptionsToIgnore
    

    Se procesan los tipos de excepción excluidos en el interior). Si se configuran tanto el retroceso como el retroceso predeterminado, solo surtirá efecto el retroceso. Los requisitos de firma de la función defaultFallback:

    • El tipo de valor de retorno debe ser coherente con el tipo de valor de retorno de la función original;
    • El método requiere que la lista de parámetros esté vacía, o puede ser un Throwabletipo adicional de anormalidad correspondiente al parámetro recibido.
    • La función defaultFallback debe estar en la misma clase que el método original por defecto. Si desea utilizar otro tipo de funciones, puede especificar fallbackClassla clase de los Classobjetos correspondientes , prestar atención a la función correspondiente es necesaria para la función estática, no se puede resolver de otra manera.
  • exceptionsToIgnore(A partir de 1.6.0): se utiliza para especificar qué excepciones se excluyen, no se incluyen en las estadísticas de excepciones y no entrarán en la lógica de reserva, pero se lanzarán tal cual.

Nota: La función de respaldo de las versiones anteriores a la 1.6.0 solo se ocupa de las excepciones de degradación ( DegradeException) y no puede ocuparse de las excepciones comerciales .

En particular, si blockHandler y fallback están configurados, se lanzaron limitando la degradación BlockExceptionsolo entrará al blockHandlerprocesar la lógica. Si no hay configuración blockHandler, fallbacky defaultFallback, se degradarán limitando BlockException el lanzamiento directo .

Cuál es el problema:

Debido a que la consola centinela, las reglas de limitación o fusión actuales no son persistentes, todas pueden persistir en la base de datos.

Puede consultar la siguiente configuración:

package cc.mrbird.febs.gateway.common.configure;

import cc.mrbird.febs.common.core.entity.FebsResponse;
import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
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.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * @author: craywen
 * @date: 2020-09-04 11:10
 * @desc:  Sentinel 配置
 * 使用时只需注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例即可。
 */
@Configuration
public class FebsGatewaySentinelConfiguration {
    
    

    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public FebsGatewaySentinelConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
                                            ServerCodecConfigurer serverCodecConfigurer) {
    
    
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    /**
     * 异常处理模块
     * @return
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
    
    
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    /**
     * 过滤器
     * @return
     */
    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter() {
    
    
        return new SentinelGatewayFilter();
    }

    @PostConstruct
    public void doInit() {
    
    
        //初始化规则
        initGatewayLimitRules();
        //熔断规则
        initFuseRules();
        //自定义限流异常处理
        initBlockHandler();
    }

    /**
     * 熔断规则 DegradeRule
     * resource	资源名,即规则的作用对象
     * grade	熔断策略,支持慢调用比例/异常比例/异常数策略	慢调用比例
     * count	慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值
     * timeWindow	熔断时长,单位为 s
     * minRequestAmount	熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入)	5
     * statIntervalMs	统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入)	1000 ms
     * slowRatioThreshold	慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)
     */
    private void initFuseRules(){
    
    
        List<DegradeRule> rules = new ArrayList<>();
        DegradeRule rule = new DegradeRule();
        rule.setResource("FEBS-Server-System");
        // set threshold RT, 10 ms
        rule.setCount(10);
        rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
        rule.setTimeWindow(10);
        rules.add(rule);
        DegradeRuleManager.loadRules(rules);
    }

    /**
     * 初始化规则
     */
    private void initGatewayLimitRules() {
    
    
        /**  Set<FlowRule> rules api 限流
         * resource	资源名,资源名是限流规则的作用对象
         * count	限流阈值
         * grade	限流阈值类型,QPS 模式(1)或并发线程数模式(0)	QPS 模式
         * limitApp	流控针对的调用来源	default,代表不区分调用来源
         * strategy	调用关系限流策略:直接、链路、关联	根据资源本身(直接)
         * controlBehavior	流控效果(直接拒绝/WarmUp/匀速+排队等待),不支持按调用关系限流	直接拒绝
         * clusterMode	是否集群限流
         */
        /*GatewayFlowRule:网关限流规则,针对 API Gateway 的场景定制的限流规则,
        可以针对不同 route 或自定义的 API 分组进行限流,
        支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。
        */

        Set<GatewayFlowRule> rules = new HashSet<>();
        /*设置限流规则
        resource: 资源名称,这里为路由router的ID
        resourceMode: 路由模式
        count: QPS即每秒钟允许的调用次数
        intervalSec: 每隔多少时间统计一次汇总数据,统计时间窗口,单位是秒,默认是 1 秒。
        */
        rules.add(new GatewayFlowRule("FEBS-Server-test")
                .setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID)
                .setCount(1).setIntervalSec(1));
        GatewayRuleManager.loadRules(rules);
    }

    /**
     * 自定义限流异常处理
     * ResultSupport 为自定义的消息封装类,代码略
     */
    private void initBlockHandler() {
    
    
        GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
    
    
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange,
                                                      Throwable throwable) {
    
    
                return ServerResponse.status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                        .body(BodyInserters.fromObject(new FebsResponse().put("data", "系统访问量过大,限流啦!")));
            }
        });
    }
}

El sistema cargará automáticamente la configuración.

Referencia : documento oficial de Sentinel

Materiales de referencia http://blog.didispace.com/spring-cloud-alibaba-sentinel-2-5/

Supongo que te gusta

Origin blog.csdn.net/qq_38893133/article/details/108445493
Recomendado
Clasificación