Prefácio
Sentinel é um componente de gerenciamento de tráfego para arquitetura de serviço heterogêneo distribuído e multilíngue, que utiliza principalmente o tráfego como ponto de entrada, cobrindo roteamento de tráfego, controle de tráfego, modelagem de tráfego, degradação de disjuntores, proteção adaptativa contra sobrecarga do sistema, proteção de tráfego em pontos quentes, etc. Dimensão para ajudar os desenvolvedores a garantir a estabilidade dos microsserviços.
Este blog apresenta o uso do sentinela, apresenta dependências e configurações e ilustra o controle de fluxo de consumidores e disjuntores do sentinela e o downgrade de produtores por meio de estudos de caso.
Outros artigos sobre sentinela são os seguintes:
Índice
liderar
1. O uso do sentinela introduz dependências e configurações;
2. Controle de fluxo para consumidores;
3. Disjuntores e downgrades para produtores;
1. Preparação para usar sentinela
1. Contexto e Recursos
Contexto (Contexto) e context-name
Context representam o contexto do link de chamada. É um nó raiz. No início de todo o link de chamada, o Sentinel criará um objeto Contexto e atribuirá a ele um nome, que é equivalente ao recurso raiz. No Sentinel, diferentes links de chamada podem usar o mesmo objeto de contexto (um nó raiz total). Aqui (integrado ao Spring MVC), nossos links de chamada estão todos em sentinel_spring_web_context:
Os recursos e o nome do recurso
estão no Sentinel. Para cada recurso, o Sentinel atribuirá um nome (ou você o especificará manualmente). Ao integrar com o Spring MVC, o Sentinel usa URI como o nome do recurso do método Controller (aqui, o método Controller é o recurso)
2. Divisão de responsabilidades
Para os consumidores, quando se trata de controle de tráfego, se outros me acessarem, tenho medo de falhar, por isso quero limitar o tráfego que outros possam me acessar;
Para o produtor, o disjuntor é rebaixado. O consumidor liga para o produtor, temendo que o produtor tenha um problema, então o disjuntor é rebaixado. Se o receptor, ou seja, o produtor, tiver um problema, a resposta correspondente será seja dado;
3. Introduzir dependências e configuração
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
spring:
cloud:
# nacos的配置
nacos:
discovery:
# 能够注册
register-enabled: true
server-addr: http://192.168.111.130:8848/
# 命名空间
namespace: my-tianju
# 组名
group: DEV
# sentinel的配置
sentinel:
transport:
dashboard: 192.168.111.130:7777
port: 8719
# 这样一启动能够立马被发现,不用请求一次后才被监控
eager: true
# 链路相关的配置
# 默认是true,开启上下文整合,所有链路在根节点下,链路监控就是将请求分开统计
web-context-unify: false
application:
name: springCloud-consumer
#feign:
# hystrix:
# enable: true
# 打开阿里的 sentinel
feign:
sentinel:
enabled: true
2. Controle o fluxo de consumidores
QPS (Consultas por Segundo) representa o número de consultas por segundo. Ou seja, o número de consultas às quais um servidor pode responder por segundo.
1. Limite de máquina única
QPS (Consultas por Segundo) representa o número de consultas por segundo. Ou seja, o número de consultas às quais um servidor pode responder por segundo.
Foram muitas solicitações e o fluxo foi restringido pelo sentinela.
2. Configurações de pré-aquecimento
Quando o sistema é iniciado pela primeira vez, menos solicitações são permitidas. À medida que o sistema se estabiliza gradualmente, o limite de permissão de acesso aumenta.
JMeter testa pós-solicitações e precisa adicionar parâmetros de cabeçalho de solicitação.
Tempo de aceleração: O intervalo entre as inicializações do thread. Se 100 threads forem iniciados em 10s, defina a aceleração como 100/10=10s.
Gráfico de forma de onda
Análise de todo o processo:
1. Permitir 3 vezes por segundo no início;
2. Aumentar gradualmente nos primeiros 10 segundos;
3. Atingir um valor estável após 10 segundos e permitir 10 vezes por segundo;
3. Espere na fila
Enfileiramento e espera: também chamado de modelagem de tráfego, permite que as solicitações passem a uma velocidade uniforme. O limite de máquina única é o número de passagens por segundo. O restante é enfileirado na fila e espera por um período de tempo (ou seja, o tempo que definimos, em milissegundos).Este tempo não é excedido.pode ser processado a tempo.Se não houver thread para processar a interface solicitada após esse tempo de espera, uma exceção será lançada.
Configurações de parâmetro JMeter
Gráfico de forma de onda
Processo de política de limitação atual:
1. Permita 10 por segundo
2. Envie 50, passe 10 e os 40 restantes entrem na fila para esperar:
3. Quando não houver solicitações, através das solicitações aguardando na fila,
4.Modo de associação
Associação: A importância da interface /important é maior do que a da interface /normal.Se a pressão de acesso da interface /important for muito alta, então a interface /normal` pode ser "sacrificada" para garantir o funcionamento normal do /interface importante.
Configurações de parâmetro JMeter
Configuração do número do thread
add foi bem-sucedido, get é limitado
Em situações de alta simultaneidade, a interface add não falha.
Suplemento: Retorno de exceção de limitação de corrente personalizado
As informações padrão retornadas pelo Sentinel são Bloqueadas pelo Sentinel (limitação de fluxo).Se você não estiver satisfeito com as informações de resposta padrão, poderá personalizar as informações de retorno de limitação de fluxo.
O Sentinel fornece a interface BlockExceptionHandler. Não importa o que faça com que o Sentinel bloqueie a solicitação normal do usuário, o Sentinel irá "entrar" na classe de implementação da interface BlockExceptionHandler definida pelo usuário, executar o método handle e passar a solicitação atual, o objeto de resposta e o objeto de exceção, e a execução o resultado do método handle é retornado ao usuário.
package com.tianju.test;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
BlockException ex) throws Exception {
String msg = null;
if (ex instanceof FlowException) {
msg = "该请求限流了,请稍后重试";
} else if (ex instanceof DegradeException) {
msg = "被熔断了";
} else {
msg = "其它原因";
// ParamFlowException "热点参数限流";
// SystemBlockException "系统规则(负载/...不满足要求)";
// AuthorityException "授权规则不通过";
}
// http 状态码
response.setStatus(500);
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type", "application/json;charset=utf-8");
response.setContentType("application/json;charset=utf-8");
new ObjectMapper().writeValue(response.getWriter(), msg);
}
}
Deve-se observar que: não são apenas os motivos de limitação de corrente e disjuntor que causarão a execução do método handle do BlockExceptionhandler, mas também outros motivos que também chamarão esse método manipulador. Portanto, é necessário executar instância de julgamento no objeto de parâmetro BlockException do método handle.
5. Modo de link
As idéias de limitação de corrente de link e limitação de corrente de associação são muito semelhantes. Suponha que queiramos solicitar um determinado microsserviço. O microsserviço possui duas interfaces (/query e /add), e essas duas interfaces chamam a mesma camada de serviço. método (como : método doSomething()), então podemos configurá-lo da perspectiva do método doSomething: Se a interface /query estiver chamando o método doSomething da camada de serviço, então a corrente é limitada e /add Não há limite de corrente para chamando a interface ou pode ser configurado para um controle de fluxo mais relaxado.
Desative a função de convergência de URL do sentinela por meio da configuração
package com.tianju.consumer.service;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;
@Service
public class ConsumerService {
@SentinelResource("hello")
public String hello(){
return "consumerService";
}
}
Modo link, da perspectiva dos métodos da camada de serviço
Interface de adição de alta simultaneidade, sem falha
Clique rapidamente no método get e ocorre uma situação inválida.
3. Disjuntor e rebaixamento de produtores
3 estados de fusível:
-
Fechado: estado fechado, todas as solicitações são acessadas normalmente.
-
Aberto: estado aberto, todas as solicitações serão rebaixadas.
O Hystrix contará as solicitações. Quando a porcentagem de solicitações com falha atingir o limite dentro de um determinado período de tempo, o fusível será acionado e o disjuntor será totalmente aberto. O limite padrão da taxa de falha é de 50% e o número de solicitações é de pelo menos 20. O padrão é 20 solicitações em cinco segundos. Se falhar 10 vezes (50%), a solicitação não poderá ser acessada normalmente.
-
Half Open: Estado meio aberto. O estado aberto não é permanente. Ele entrará no tempo de suspensão após a abertura (o padrão é 5S). O disjuntor entrará automaticamente no estado semiaberto.
Neste momento, algumas solicitações serão liberadas para passar. Se essas solicitações estiverem íntegras, o disjuntor será completamente fechado. Caso contrário, permanecerá aberto e o sleep timer será reiniciado.
1. Número de exceções
A seguinte configuração: Envie 2 solicitações em um segundo. Se ocorrer uma falha (anormal), o disjuntor será desconectado diretamente e depois rebaixado.
Configurando parâmetros
2. Proporções anormais
Definir método substituto
package com.tianju.config;
import com.tianju.common.dto.StorageDto;
import com.tianju.common.result.HttpResp;
import com.tianju.config.fallback.StorageFeignFallback;
import com.tianju.entity.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(value = "storage-server",fallback = StorageFeignFallback.class)
public interface StorageFeign {
@PostMapping("/storage/sub")
HttpResp subStorage(@RequestBody StorageDto storageDto);
}
openfeign define método substituto
package com.tianju.config;
import com.tianju.common.dto.StorageDto;
import com.tianju.common.result.HttpResp;
import com.tianju.config.fallback.StorageFeignFallback;
import com.tianju.entity.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(value = "storage-server",fallback = StorageFeignFallback.class)
public interface StorageFeign {
@PostMapping("/storage/sub")
HttpResp subStorage(@RequestBody StorageDto storageDto);
}
Uma anormalidade ocorre no produtor
Teste com carteiro
package com.tianju.config.fallback;
import com.tianju.common.dto.StorageDto;
import com.tianju.common.result.HttpResp;
import com.tianju.config.StorageFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 调用库存的feign异常时的返回
*/
@Component
@Slf4j
public class StorageFeignFallback implements StorageFeign {
@Override
public HttpResp subStorage(StorageDto storageDto) {
System.out.println("#########################进入了减库存方法的异常中....###########################");
log.debug("进入了减库存方法的异常中....");
return HttpResp.failed("减库存的openFeign调用失效,请稍后重试");
}
}
package com.tianju.config.fallback;
import com.tianju.common.dto.StorageDto;
import com.tianju.common.result.HttpResp;
import com.tianju.config.StorageFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 调用库存的feign异常时的返回
*/
@Component
@Slf4j
public class StorageFeignFallback implements StorageFeign {
@Override
public HttpResp subStorage(StorageDto storageDto) {
System.out.println("#########################进入了减库存方法的异常中....###########################");
log.debug("进入了减库存方法的异常中....");
return HttpResp.failed("减库存的openFeign调用失效,请稍后重试");
}
}
3. Proporção de chamadas lenta
A seguinte configuração: enviar 5 solicitações em um segundo. Se o tempo de resposta de cada solicitação exceder 500 milissegundos e a proporção atingir 0,5 (50%), um disjuntor será executado. A duração do disjuntor é de 10 segundos. Por exemplo: há 5 solicitações em 1 segundo e o tempo de resposta de 3 delas excede 500 milissegundos, então a proporção é de 60%.Se for maior que 50%, o circuito será interrompido neste momento e depois rebaixado.
Testado com Jmeter, quando id=1 no programa, cada resposta dura 800 milissegundos. Portanto, cada solicitação leva mais de 500 milissegundos e a taxa de falha é de 100%.Neste momento, a solicitação do recurso com id = 4 não pode ser solicitada, pois o disjuntor está quebrado, portanto é rebaixado diretamente. Será normal solicitar id=4 novamente após 10 segundos.
Resumir
1. O uso do sentinela introduz dependências e configurações;
2. Controle de fluxo para consumidores;
3. Disjuntores e downgrades para produtores;