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 @SentinelResource
anotaciones 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
Para demostrar el efecto, configúrelo dos veces por segundo.
Tabla de efectos de prueba de cartero:
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
@SentinelResource
anotadosblockHandler
(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
BlockException
pará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
@SentinelResource
Tenga 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.
-
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
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:
Efecto fusible:
No hay mucho que decir, obviamente, llame al método alternativo directamente.
Más descripción del atributo de anotación
@SentinelResource
Se 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 esEntryType.OUT
) -
blockHandler
/blockHandlerClass
: Nombre de la función deblockHandler
procesamiento de correspondenciaBlockException
, opciones. El alcance de acceso de la función blockHandler debe serpublic
que 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 esBlockException
. 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 especificarblockHandlerClass
la clase de losClass
objetos 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
Throwable
tipo 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
fallbackClass
la clase de losClass
objetos 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
Throwable
tipo 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
fallbackClass
la clase de losClass
objetos 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 BlockException
solo entrará al blockHandler
procesar la lógica. Si no hay configuración blockHandler
, fallback
y 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/