Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Limite os recursos que uma instância de aplicação, um inquilino individual ou um serviço inteiro podem consumir. Isto permite que o sistema funcione e cumpra os seus objetivos de nível de serviço (SLOs) sob carga súbita ou sustentada.
Contexto e problema
A carga numa aplicação na cloud varia ao longo do tempo consoante os utilizadores ativos e a sua atividade. Mais utilizadores iniciam sessão durante o horário comercial, e o sistema executa análises computacionalmente dispendiosas no final de cada mês. Também ocorrem explosões súbitas. Se a necessidade de processamento exceder a capacidade disponível, o sistema abranda ou falha. Quando o sistema tem um nível de serviço acordado, essa falha viola o SLO.
Várias estratégias lidam com diferentes cargas, dependendo dos objetivos empresariais da aplicação. Uma estratégia é o dimensionamento automático, que ajusta os recursos aprovisionados à procura atual e controla os custos. Mas provisionar novos recursos demora tempo e acrescenta custos. A procura que excede o crescimento da capacidade ou o orçamento cria um défice de recursos.
Solução
Uma alternativa ao dimensionamento automático é limitar a utilização de recursos e limitar as solicitações quando a utilização ultrapassa esse limite. A carga de trabalho monitoriza o seu próprio uso de recursos e limita os pedidos de um ou mais utilizadores quando a utilização ultrapassa o limiar. O sistema continua a funcionar e a cumprir os respetivos SLOs.
O throttling é um ciclo de controlo, não uma única decisão de admissão. O sistema necessita de sinais de baixa latência em três camadas: utilização da infraestrutura, estado da aplicação e contadores por principal. Mede continuamente a saturação, impõe limites em limites bem definidos e adapta esses limites à medida que os padrões de tráfego mudam. A sobrecarga é um modo de funcionamento normal que um sistema maduro deteta e recupera. A limitação proporciona capacidades de autopreservação na sua carga de trabalho.
O sistema pode implementar várias estratégias de limitação ou outras estratégias relacionadas:
Limites de taxa por principal: Rejeitar pedidos de um utilizador que já excedeu a taxa configurada numa janela definida. Esta estratégia exige que o sistema atribua cada pedido a um principal e contabilize a utilização de recursos em função desse principal. Para cargas de trabalho multi-inquilino, veja Medir o consumo de cada inquilino.
Degradação graciosa das características: Desligue ou degrade as funcionalidades não essenciais para que as funcionalidades essenciais tenham recursos suficientes. Esta estratégia troca a completude da resposta pela disponibilidade. Por exemplo, uma aplicação de streaming de vídeo pode baixar para uma resolução mais baixa.
Nivelamento de carga: Uniformização do volume de atividade recorrendo a uma fila. Num ambiente multiinquilino, o nivelamento reduz o desempenho para todos os inquilinos. Quando os inquilinos têm acordos de nível de serviço (SLAs) diferentes, processe imediatamente o trabalho para inquilinos de alto valor e mantenha o trabalho de menor prioridade até que o atraso desapareça. Implemente esta abordagem utilizando o padrão Priority Queue ou expondo endpoints separados para cada nível de prioridade.
Adiamento baseado em prioridades: Adiar operações em nome de aplicações ou inquilinos de menor prioridade. Suspender ou limitar as operações, e devolver uma exceção que indique ao inquilino para tentar novamente mais tarde.
Limites de taxa de saída: Limite as suas próprias chamadas de saída quando uma dependência externa falhar ou devolver erros. Reduza o número de pedidos em curso para evitar sobrecarregar os registos e os custos associados a novas tentativas numa dependência instável. Restaure o fluxo normal de solicitações após a recuperação da dependência. Por exemplo, o NServiceBus implementa esta funcionalidade.
O gráfico seguinte mostra o uso de recursos (uma combinação de memória, CPU, largura de banda e outros fatores) ao longo do tempo para uma aplicação que utiliza três funcionalidades, rotuladas como A, B e C. Uma funcionalidade é uma área específica de funcionalidade, como um componente que executa um conjunto específico de tarefas, um pedaço de código que realiza um cálculo complexo, ou um elemento que fornece um serviço, como uma cache em memória.
Um gráfico de linhas representa a utilização de recursos no eixo y em função do tempo no eixo x. Três linhas coloridas representam a Característica A, a Característica B e a Característica C, com a linha da Característica A mais baixa, a linha da Característica B no meio e a linha da Característica C mais alta. Uma linha horizontal sólida perto do topo do gráfico marca a capacidade máxima, e uma linha horizontal tracejada abaixo marca o limite suave da utilização de recursos. Duas linhas verticais tracejadas marcam os tempos T1 e T2. Antes de T1, as três linhas de características flutuam, e a linha da Característica C sobe e ultrapassa o limite suave. Em T1, a linha da Característica B desce para zero e mantém-se em zero até T2 porque a Característica B é suspensa para libertar recursos para a Característica A e a Característica C. A linha da Característica C cai abaixo do limite suave entre T1 e T2 enquanto a Característica A continua normalmente. No T2, a Funcionalidade B retoma e as três linhas continuam a flutuar abaixo do limite suave.
O gráfico é um gráfico de áreas empilhadas. A área abaixo da linha da Característica A mostra os recursos que a Característica A consome, a área entre as linhas da Característica A e da Característica B mostra os recursos que a Característica B consome, e a área entre as linhas da Característica B e da Característica C mostra os recursos que a Característica C consome. A linha da Funcionalidade C situa-se no topo da pilha, por isso também mostra o uso total de recursos do sistema ao longo do tempo.
O gráfico mostra uma degradação gradual das funcionalidades. Pouco antes do tempo T1, o uso total de recursos aproxima-se do limiar e corre o risco de esgotar a capacidade disponível. A Funcionalidade B é menos crítica do que a Característica A ou C, pelo que o sistema desliga a Funcionalidade B e liberta os seus recursos. Entre os tempos T1 e T2, a Característica A e a Característica C continuam normalmente. No tempo T2, o uso total de recursos cai o suficiente para reativar a Funcionalidade B.
Pode combinar o dimensionamento automático, a degradação gradual e a limitação da taxa para manter as aplicações responsivas e em conformidade com os SLAs. Quando se espera que a procura se mantenha elevada, a limitação mantém a estabilidade enquanto o sistema se expande. Após a conclusão da escalabilidade, o sistema restaura a funcionalidade total.
O gráfico seguinte mostra o uso total de recursos ao longo do tempo e como o throttling se combina com o autoscaling e outros controlos compensadores.
Um gráfico de linhas representa a utilização de recursos para todas as aplicações no eixo y em função do tempo no eixo x. Duas linhas horizontais de referência marcam o limite suave da utilização dos recursos e a capacidade máxima antes da autoescalabilidade. Uma linha horizontal mais alta, que começa no instante T2, assinala a capacidade máxima após o dimensionamento automático. A linha de utilização sobe e flutua ao longo do tempo. Excede o limite suave no instante T1, que é o ponto em que tem início o dimensionamento automático. Entre T1 e T2, o sistema é restringido enquanto ocorre o escalonamento automático, e a utilização mantém-se abaixo da capacidade máxima anterior ao escalonamento automático. No instante T2, o dimensionamento automático é concluído, a limitação é atenuada e a linha de utilização sobe abruptamente e continua a oscilar abaixo do novo limite máximo de capacidade, mais elevado.
No momento T1, o sistema atinge o limite suave e começa a escalar. Se os novos recursos não chegarem a tempo, a procura pode esgotar os recursos existentes e o sistema pode falhar. A limitação rejeita pedidos em excesso durante o scale-out para manter o uso de recursos abaixo do limite rígido, e depois levanta essas restrições quando a nova capacidade entra em funcionamento.
Tip
Os controlos Edge e o padrão Throttling abordam problemas diferentes. Controlos de borda, como Azure DDoS Protection e regras de limite de taxa de firewall de aplicações web (WAF), executam-se na fronteira da rede e eliminam tráfego volumétrico ou malicioso antes de chegar à sua aplicação. O padrão de limitação é executado na sua aplicação e regula o tráfego legítimo de acordo com os limites definidos na aplicação. Use as duas camadas em conjunto. A proteção DDoS não impede um utilizador legítimo de sobrecarregar o seu serviço, e a limitação de aplicações não absorve um ataque volumétrico.
Problemas e considerações
Considere os seguintes pontos ao decidir como implementar este padrão:
Tome decisões de limitação cedo. A limitação é uma decisão arquitetónica que afeta todo o sistema. Adaptá-lo mais tarde é caro.
Alinhe os limites de limitação com o componente que se satura primeiro.
A taxa de pedidos é a dimensão mais comum de limitar, mas, muitas vezes, o verdadeiro gargalo são os pedidos simultâneos em processamento, a profundidade da fila, a utilização da CPU ou da memória, ou os próprios limites de uma dependência subsequente. Um limite de requisições por segundo não protege um sistema cujo gargalo é a concorrência num ponto de ramificação.
Em cada limite de aplicação da limitação, como o gateway, o serviço, uma partição ou uma dependência a jusante, identifique primeiro o que satura e defina o limite dessa dimensão. Para proteção limitada por concorrência nos pontos de dispersão, veja o padrão Bulkhead, que complementa a limitação.
Escolhe intencionalmente um algoritmo limitante. Ajuste-a à tolerância do componente que está a proteger.
Algoritmo Comportamento e melhor ajuste Balde de tokens Suporta disparos até um tamanho configurado e impõe uma taxa de recarga constante. Usa para gateways que precisam de absorver picos curtos. Balde com fugas Emite a uma taxa constante. Utilize para sistemas de back-end que precisem de uma taxa de entrada constante. Janela fixa Simples de implementar, mas admite explosões consecutivas nos limites das janelas. Janela deslizante Suaviza o problema da fronteira das janelas fixas à custa de mais estado. Decida a quem se aplica o limite. A limitação num limite grosseiro, como um gateway regional, pode afetar muitos utilizadores não relacionados quando apenas alguns deles conduzem a carga.
Decida onde reside o contador quando um limite abrange vários nós. Os contadores locais são rápidos mas subestimam quando o mesmo chamador chega a múltiplas réplicas. Um contador centralizado numa loja partilhada como a Redis vê todos os pedidos, mas adiciona latência a cada decisão. Para aproximar uma taxa global, dividir o limite entre réplicas e reconciliar periodicamente.
Tome decisões de limitação de débito rapidamente. O sistema deve detetar carga crescente, reagir e regressar ao normal após a diminuição da carga. Este processo requer instrumentação de performance contínua.
Reduza a carga proativamente, não quando estiver à beira do colapso. Um limitador que só rejeita depois de um componente ficar saturado faz com que a latência dispare antes de os clientes verem qualquer contrapressão.
À medida que a utilização se aproxima do limite rígido, comece a rejeitar uma fração crescente dos pedidos. A rejeição precoce sinaliza os chamadores para recuarem e previne o colapso da latência que limites abruptos frequentemente desencadeiam. Usa a latência p99 contra o teu SLO como gatilho principal. A utilização média pode parecer normal, enquanto o p99 já ultrapassou o limite.
Onde consegues distinguir o valor do pedido, elimina primeiro trabalhos de menor valor ou mais retentáveis. Para obter mais informações, consulte o padrão de fila de prioridade.
Devolva um código de estado que informe o cliente quando uma rejeição temporária resulta de uma limitação:
- HTTP 429 (Demasiados Pedidos): O chamador excede uma taxa de pedido configurada numa janela definida.
- HTTP 503 (Serviço Indisponível): O serviço não consegue lidar com o pedido neste momento, muitas vezes devido a um pico inesperado de carga.
Inclua um cabeçalho HTTP
Retry-Afterpara que o cliente possa escolher uma estratégia de repetição. Forneça contexto suficiente para que o autor da chamada repita a tentativa de forma deliberada, em vez de adivinhar. Por exemplo, nomeie o limite que o chamador ultrapassa, clarifique o âmbito afetado ou sugira uma taxa que teria sucesso. Rejeições inexplicadas não ajudam os chamadores a adaptarem-se.Transmite os sinais de sobrecarga provenientes das tuas dependências, em vez de os absorver. Um serviço que aplica limitação de débito aos seus chamadores também deve respeitar as respostas de limitação de débito que recebe das suas próprias dependências a jusante. Se o seu serviço ocultar uma resposta 429 ou 503 proveniente de um serviço a jusante, repetindo silenciosamente a tentativa ou devolvendo uma resposta HTTP 500 genérica (Erro Interno do Servidor), os clientes não conseguem abrandar, as repetições amplificam-se e a sobrecarga propaga-se de volta a montante. O antipadrão Retry Storm descreve este modo de falha. Propague a back-pressure aos chamadores a montante, de modo a que toda a cadeia de chamadas reduza a carga de forma conjunta.
Tornar a rejeição mais barata do que o trabalho que ela impede. Se recusar uma solicitação exigir autenticação complexa, análise aprofundada ou avaliação complexa de políticas, uma enxurrada de solicitações rejeitadas pode, ainda assim, saturar o sistema. Rejeite o mais cedo possível no fluxo de processamento dos pedidos e teste também o próprio fluxo de rejeição sob carga.
Prepare-se para os casos em que a limitação de taxa não consiga dar tempo suficiente ao dimensionamento automático. Se a procura crescer mais depressa do que a nova capacidade entra em funcionamento, até um sistema limitado pode falhar. Quando esse resultado for inaceitável, mantenha reservas de capacidade maiores e configure uma escalabilidade automática mais agressiva.
Não uses cache como substituto do throttling. Um cache reduz a carga média na origem, mas não limita a carga máxima. Cada falha de cache passa para a origem e, quando uma chave popular expira com tráfego intenso, muitos chamadores podem correr para a reabastecer. Usa cache para reduzir a pressão normal e throttling para limitar o pior cenário. Para mais informações, consulte o padrão Cache-Aside.
Normalizar os custos de recursos para diferentes operações porque geralmente não têm custos de execução iguais. Por exemplo, os limites de limitação podem ser mais altos para operações de leitura e mais baixos para operações de escrita. Ignorar o custo por operação pode esgotar a capacidade e criar um vetor de ataque.
Torne a configuração do throttling alterável em tempo de execução. Quando chega uma carga anormal, é necessário ajustar os limites sem necessidade de implementação. As missões são lentas e arriscadas durante um incidente. O padrão External Configuration Store externaliza a configuração para que possas alterá-la em tempo de execução.
Considere limites adaptativos em vez de limites estáticos. Alguns SDKs de limitação reagem a sinais de latência ou ao comprimento da fila, para que o limite reflita as condições reais dos componentes. Emparelha sempre um limitador adaptativo com um máximo definido.
Reavalie os seus limites à medida que a carga de trabalho evolui. Os limitadores adaptativos não conseguem acompanhar todos os tipos de desvio, como alterações no SLO, alterações na capacidade de dependência ou variações no custo por operação. Agende uma revisão periódica por parte do operador com base nesses dados.
Quando utilizar este padrão
Utilize este padrão:
Para manter um sistema dentro dos seus SLOs.
Para evitar que um único inquilino monopolize os recursos da aplicação.
Para gerir o aumento da atividade.
Para limitar o nível máximo de recursos que um sistema precisa.
Reduzir o cálculo de baixo valor durante períodos de elevada intensidade de carbono na rede.
Design da carga de trabalho
Avalie como usar o padrão de Throttling no design de uma carga de trabalho para abordar os objetivos e princípios abordados nos pilares Azure Well-Architected Framework. A tabela a seguir fornece orientação sobre como esse padrão suporta as metas de cada pilar.
| Pilar | Como esse padrão suporta os objetivos do pilar |
|---|---|
| As decisões de projeto de confiabilidade ajudam sua carga de trabalho a se tornar resiliente ao mau funcionamento e garantem que ela se recupere para um estado totalmente funcional após a ocorrência de uma falha. | Você projeta os limites para ajudar a evitar o esgotamento de recursos que pode levar a avarias. Você também pode usar esse padrão como um mecanismo de controle em um plano de degradação gracioso. - RE:07 Autopreservação |
| As decisões de design de segurança ajudam a garantir a confidencialidade, integridade e disponibilidade dos dados e sistemas da sua carga de trabalho. | Você pode projetar os limites para ajudar a evitar o esgotamento de recursos que poderia resultar do abuso automatizado do sistema. - SE:06 Controles de rede - SE:08 Endurecimento de recursos |
| A Otimização de Custos foca-se em manter e melhorar o retorno do investimento da sua carga de trabalho. | Os limites aplicados podem informar a modelação de custos e podem estar diretamente ligados ao modelo de negócio da sua aplicação. Eles também colocam limites superiores claros na utilização, que podem ser levados em conta no dimensionamento de recursos. - CO:02 Modelo de custo - CO:12 Custos de escala |
| A Eficiência de Desempenho ajuda sua carga de trabalho a atender às demandas de forma eficiente por meio de otimizações em escala, dados e código. | Quando o sistema está sob alta demanda, esse padrão ajuda a mitigar o congestionamento que pode levar a gargalos de desempenho. Você também pode usá-lo para evitar proativamente cenários vizinhos barulhentos. - PE:02 Planeamento da capacidade - PE:05 Dimensionamento e particionamento |
Se este padrão introduzir compensações dentro de um pilar, considere-as em relação aos objetivos dos outros pilares.
Example
O diagrama seguinte mostra a limitação num sistema multiinquilino.
Três utilizadores identificados à esquerda representam locatários de uma aplicação Surveys multitenant: Adatum, Fabrikam e Contoso. Cada utilizador envia pedidos através de um domínio personalizado específico do inquilino, que a aplicação utiliza para identificar o inquilino. A Adatum envia 5 pedidos por segundo através da surveys.adatum.com, a Fabrikam envia 10 pedidos por segundo através da surveys.fabrikam.com, e a Contoso envia 150 pedidos por segundo através da surveys.contoso.com. À direita, a função Web da aplicação de inquéritos mede a taxa de pedidos por segundo para cada tenant. Os fluxos de pedidos Adatum e Fabrikam passam para a aplicação. O fluxo de pedidos Contoso é bloqueado por uma resposta Erro: Limitada porque a taxa excede o limite por inquilino.
Utilizadores de várias organizações de inquilinos acedem a uma aplicação alojada na cloud para preencher e submeter inquéritos. A aplicação contém instrumentação que monitoriza a frequência com que os utilizadores de cada locatário submetem pedidos.
Para evitar que os utilizadores de um locatário prejudiquem a capacidade de resposta e a disponibilidade dos utilizadores de outros locatários, a aplicação limita a taxa de pedidos por segundo que qualquer locatário pode enviar. A aplicação bloqueia os pedidos que excedem este limite.
Passo seguinte
Recursos relacionados
- Meça o consumo de cada cliente
- Autoscaling em Azure
- Queue-Based Padrão de nivelamento de carga
- Padrão de fila de prioridade
- Padrão de Repositório de Configuração Externa