Olá, meu nome é Stas Makeev. Na Yandex, lidero o desenvolvimento de tecnologia para páginas Turbo, que fornece carregamento rápido de conteúdo, mesmo com uma conexão lenta. Hoje vou contar aos leitores de Habr um pouco sobre a arquitetura do nosso projeto.
A felicidade do usuário é amplamente influenciada pela rapidez com que ele vê o conteúdo da página da web. A velocidade preocupa muitos: na loja de aplicativos para dispositivos móveis, apenas o Speedtest possui mais de cem milhões de instalações. Fornecedores, operadoras de celular, desenvolvedores de sites e aplicativos se esforçam para fornecer o acesso mais rápido ao conteúdo, para que os clientes fiquem satisfeitos.
A velocidade média de download nas redes móveis russas é de
16,26 Mbit / s - este é um bom indicador. Mas a velocidade da conexão é desigual, ainda estamos enfrentando uma conexão lenta à Internet - 3G, 2G, EDGE. Certamente você estava em uma situação em que, em um café ou shopping center, na estrada ou em uma casa de campo, a velocidade habitualmente alta é bastante reduzida: os locais são carregados por dezenas de segundos ou até mais.
A tecnologia Turbo-page resolve o problema de acesso ao conteúdo, inclusive em velocidades de conexão baixas ou instáveis. Isso é importante para os proprietários de sites que têm uma porcentagem reduzida de visitantes "caindo" durante a transição da pesquisa.

Como funcionam as páginas Turbo
O proprietário do site registra o feed RSS no Yandex.Webmaster. O feed entra no sistema de conteúdo do Turbo Pages, que leva atualizações a cada poucos minutos. Conteúdo pesado - principalmente fotos e vídeos - armazenamos e armazenamos em cache em uma CDN. Além do RSS, o conteúdo pode ser transmitido através da API e do autoparser.
O volume de imagens em cache das páginas Turbo está chegando a 100 Tb
A confiabilidade e a tolerância a falhas do sistema são importantes para nós; portanto, fazemos várias réplicas dos dados e as armazenamos em nossos três datacenters. Em cada data center, centenas de servidores processam milhares de solicitações por segundo, o que permite equilibrar a carga de maneira flexível.
O sistema de conteúdo do Turbo Pages merece uma postagem separada, e nós a escreveremos. Por enquanto, nos restringimos a um esquema simplificado.

O que acontece quando você abre um URL em um navegador?
Quando o usuário acessa a página Turbo, algo como o seguinte acontece "sob o capô":
O adaptador HTTP processa a solicitação HTTP do usuário e faz uma solicitação no gráfico desejado no AppHost e no renderizador de relatórios.
O AppHost é um componente especial que encapsula a interação de fontes na rede, descrita como um gráfico de dependência. As fontes são interrogadas na ordem de classificação topológica neste gráfico; toda a lógica de negócios é costurada nelas e na configuração do gráfico. Em particular, no nível do gráfico, o armazenamento KV é pesquisado e uma solicitação de dados é enviada para APIs de terceiros.
O renderizador de relatório é um aplicativo escrito em node.js que aceita entrada JSON, executa modelos gravados em JS e retorna uma sequência.
Tudo isso acontece quase instantaneamente.
O que afeta a velocidade do download?
Estamos trabalhando em todos os aspectos da velocidade: da implementação do HTTP / 2 no balanceador e da otimização do handshake TLS à otimização manual do SVG. Nesse caso, você precisa entender de que é composta a velocidade do usuário final.
Dentro da equipe, distinguimos três estágios do processamento de solicitações: servidor, rede e cliente.
ServidorIsso inclui tudo o que acontece nos datacenters: desde o momento em que a solicitação HTTP chega ao nosso servidor até a geração da página HTML, que é enviada diretamente ao cliente.
O tempo de processamento da solicitação no servidor deve ser mínimo. Apesar dos valores relativamente pequenos, afeta absolutamente todas as consultas do usuário. Além disso, todos os processos ocorrem em nosso ambiente controlado - simplesmente não pode haver desculpas para grandes atrasos.
O tempo do servidor consiste em interações de rede entre os vértices do gráfico de dependência de origem e os tempos de operação de cada um dos vértices. Mas não focaremos nos recursos da infraestrutura de rede dos datacenters Yandex - eles merecem uma postagem separada.
Eu gostaria de prestar mais atenção ao segundo componente - o tempo de execução de cada um dos picos. Como exemplo, vamos dar uma olhada em nossos princípios e ferramentas para trabalhar com o componente Report-renderer, responsável pela geração de HTML. Para outros componentes, eles são muito semelhantes.
Em nosso processo de IC, existem tarefas que aceitam solicitações pull no dev, que executam verificações básicas para cada confirmação na ramificação do recurso. Se algum indicador exceder os limites especificados, a influência no dev será congelada até que os motivos sejam esclarecidos.
Métricas principais nesta fase:
- hora do modelo;
- tamanho da página de resumo;
- tamanho de arquivos estáticos.
Coletamos estatísticas do cliente (CSS e JS) para cada página, dependendo dos dados, mas os pacotes configuráveis com os próprios blocos são independentes da solicitação, portanto, basta comparar o tamanho dos arquivos na ramificação com arquivos semelhantes no dev. Para diferentes tipos de arquivos, definimos diferentes valores limite, após os quais a tarefa não pode ser despejada no dev sem "OK" dos responsáveis pela velocidade.
Como regra, há uma análise conjunta do código e procura maneiras de otimizar.
Temos que agir de maneira diferente com as métricas de tamanho da página e o tempo do modelo, pois elas são altamente dependentes de uma solicitação específica e é necessário algum tipo de certeza estatística. Além disso, você não pode fazer consultas sintéticas, porque essas serão medidas desonestas. Portanto, constantemente coletamos solicitações aleatórias de usuários para logs de acesso, formamos "cartuchos" deles e "disparamos" neles com padrões no ramo com alterações e com o desenvolvedor. Isso permite capturar alterações mesmo em solicitações não muito populares.
Temos vários "cestos de pedidos" que nos permitem cobrir a maior parte do tráfego para as páginas Turbo.
Além de otimizar nossos modelos, seguimos as otimizações que ocorrem na V8. Por exemplo, a mudança para o
TurboFan produziu excelentes resultados: o tempo de modelagem no servidor foi reduzido significativamente.

O tempo de modelagem do servidor diminuiu após a mudança para o TurboFan
RedeNa parte da rede, incluímos tudo o que acontece entre o cliente e o servidor: tempo de transferência de dados, tamanho da página e estática, além de cache de recursos. Isso já é mais interessante, porque a partir de nossos aconchegantes data centers nos encontramos no mundo selvagem, onde nem tudo depende de nós. As medições se tornam um pouco mais complicadas e o mais importante - você pode obter resultados realmente tangíveis em centenas de milissegundos.
Aqui está o que fazemos.
Torcemos os parâmetros TCP e TLS, que permitem ganhar vários RTT (Round Trip Time), proporcionando excelentes resultados em redes com alta latência. Nossos colegas já
escreveram sobre isso, então não vou me aprofundar.
O tamanho dos dados transmitidos pode afetar bastante a velocidade do download, por isso tentamos enviar apenas o que a página atual precisa da maneira mais eficiente.
As imagens em nossas interfaces são otimizadas usando o ImageOptim. Para otimizar o SVG, usamos não apenas o
SVGO , mas também não temos preguiça de analisar o conteúdo e, se possível, otimizá-lo manualmente.
Carregamos imagens dos proprietários do site em uma CDN especial, otimizada para a renderização de imagens. Recortamos o perfil exif e de cores da imagem, primeiro convertendo a imagem em sRGB. A taxa de bits é reduzida para 8 bits por canal, o nível de compressão é definido como 85. O filtro lanczos é usado para redimensionar.
Criamos dezenas de opções para cada imagem para uma combinação de diferentes tamanhos de tela, levando em consideração a densidade de pixels (telas de retina). E, é claro, codificamos automaticamente imagens no formato WebP, se suportadas pelo navegador.
Os formatos de texto (HTML, JavaScript, CSS) são compactados usando gzip / zopfli e brotli, se o navegador suportar.
É importante não esquecer a distância dos usuários dos servidores. As páginas Turbo são usadas em muitas regiões e o conteúdo pode ser qualquer um. Portanto, não comprometemos e reduzimos a latência, mesmo nas regiões mais remotas que usamos CDN, que está em constante expansão.
E, claro, a consulta mais rápida é que eles não fazem nada. Todas as estáticas são fornecidas com o cache eterno de um domínio separado sem cookies e, para aumentar o acerto do cache, ainda pode ser adicionalmente aquecido na página principal e na página com os resultados da pesquisa.
ClienteNão basta formar uma resposta do servidor e entregá-la ao navegador pela rede, ele ainda precisa ser mostrado com eficácia. Otimizamos o horário de início da renderização da página para que a pessoa comece a ler o conteúdo mais rapidamente.
No cabeçalho HTML, "aquecemos" a conexão com nossos servidores de distribuição estática e a pré-carregamos adicionalmente. Estilos embutidos na página, o que permite que o navegador comece a renderizar a página sem aguardar o carregamento dos estilos pela rede.
Imagens de conteúdo, incorporações e anúncios não são carregados imediatamente, mas quando eles leem a página, quando se aproximam do campo de visão do usuário.
O JavaScript é parcialmente incorporado ao HTML e todos os outros scripts são carregados no final com solicitações HTTP separadas. Os scripts críticos para iniciar, a coleção de erros e métricas, bem como os componentes que geralmente não são encontrados na página, são incorporados na página.
Coletamos métricas de carregamento de página RUM. O mais crítico: o tempo até o primeiro byte, o primeiro desenho e o início da interatividade, quando todos os scripts concluíram a inicialização e o usuário pode usar a página.
A maioria dos usuários não acessa as páginas Turbo diretamente, mas de outros serviços Yandex, e queríamos avaliar o tempo de carregamento da página no contexto da experiência do usuário. Não apenas obtendo tempo abstrato no vácuo, mas uma métrica de como o usuário vê tudo.
Por isso, formulamos a métrica de velocidade integral:
max (firstContentfulPaint, firstImageLoadTime, timeToVisible) — timeToClick
Onde:
- timeToClick - tempo absoluto de clique que levou à exibição da página Turbo. Pode ser um clique em um trecho na página de resultados da pesquisa ou em um cartão no Yandex.Zen.
- firstImageLoadTime - tempo de carregamento absoluto da primeira imagem de conteúdo na primeira tela.
- timeToVisible - o tempo absoluto em que a página entra no estado visível. Isso ocorre nos casos em que a página foi carregada em segundo plano.
E obteve uma métrica de experiência do usuário:
- se 2/3 da tela estiver ocupada por uma imagem que ainda não foi carregada, a integridade da primeira métricaContentfulPaint será bastante duvidosa;
- existem muitos manipuladores de eventos nos links, entre o clique e o horário de início real da página que carrega um horário diferente de zero, o que eu gostaria de entender.

Estamos constantemente desenvolvendo tecnologia para que os sites atraiam mais visitantes. Agora, uma página Turbo carrega em média 15 vezes mais rápido que uma versão móvel comum. Dezenas de milhares de sites usam o Turbo, e o número total de visitas a eles é superior a 12 bilhões.
Tudo isso é resultado do trabalho de desenvolvedores, serviços de suporte, gerentes que trabalham com proprietários de sites e muitos outros. Com o tempo, a equipe, é claro, se expande. Por exemplo, agora estamos procurando especialistas
em front-end e back-end e teremos prazer em conhecer novos colegas.
Quais componentes da tecnologia Turbo Page você gostaria de ler materiais técnicos mais detalhados no futuro? Em que experiência você estaria interessado? Também receberemos feedback e idéias. Obrigada