Rendemento da aplicación de rede Linux. Introdución

As aplicacións web utilízanse agora en todas partes, e entre todos os protocolos de transporte, HTTP ocupa a parte do león. Ao estudar os matices do desenvolvemento de aplicacións web, a maioría da xente presta moi pouca atención ao sistema operativo onde se executan estas aplicacións. A separación de desenvolvemento (Dev) e operacións (Ops) só empeorou a situación. Pero co auxe da cultura DevOps, os desenvolvedores están a ser responsables de executar as súas aplicacións na nube, polo que é moi útil que se familiaricen a fondo co backend do sistema operativo. Isto é especialmente útil se estás tentando implantar un sistema para miles ou decenas de miles de conexións simultáneas.

As limitacións dos servizos web son moi similares ás doutras aplicacións. Tanto se se trata de equilibradores de carga como de servidores de bases de datos, todas estas aplicacións teñen problemas similares nun ambiente de alto rendemento. Comprender estas limitacións fundamentais e como superalas en xeral axudarache a avaliar o rendemento e a escalabilidade das túas aplicacións web.

Escribo esta serie de artigos en resposta ás preguntas de novos desenvolvedores que queren converterse en arquitectos de sistemas ben informados. É imposible comprender claramente as técnicas de optimización de aplicacións Linux sen mergullarse nos conceptos básicos de como funcionan a nivel de sistema operativo. Aínda que hai moitos tipos de aplicacións, nesta serie quero explorar aplicacións baseadas na web en lugar de aplicacións de escritorio como un navegador ou un editor de texto. Este material está destinado a desenvolvedores e arquitectos que queiran entender como funcionan os programas Linux ou Unix e como estruturalos para un alto rendemento.

Linux é sala de servidores sistema operativo e, a maioría das veces, as súas aplicacións execútanse neste SO. Aínda que digo "Linux", a maioría das veces pode asumir con seguridade que me refiro a todos os sistemas operativos similares a Unix en xeral. Non obstante, non probei o código que se acompaña noutros sistemas. Polo tanto, se estás interesado en FreeBSD ou OpenBSD, os teus resultados poden variar. Cando intento algo específico de Linux, sináloo.

Aínda que podes usar este coñecemento para crear unha aplicación desde cero e estará perfectamente optimizada, é mellor non facelo. Se escribes un novo servidor web en C ou C++ para a aplicación empresarial da túa organización, este pode ser o teu último día no traballo. Non obstante, coñecer a estrutura destas aplicacións axudará a elixir os programas existentes. Poderás comparar sistemas baseados en procesos con sistemas baseados en fíos, así como con sistemas baseados en eventos. Comprenderás e apreciarás por que Nginx funciona mellor que Apache httpd, por que unha aplicación Python baseada en Tornado pode servir a máis usuarios en comparación cunha aplicación Python baseada en Django.

ZeroHTTPd: Ferramenta de aprendizaxe

ZeroHTTPd é un servidor web que escribín desde cero en C como ferramenta didáctica. Non ten dependencias externas, incluído o acceso a Redis. Realizamos os nosos propios procedementos Redis. Vexa a continuación para obter máis detalles.

Aínda que poderiamos discutir a teoría en detalle, non hai nada mellor que escribir código, executalo e comparar todas as arquitecturas de servidor entre si. Este é o método máis obvio. Polo tanto, escribiremos un servidor web ZeroHTTPd sinxelo usando cada modelo: baseado en procesos, baseado en fíos e baseado en eventos. Vexamos cada un destes servidores e vexamos como funcionan en comparación entre eles. ZeroHTTPd está implementado nun único ficheiro C. O servidor baseado en eventos inclúe uthash, unha excelente implementación de táboas hash que vén nun único ficheiro de cabeceira. Noutros casos non hai dependencias, para non complicar o proxecto.

Hai moitos comentarios no código para axudarche a entender. Sendo un servidor web simple en poucas liñas de código, ZeroHTTPd tamén é un marco mínimo para o desenvolvemento web. Ten unha funcionalidade limitada, pero é capaz de servir ficheiros estáticos e páxinas "dinámicas" moi sinxelas. Teño que dicir que ZeroHTTPd é bo para aprender a crear aplicacións Linux de alto rendemento. En xeral, a maioría dos servizos web agardan solicitudes, compróbaas e procesalas. Isto é exactamente o que fará ZeroHTTPd. Esta é unha ferramenta de aprendizaxe, non de produción. Non é excelente para manexar erros e é improbable que presuma das mellores prácticas de seguranza (oh, si, usei strcpy) ou os intelixentes trucos da linguaxe C. Pero espero que faga ben o seu traballo.

Rendemento da aplicación de rede Linux. Introdución
Páxina de inicio de ZeroHTTPd. Pode producir diferentes tipos de ficheiros, incluíndo imaxes

Aplicación de libro de visitas

As aplicacións web modernas normalmente non se limitan a ficheiros estáticos. Teñen interaccións complexas con diversas bases de datos, cachés, etc. Así que imos crear unha sinxela aplicación web chamada "Guest Book" onde os visitantes deixan entradas baixo os seus nomes. O libro de visitas almacena as entradas que quedaron antes. Tamén hai un contador de visitantes na parte inferior da páxina.

Rendemento da aplicación de rede Linux. Introdución
Aplicación web "Guest Book" ZeroHTTPd

O contador de visitantes e as entradas do libro de visitas almacénanse en Redis. Para as comunicacións con Redis impléntanse procedementos propios, non dependen da biblioteca externa. Non son un gran fan de lanzar código homebrew cando hai solucións dispoñibles publicamente e ben probadas. Pero o propósito de ZeroHTTPd é estudar o rendemento de Linux e o acceso a servizos externos, mentres que atender solicitudes HTTP ten un serio impacto no rendemento. Debemos controlar totalmente as comunicacións con Redis en cada unha das nosas arquitecturas de servidor. Nalgunhas arquitecturas usamos chamadas de bloqueo, noutras usamos procedementos baseados en eventos. O uso dunha biblioteca cliente de Redis externa non proporcionará este control. Ademais, o noso pequeno cliente Redis só realiza algunhas funcións (obter, configurar e incrementar unha clave; obter e engadir a unha matriz). Ademais, o protocolo Redis é extremadamente elegante e sinxelo. Nin sequera necesitas ensinalo especialmente. O feito de que o protocolo faga todo o traballo nunhas cen liñas de código mostra o ben pensado que está.

A seguinte figura mostra o que fai a aplicación cando o cliente (navegador) solicita /guestbookURL.

Rendemento da aplicación de rede Linux. Introdución
Como funciona a aplicación do libro de visitas

Cando é necesario emitir unha páxina do libro de visitas, hai unha chamada ao sistema de ficheiros para ler o modelo na memoria e tres chamadas de rede a Redis. O ficheiro de modelo contén a maior parte do contido HTML da páxina na captura de pantalla anterior. Tamén hai marcadores de posición especiais para a parte dinámica do contido: publicacións e contador de visitantes. Recibimos de Redis, insérmolos na páxina e ofrecémoslle ao cliente contido totalmente formado. A terceira chamada a Redis pódese evitar porque Redis devolve o novo valor da chave cando se incrementa. Non obstante, para o noso servidor, que ten unha arquitectura asincrónica baseada en eventos, moitas chamadas de rede son unha boa proba para propósitos de aprendizaxe. Entón, descartamos o valor de retorno de Redis do número de visitantes e consultamos cunha chamada separada.

Arquitecturas de servidor ZeroHTTPd

Estamos construíndo sete versións de ZeroHTTPd coa mesma funcionalidade pero con diferentes arquitecturas:

  • Iterativo
  • Servidor fork (un proceso secundario por solicitude)
  • Servidor pre-fork (pre-fork de procesos)
  • Servidor con fíos de execución (un fío por solicitude)
  • Servidor con creación previa ao fío
  • Baseado en arquitectura poll()
  • Baseado en arquitectura epoll

Medimos o rendemento de cada arquitectura cargando o servidor con solicitudes HTTP. Pero ao comparar arquitecturas altamente paralelas, o número de consultas aumenta. Probamos tres veces e calculamos a media.

Metodoloxía de proba

Rendemento da aplicación de rede Linux. Introdución
Configuración da proba de carga ZeroHTTPd

É importante que ao executar probas, todos os compoñentes non funcionen na mesma máquina. Neste caso, o sistema operativo incorre en sobrecarga adicional de programación xa que os compoñentes compiten pola CPU. Medir a sobrecarga do sistema operativo de cada unha das arquitecturas de servidor seleccionadas é un dos obxectivos máis importantes deste exercicio. Engadir máis variables será prexudicial para o proceso. Polo tanto, a configuración da imaxe superior funciona mellor.

Que fai cada un destes servidores?

  • load.unixism.net: aquí é onde corremos ab, utilidade Apache Benchmark. Xera a carga necesaria para probar as nosas arquitecturas de servidor.
  • nginx.unixism.net: Ás veces queremos executar máis dunha instancia dun programa de servidor. Para iso, o servidor Nginx coa configuración adecuada funciona como un equilibrador de carga procedente ab aos procesos do noso servidor.
  • zerohttpd.unixism.net: Aquí executamos os nosos programas de servidor en sete arquitecturas diferentes, unha á vez.
  • redis.unixism.net: este servidor executa o daemon Redis, onde se almacenan as entradas do libro de visitas e os contadores de visitantes.

Todos os servidores funcionan no mesmo núcleo de procesador. A idea é avaliar o máximo rendemento de cada arquitectura. Dado que todos os programas de servidor son probados no mesmo hardware, esta é unha referencia para a comparación. A miña configuración de proba consiste en servidores virtuais alugados a Digital Ocean.

Que estamos medindo?

Podes medir diferentes indicadores. Avaliamos o rendemento de cada arquitectura nunha determinada configuración cargando os servidores con peticións a diferentes niveis de paralelismo: a carga medra de 20 a 15 usuarios simultáneos.

Resultados da proba

O seguinte gráfico mostra o rendemento dos servidores en diferentes arquitecturas en diferentes niveis de paralelismo. O eixe Y é o número de solicitudes por segundo, o eixe X son conexións paralelas.

Rendemento da aplicación de rede Linux. Introdución

Rendemento da aplicación de rede Linux. Introdución

Rendemento da aplicación de rede Linux. Introdución

Abaixo está unha táboa cos resultados.

solicitudes por segundo

paralelismo
iterativo
garfo
pre-garfo
en streaming
pre-streaming
votación
epollo

20
7
112
2100
1800
2250
1900
2050

50
7
190
2200
1700
2200
2000
2000

100
7
245
2200
1700
2200
2150
2100

200
7
330
2300
1750
2300
2200
2100

300
-
380
2200
1800
2400
2250
2150

400
-
410
2200
1750
2600
2000
2000

500
-
440
2300
1850
2700
1900
2212

600
-
460
2400
1800
2500
1700
2519

700
-
460
2400
1600
2490
1550
2607

800
-
460
2400
1600
2540
1400
2553

900
-
460
2300
1600
2472
1200
2567

1000
-
475
2300
1700
2485
1150
2439

1500
-
490
2400
1550
2620
900
2479

2000
-
350
2400
1400
2396
550
2200

2500
-
280
2100
1300
2453
490
2262

3000
-
280
1900
1250
2502
gran difusión
2138

5000
-
gran difusión
1600
1100
2519
-
2235

8000
-
-
1200
gran difusión
2451
-
2100

10
-
-
gran difusión
-
2200
-
2200

11
-
-
-
-
2200
-
2122

12
-
-
-
-
970
-
1958

13
-
-
-
-
730
-
1897

14
-
-
-
-
590
-
1466

15
-
-
-
-
532
-
1281

Na gráfica e na táboa pódese ver que por riba das 8000 solicitudes simultáneas só nos quedan dous xogadores: pre-fork e epoll. A medida que aumenta a carga, un servidor baseado en enquisas funciona peor que un de streaming. A arquitectura de pre-creación de fíos é un digno competidor para epoll, unha proba do ben que o núcleo de Linux programa un gran número de fíos.

Código fonte ZeroHTTPd

Código fonte ZeroHTTPd aquí. Hai un directorio separado para cada arquitectura.

ZeroHTTPd │ ├── 01_iterativo │ ├── main.c ├── 02_forking │ ├── main.c ├─── 03_preforking │── main.─── 04_ rosca │ ├── main.c ├── 05_prethreading │ ├── main.c ├── 06_poll │ ├── main.c ├── 07_epoll │ └── main.c ─ Facer público o ficheiro main.c ├─── ├── índice .html │ └── tux . png └── modelos └── libro de visitas └── index.html

Ademais de sete directorios para todas as arquitecturas, hai dous máis no directorio de nivel superior: público e modelos. O primeiro contén o ficheiro index.html e a imaxe da primeira captura de pantalla. Podes poñer alí outros ficheiros e cartafoles e ZeroHTTPd debería servir eses ficheiros estáticos sen ningún problema. Se a ruta do navegador coincide coa ruta do cartafol público, ZeroHTTPd busca o ficheiro index.html neste directorio. O contido do libro de visitas xérase de forma dinámica. Só ten unha páxina de inicio e o seu contido baséase no ficheiro 'templates/guestbook/index.html'. ZeroHTTPd engade facilmente páxinas dinámicas para ampliar. A idea é que os usuarios poidan engadir modelos a este directorio e estender ZeroHTTPd segundo sexa necesario.

Para construír os sete servidores, executa make all desde o directorio de nivel superior - e todas as compilacións aparecerán neste directorio. Os ficheiros executables buscan os directorios públicos e de modelos no directorio desde o que se lanzan.

API de Linux

Non é preciso ter un bo coñecemento da API de Linux para comprender a información desta serie de artigos. Non obstante, recomendo ler máis sobre este tema, xa que hai moitos recursos de referencia en Internet. Aínda que abordaremos varias categorías de API de Linux, o noso foco centrarase principalmente nos procesos, fíos, eventos e a pila de rede. Ademais de libros e artigos sobre a API de Linux, tamén recomendo ler mana para as chamadas ao sistema e as funcións de biblioteca utilizadas.

Rendemento e escalabilidade

Unha nota sobre o rendemento e a escalabilidade. Teoricamente, non hai conexión entre eles. Podes ter un servizo web que funcione moi ben, cun tempo de resposta duns milisegundos, pero non se escala en absoluto. Así mesmo, pode haber unha aplicación web de mal rendemento que tarda uns segundos en responder, pero escala en decenas para xestionar decenas de miles de usuarios simultáneos. Non obstante, a combinación de alto rendemento e escalabilidade é unha combinación moi poderosa. As aplicacións de alto rendemento xeralmente usan os recursos con moderación e, polo tanto, serven de forma eficiente a máis usuarios concorrentes no servidor, reducindo os custos.

Tarefas de CPU e E/S

Finalmente, en informática sempre hai dous tipos posibles de tarefas: para E/S e CPU. Recibir solicitudes a través de Internet (E/S de rede), servir ficheiros (E/S de rede e disco), comunicarse coa base de datos (E/S de rede e de disco) son todas actividades de E/S. Algunhas consultas de bases de datos poden ser un pouco intensivas en CPU (clasificación, promediando un millón de resultados, etc.). A maioría das aplicacións web están limitadas pola máxima E/S posible e o procesador raramente se usa a plena capacidade. Cando ves que algunha tarefa de E/S está a usar moita CPU, o máis probable é que sexa un sinal dunha arquitectura de aplicación deficiente. Isto pode significar que se malgasten os recursos da CPU na xestión de procesos e no cambio de contexto, e isto non é de todo útil. Se estás facendo algo como o procesamento de imaxes, a conversión de ficheiros de audio ou a aprendizaxe automática, entón a aplicación require poderosos recursos da CPU. Pero para a maioría das aplicacións este non é o caso.

Máis información sobre as arquitecturas de servidores

  1. Parte I: Arquitectura Iterativa
  2. Parte II. Servidores fork
  3. Parte III. Servidores pre-fork
  4. Parte IV. Servidores con fíos de execución
  5. Parte V. Servidores pre-thread
  6. Parte VI. Arquitectura baseada en Pol
  7. Parte VII. arquitectura baseada en epoll

Fonte: www.habr.com

Engadir un comentario