Como sobrevivemos ao aumento acentuado da carga x10 no site remoto e que conclusões tiramos

Olá Habr! Nos últimos dois meses, vivemos uma situação muito interessante e gostaria de compartilhar nossa história de dimensionamento de infraestrutura. Durante esse período, a SberMarket cresceu 4 vezes em pedidos e lançou um serviço em 17 novas cidades. O crescimento explosivo da demanda por entrega de alimentos exigiu que escalássemos nossa infraestrutura. Leia as descobertas mais interessantes e úteis sob o gato.



Meu nome é Dima Bobylev, sou o diretor técnico da SberMarket. Como esta é a primeira publicação em nosso blog, vou dizer algumas palavras sobre mim e sobre a empresa. No outono passado, participei do concurso de jovens líderes da Runet. Para o concurso, escrevi uma história curta sobre como nós da SberMarket vemos a cultura interna e a abordagem para o desenvolvimento do serviço. E, embora não tenha sido possível vencer a competição, formulei para mim os princípios básicos para o desenvolvimento do ecossistema de TI.

Ao gerenciar uma equipe, é importante entender e encontrar um equilíbrio entre o que a empresa precisa e as necessidades de cada desenvolvedor específico. Agora, o SberMarket está crescendo 13 vezes ano a ano, e isso afeta o produto, exigindo um aumento constante no volume e no ritmo de desenvolvimento. Apesar disso, dedicamos tempo suficiente aos desenvolvedores para análise preliminar e escrita de código de alta qualidade. A abordagem formada ajuda não apenas na criação de um produto de trabalho, mas também em sua expansão e desenvolvimento. Como resultado desse crescimento, a SberMarket já se tornou líder em serviços de entrega de alimentos: entregamos cerca de 18 mil pedidos por dia todos os dias, embora no início de fevereiro houvesse cerca de 3.500.


Depois que um cliente solicitou ao correio da SberMarket que lhe entregasse produtos sem contato - diretamente para a varanda

Mas vamos aos detalhes. Nos últimos meses, temos escalado ativamente a infraestrutura de nossa empresa. Essa necessidade foi explicada por fatores externos e internos. Simultaneamente à expansão da base de clientes, o número de lojas conectadas aumentou de 90 no início do ano para mais de 200 em meados de maio. Obviamente, preparamos, reservamos a infraestrutura principal e contamos com a possibilidade de dimensionamento vertical e horizontal de todas as máquinas virtuais localizadas na nuvem Yandex. No entanto, a prática mostrou: "Tudo o que pode dar errado dá errado". E hoje quero compartilhar as situações mais interessantes que aconteceram nessas semanas. Espero que nossa experiência seja útil para você.

Escravo em alerta total


Mesmo antes do início da pandemia, estávamos diante de um aumento no número de solicitações para nossos servidores back-end. A tendência de encomendar produtos com entrega em domicílio começou a ganhar impulso e, com a introdução das primeiras medidas de auto-isolamento em relação ao COVID-19, a carga cresceu dramaticamente diante de nossos olhos o dia todo. Havia uma necessidade de descarregar rapidamente os servidores principais do banco de dados principal e transferir parte das solicitações de leitura para os servidores de réplica (escravos).

Estávamos nos preparando antecipadamente para esta etapa e, para essa manobra, 2 servidores escravos já haviam sido lançados. Eles trabalharam principalmente em tarefas em lote de geração de feeds de informações para troca de dados com parceiros. Esses processos criaram uma carga extra e, com toda a razão, foram colocados “fora do suporte” alguns meses antes. 

Como houve replicação no Slave, aderimos ao conceito de que os aplicativos só podem trabalhar com eles no modo somente leitura. O Plano de Recuperação de Desastres sugeriu que, em caso de desastre, poderíamos simplesmente montar o Escravo no lugar do Mestre e alternar todas as solicitações de gravação e leitura para o Escravo. No entanto, também queríamos usar réplicas para as necessidades do departamento de análise, para que os servidores não fossem completamente transferidos para o status somente leitura, e cada host tinha seu próprio conjunto de usuários e alguns tinham permissões de gravação para salvar resultados de cálculos intermediários.

Até um certo nível de carga, tínhamos assistentes suficientes para escrever e ler ao processar solicitações http. Em meados de março, quando a Sbermarket decidiu mudar completamente para um site remoto, iniciamos um aumento múltiplo no RPS. Cada vez mais clientes usavam o auto-isolamento ou trabalhavam em casa, o que se refletia nos indicadores de carga.

Como o desempenho do "mestre" não era mais suficiente, começamos a suportar alguns dos pedidos de leitura mais pesados ​​de uma réplica. Para enviar de forma transparente solicitações de gravação para o mestre e leitura para o escravo, usamos ruby ​​gem “ Octopus" Criamos um usuário especial com o postfix _readonly sem permissões de gravação. Porém, devido a um erro na configuração de um dos hosts, parte das solicitações de gravação foi para o servidor escravo em nome de um usuário com os direitos apropriados.

O problema não se manifestou imediatamente, porque carga aumentada aumentou o atraso do escravo. A inconsistência dos dados foi revelada pela manhã quando, após as importações noturnas, os escravos não "alcançaram" o mestre. Atribuímos isso à alta carga no próprio serviço e à importação associada ao lançamento de novas lojas. Mas para dar informações para as muitas horas de atraso era inaceitável, e nós mudamos para o segundo processos analíticos do escravo, porque ele tinha usado em recursos lshie e não foi carregado solicitações de leitura (e nós explicamos-nos a ausência de lag replicação).

Quando descobrimos as razões para a "fluência" do escravo principal, o analítico já falhou pelo mesmo motivo. Apesar da presença de dois servidores adicionais, para os quais planejamos transferir a carga no caso de uma falha principal, devido a um erro infeliz, verificou-se que, em um momento crítico, não há nenhum.

Mas como não apenas despejamos o banco de dados (o restante na época era cerca de 5 horas), mas também capturamos instantaneamente o servidor principal, conseguimos iniciar a réplica em 2 horas. É verdade que, depois disso, esperávamos rolar o log de replicação por um longo tempo (porque o processo está no modo de thread único, mas essa é uma história completamente diferente).

: , readonly . , .

« »


Embora atualizemos constantemente o catálogo no site, os pedidos que fizemos aos servidores escravos permitiram um pequeno atraso do mestre. O tempo durante o qual descobrimos e eliminamos o problema de "cair repentinamente à distância" era mais do que uma "barreira psicológica" (durante esse período, os preços poderiam ter sido atualizados e os clientes teriam visto dados desatualizados) e tivemos que alternar todas as solicitações para o servidor principal do banco de dados. . Como resultado, o site funcionou lentamente ... mas pelo menos funcionou. E enquanto o Escravo estava se recuperando, não tínhamos escolha a não ser otimizar. 

Enquanto os servidores escravos estavam se recuperando, os minutos foram se arrastando lentamente, o Mestre permaneceu sobrecarregado e dedicamos todos os nossos esforços para otimizar tarefas ativas de acordo com a Regra de Pareto: selecionamos as solicitações TOP que fornecem a maior parte da carga e iniciamos o ajuste. Isso foi feito diretamente "on the fly".

Um efeito interessante foi que o MySQL carregado no globo ocular responde a até uma ligeira melhoria nos processos. A otimização de um par de solicitações, que forneceu apenas 5% da carga total, já mostrava descarga tangível da CPU. Como resultado, fomos capazes de fornecer um suprimento aceitável de recursos para o Master trabalhar com o banco de dados e obter o tempo necessário para restaurar réplicas. 

Conclusão: Mesmo uma pequena otimização permite "sobreviver" durante a sobrecarga por várias horas. Isso foi suficiente para nós durante a recuperação de servidores com réplicas. A propósito, discutiremos o lado técnico da otimização de consultas em uma das seguintes postagens. Portanto, assine o nosso blog se isso lhe for útil.

Organizar o monitoramento de desempenho dos serviços de parceiros


Estamos envolvidos no processamento de pedidos de clientes e, portanto, nossos serviços interagem constantemente com APIs de terceiros - esses são gateways para envio de SMS, plataformas de pagamento, sistemas de roteamento, geocoder, Serviço de Impostos Federais e muitos outros sistemas. E quando a carga começou a crescer rapidamente, começamos a descansar contra as limitações da API de nossos parceiros de serviço, sobre as quais nunca tínhamos pensado antes.

Excesso inesperado de cotas para serviços afiliados pode levar a seu próprio tempo de inatividade. Muitas APIs bloqueiam clientes que excedem os limites e, em alguns casos, um excesso de solicitações pode sobrecarregar a produção com um parceiro. 

Por exemplo, no momento de aumentar o número de entregas, os serviços acompanhantes não conseguiam lidar com as tarefas de distribuição, determinação de rotas. Como resultado, verificou-se que os pedidos foram feitos e o serviço que cria a rota não funciona. Devo dizer que nossos logísticos tornaram quase impossível nessas condições, e a clara interação da equipe ajudou a compensar falhas temporárias de serviço. Porém, é impossível processar esse volume de aplicativos manualmente manualmente e, após algum tempo, encontraríamos uma lacuna inaceitável entre os pedidos e sua execução. 

Várias medidas organizacionais foram tomadas e o trabalho coordenado da equipe ajudou a ganhar tempo, enquanto concordávamos com novas condições e aguardávamos a modernização dos serviços de alguns parceiros. Existem outras APIs que agradam você com alta resistência e tarifas sem Deus em caso de tráfego intenso. Por exemplo, no início, usamos uma API de mapeamento conhecida para determinar o endereço de um ponto de entrega. Mas, no final do mês, eles receberam uma conta arrumada de quase 2 milhões de rublos. Depois disso, eles decidiram substituí-lo rapidamente. Não participarei de publicidade, mas direi que nossas despesas diminuíram significativamente.

: . , « », , . , ,   . 

, « » ()


Estamos acostumados a “conectar” no banco de dados principal ou nos servidores de aplicativos, mas, ao aumentar a escala, podem aparecer problemas onde eles não eram esperados.Para pesquisa de texto completo no site, usamos o mecanismo Apache Solr. Com um aumento na carga, notamos uma diminuição no tempo de resposta e a carga do processador do servidor atingiu 100%. O que poderia ser mais simples - forneceremos mais recursos ao contêiner com o Solr.

Em vez do ganho de desempenho esperado, o servidor simplesmente "morreu". Carregou imediatamente 100% e respondeu ainda mais lentamente. Inicialmente, tínhamos 2 núcleos e 2 GB de RAM. Decidimos fazer o que geralmente ajuda - demos ao servidor 8 núcleos e 32 GB. Tudo ficou muito pior (exatamente como e por quê - contaremos em um post separado). 

Por vários dias, descobrimos os meandros desse problema e alcançamos o desempenho ideal com 8 núcleos e 32 GB. Essa configuração nos permite continuar aumentando a carga hoje, o que é muito importante, porque o crescimento não ocorre apenas em clientes, mas também no número de lojas conectadas - em 2 meses, o número dobrou. 

Conclusão: Métodos padrão como "adicione mais ferro" nem sempre funcionam. Portanto, ao expandir qualquer serviço, você precisa entender bem como ele usa recursos e pré-testar sua operação em novas condições. 

Sem estado - a chave para o dimensionamento horizontal fácil


Em geral, nossa equipe segue uma abordagem bem conhecida: os serviços não devem ter um estado sem estado e devem ser independentes do ambiente de tempo de execução. Isso nos permitiu sobreviver ao crescimento da carga por simples escala horizontal. Mas tivemos uma exceção de serviço - um manipulador para longas tarefas em segundo plano. Ele estava envolvido em enviar e-mails e sms, processar eventos, gerar feeds, importar preços e estoques e processar imagens. Aconteceu que dependia do armazenamento local de arquivos e estava em uma única cópia. 

Quando o número de tarefas na fila do processador aumentou (e isso naturalmente aconteceu com um aumento no número de pedidos), o desempenho do host que hospedava o processador e o armazenamento de arquivos tornou-se um fator limitante. Como resultado, a atualização do sortimento e dos preços, o envio de notificações aos usuários e muitas outras funções críticas presas na fila foram interrompidas. A equipe de Ops migrou rapidamente o armazenamento de arquivos para um armazenamento de rede semelhante ao S3, e isso nos permitiu criar várias máquinas poderosas para dimensionar o manipulador de tarefas em segundo plano.

Conclusão: a regra sem estado deve ser respeitada para todos os componentes, sem exceção, mesmo que pareça "que definitivamente não estamos nos incomodando". É melhor dedicar um pouco de tempo à organização correta do trabalho de todos os sistemas do que reescrever o código às pressas e reparar o serviço com sobrecarga.

7 princípios para um crescimento intenso


Apesar da disponibilidade de capacidade adicional, no processo de crescimento, demos alguns passos. Durante esse período, o número de pedidos aumentou mais de 4 vezes. Agora já entregamos mais de 17.000 pedidos por dia em 62 cidades e planejamos expandir nossa geografia ainda mais - na primeira metade de 2020, espera-se que o serviço seja lançado em toda a Rússia. Para lidar com a carga crescente, levando em conta os solavancos já cheios, desenvolvemos para nós 7 princípios básicos de trabalho em condições de crescimento constante:

  1. -. Jira,   . . — . , , , , .
  2. . « » . , , . , .
  3. . -, . -, , .
  4. stateless. , . . , , S3. https://12factor.net. , .
  5. . , . , , - . , . 
  6. . , . , SMS . , .
  7. . , . , , . API, -. .


Não sem perdas, mas sobrevivemos a esse estágio e hoje tentamos aderir a todos os princípios encontrados, e cada máquina tem a capacidade de aumentar facilmente o desempenho x4 para lidar com qualquer surpresa. 

Nas postagens seguintes, compartilharemos nossa experiência na investigação de subsidência de desempenho no Apache Solr, além de falar sobre otimização de consultas e como a interação com o Serviço Fiscal Federal ajuda a empresa a economizar dinheiro. Assine o nosso blog para não perder nada e conte-nos nos comentários se você teve esses problemas durante o crescimento do tráfego.


All Articles