BLOG | NGINX

Módulo de gerenciamento de API do controlador NGINX vs. Conde: Comparação de desempenho

NGINX-Parte-de-F5-horiz-preto-tipo-RGB
Miniatura de Faisal Memon
Faisal Memon
Publicado em 06 de maio de 2019

O mercado de gerenciamento de API (APIM) é um espaço concorrido. O mais recente Quadrante Mágico da Gartner para Gerenciamento de API do Ciclo de Vida Completo classifica 22 fornecedores, com 7 no quadrante de Líderes. Competir em um mercado existente exige estabelecer uma posição forte para se diferenciar e se destacar da concorrência. Então, o que torna a solução de gerenciamento de API da NGINX diferente?

Na NGINX, nosso objetivo é criar software leve e de alto desempenho. O NGINX Open Source se tornou o servidor web preferido para os sites mais movimentados do mundo porque sua arquitetura orientada a eventos é melhor escalável do que servidores web que geram um processo ou thread para cada conexão. O NGINX Open Source também é o gateway de API mais onipresente do setor, um componente de infraestrutura que processa o tráfego de API em soluções APIM como as da Apigee, Axway, IBM DataPower, Kong, Red Hat 3scale e Torry Harris.

O NGINX Controller API Management Module é uma solução APIM de alto desempenho. Neste blog, compararemos seu desempenho com o Kong, um concorrente conhecido por seu alto desempenho. O Kong é construído no NGINX e usa Lua para implementar sua funcionalidade de API, enquanto o Módulo de Gerenciamento de API depende completamente de recursos nativos de alto desempenho que são implementados como módulos NGINX Plus. A solução de gerenciamento de API da NGINX é construída em uma arquitetura inovadora que separa o plano de dados do plano de controle. Todas as chamadas de API são tratadas diretamente pelo NGINX Plus, atuando como gateway de API (plano de dados), sem exigir nenhuma interação com o plano de controle. Isso resulta em mediação de tráfego de API de alto desempenho para tráfego norte-sul e leste-oeste.

Uma prévia dos resultados: o NGINX Controller API Management Module supera o Kong em 2x.

Um agradecimento especial à Intel por fornecer o hardware e o espaço de laboratório usados para realizar esses testes. Detalhes completos do teste e do hardware podem ser encontrados no Apêndice .

Latência adicionada a uma única solicitação

Neste teste, comparamos a latência adicional introduzida pelo gerenciador de API a uma única solicitação, para arquivos de 0 KB e 1 KB de tamanho. Usamos curl para enviar a única solicitação HTTP ( detalhes ).

O Kong aumenta a latência em comparação ao Módulo de Gerenciamento de API: em 44% para um arquivo de 0 KB e 24% para um arquivo de 1 KB.

Chamadas de API por segundo

Uma métrica de escalabilidade HTTP padrão é solicitações por segundo (RPS). A métrica equivalente no contexto do APIM são chamadas de API por segundo. Usamos o wrk para enviar um fluxo contínuo de solicitações para um arquivo de 0 KB ou 1 KB , em 300 conexões por 3 minutos ( detalhes ).

O Módulo de Gerenciamento de API superou o Kong, lidando com 2,6x mais chamadas de API por segundo para respostas de 1 KB .

Uso da CPU

O Módulo de Gerenciamento de API introduz menos latência e lida com mais chamadas de API por segundo do que o Kong porque usa a CPU de forma mais eficiente. Medimos o uso da CPU em números crescentes de chamadas de API por segundo. Usamos um único núcleo, então o número absoluto de chamadas de API por segundo é muito menor do que no teste anterior, onde usamos 22 núcleos ( detalhes ).

O Kong efetivamente atinge o limite de 5.000 chamadas de API por segundo – a latência aumenta consideravelmente em volumes de chamadas maiores que isso, indicando que o sistema está totalmente carregado. Com 5.000 chamadas por segundo, o uso da CPU é de 93%, 73% maior que o Módulo de Gerenciamento de API.

Chamadas de API por segundo com JWTs

O teste final mede o quão bem cada gateway de API valida JSON Web Tokens (JWTs), o método preferido para autenticação de solicitações de API. Seus endpoints de API mais importantes provavelmente serão autenticados, então este teste se aproxima mais de uma configuração do mundo real.

Usamos o mesmo JWT, assinado usando HS256, com ambos os gateways ( detalhes ).

O Módulo de Gerenciamento de API processa mais de 2x mais chamadas de API autenticadas por JWT por segundo do que o Kong.

Como funciona o controlador NGINX

O NGINX Controller é uma solução de plano de controle que gerencia o plano de dados NGINX Plus. O NGINX Controller permite que você gerencie todo o ciclo de vida do NGINX Plus, como um balanceador de carga, gateway de API ou proxy em um ambiente de malha de serviço. Com o Módulo de Gerenciamento de API do NGINX Controller, você pode definir, publicar, proteger, monitorar e analisar APIs.

Nos bastidores, o NGINX Controller gera a configuração do NGINX Plus que é publicada no plano de dados NGINX Plus subjacente. O carregador de configuração principal tem um mecanismo muito eficiente para armazenar configurações na memória, permitindo que o Módulo de Gerenciamento de API ofereça alto desempenho para APIs.

Conclusão

Muitas empresas já usam o NGINX Open Source como seu gateway de API. O Capital One conseguiu escalar para mais de 12 bilhões de chamadas de API por dia usando o NGINX Open Source. De fato, muitos dos nossos concorrentes, incluindo a Kong, usam o NGINX Open Source em suas soluções APIM. Nosso design leve – baseado na configuração nativa de alto desempenho do NGINX junto com os módulos NGINX Plus – permite que o Módulo de Gerenciamento de API seja dimensionado melhor do que a concorrência derivada do NGINX.

A latência é uma das métricas mais importantes para a experiência do usuário final. Alta latência reduz a capacidade de resposta do aplicativo, frustrando os usuários. O Módulo de Gerenciamento de API adiciona 20–30% menos latência às solicitações do usuário em comparação ao Kong. Ele também usa os recursos do sistema de forma mais eficiente, usando 40% menos CPU que o Kong para a mesma carga de trabalho.


Apêndice

Topologia

Todos os testes foram feitos usando três máquinas separadas conectadas por links de 10 GbE em uma rede de Camada 2 simples e plana.

Hardware usado

O seguinte hardware foi usado para o teste. Todas as três máquinas eram idênticas. Hyperthreading não foi usado. Em testes anteriores, não observamos uma grande diferença no desempenho do hyperthreading.

CPU Rede Memória
CPU Intel® Xeon(R) E5‑2699 v4 @ 2,20 GHz, 22 núcleos Controlador Intel Ethernet 10 Gigabit X540 AT2 128 GB

Software usado

O seguinte software foi usado para fazer o teste:

  • Módulo de gerenciamento de API do controlador NGINX versão 2.
  • Kong Open Source versão 1.0.0. Não testamos o Kong Enterprise, mas nenhum de seus recursos adicionais é relevante para nossos testes (por exemplo, o Kong Open Source e o Kong Enterprise usam o mesmo plug-in JWT).
  • curl versão 7.61.0.
  • Versão do Docker 18.09.1. Para facilitar o gerenciamento, executamos o Kong e o Módulo de Gerenciamento de API dentro de contêineres Docker. Descobrimos que o Docker reduz o desempenho em cerca de 30%, mas como estamos comparando o desempenho relativo, os benefícios de usar o Docker superaram o impacto no desempenho.
  • mpstat na versão 12.0.1 do pacote systat .
  • wrk versão 4.1.0, instalado de acordo com estas instruções .

Configuração NGINX

A seguinte configuração do NGINX foi usada para o teste.

upstream my_upstream { keepalive 60; servidor API-server :80; keepalive_requests 3000000; keepalive_timeout 300; } servidor { listen 8000; access_log off; keepalive_requests 3000000; keepalive_timeout 300; tcp_nodelay on; localização /test { set $apimgmt_environment 4; set $apimgmt_definition 3; set $upstream my_upstream; set $upstream_protocol http; rewrite ^ /_devel_4 last; } localização = /_devel_4 { interno; set $apimgmt_definition_name my_api; set $apimgmt_environment_name devel; proxy_intercept_errors on; proxy_http_version 1.1; proxy_set_header Conexão ""; proxy_pass $upstream_protocol://$upstream/0kb; # arquivo de 0 KB #proxy_pass $upstream_protocol://$upstream/1kb.bin; # arquivo de 1 KB } }

Fizemos as seguintes configurações para maximizar o desempenho. Conforme detalhado na próxima seção, fizemos configurações semelhantes na configuração do Kong.

  • keepalive_requests e keepalive_timeout foram definidos como um número alto para minimizar a sobrecarga da configuração de conexões TCP.
  • tcp_nodelay foi habilitado, melhorando ligeiramente o desempenho ao desabilitar o algoritmo de Nagle.
  • access_log foi desabilitado. Habilitá-lo reduz o desempenho em cerca de 10%.
  • Usamos as duas diretivas proxy_pass para solicitar o tamanho de arquivo apropriado.

Configuração Kong

Adicionamos as seguintes diretivas de configuração ao kong.conf.default , correspondendo às configurações do NGINX discutidas na seção anterior.

nginx_http_tcp_nodelay=onnginx_http_keepalive_requests=3000000
nginx_http_keepalive_timeout=300
proxy_access_log=off

Executamos as seguintes chamadas da API do Kong para criar uma rota para o servidor da API. O primeiro comando cria um serviço chamado test e o segundo cria a rota /test apontando para o servidor.

$ curl -X POST http://localhost:8001/services/ \ --data 'nome=teste' \ --data 'url=http:// Servidor API :80/0kb' $ curl -X POST http://localhost:8001/services/teste/rotas \ --data 'caminhos[]=/teste'

Os comandos a seguir exibem a configuração do serviço e da rota, respectivamente. Enviamos a saída para a ferramenta jq para facilitar a leitura da saída JSON.

$ curl localhost:8001/services/ | jq '.' { "próximo": nulo, "dados": [ { "host": "172.20.40.32", "criado_em": 1556770191, "tempo_limite_de_conexão": 60000, "id": "f4629d56-550b-4b37-aa59-66d931aa6f37", "protocolo": "http", "nome": "teste", "tempo_limite_de_leitura": 60000, "porta": 80, "caminho": "/0kb", "updated_at": 1556770191, "novas tentativas": 5, "tempo_limite_de_gravação": 60000 } ] } $ curl localhost:8001/services/test/routes | jq '.' { "next": nulo, "data": [ { "created_at": 1556770191, "métodos": nulo, "id": "a7b417af-ccd4-48f7-b787-ae19490194dc", "serviço": { "id": "f4629d56-550b-4b37-aa59-66d931aa6f37" }, "nome": nulo, "hosts": nulo, "updated_at": 1556770191, "preserve_host": falso, "regex_priority": 0, "caminhos": [ "/teste" ], "fontes": nulo, "destinos": nulo, "snis": nulo, "protocolos": [ "http", "https" ], "strip_path": verdadeiro } ] }

Metodologia de Teste

Latência adicionada a uma única solicitação

Usamos curl para o teste de latência de solicitação única. Para definir uma linha de base, primeiro fizemos uma solicitação ao servidor de API sem um gateway de API na frente dele. Em seguida, fizemos a mesma solicitação com cada gateway de API na frente do servidor de API para medir a latência que eles introduziram.

$ curl -w "@curl-latency.txt" -o /dev/null -s http:// servidor-de-alvo

O conteúdo de curl-latency.txt :

    time_namelookup: %{time_namelookup}\n
time_connect: %{time_connect}\n
time_appconnect: %{time_appconnect}\n
time_pretransfer: %{time_pretransfer}\n
time_redirect: %{time_redirect}\n
time_starttransfer: %{time_starttransfer}\n
----------\n
time_total: %{time_total}\n

O gráfico em Latência adicionada a uma única solicitação mostra time_total , em milissegundos. Aqui está um exemplo de saída:

$ curl -w "@curl-latency.txt" -o /dev/null -s http://192.0.2.1/api-endpoint time_namelookup:  0,000035 tempo_conexão:  0,000364 tempo_appconnect:  0,000000 tempo_pré-transferência:  0,000401 tempo_redirecionamento:  0,000000 time_starttransfer:  0,001701 ---------- tempo_total:  0.001727

Chamadas de API por segundo

Testamos chamadas de API por segundo com o wrk , uma ferramenta de benchmarking escalável que usamos com frequência. Tentamos várias combinações de parâmetros, e esta maximizou o desempenho tanto do Módulo de Gerenciamento de API quanto do Kong:

$ wrk -t 22 -c 300 -d 180 http:// servidor-alvo

O comando cria 22 threads de trabalho (1 por núcleo) e um total de 300 conexões entre os threads. O parâmetro -d especifica a duração do teste, no nosso caso 180 segundos (3 minutos). Exemplo de saída:

$ wrk -t 22 -c 300 -d 180 http://192.0.2.1/api-endpoint Executando teste de 3m em http://192.0.2.1/api-endpoint 22 threads e 300 conexões Estatísticas de thread Desvio padrão médio Máx. +/- Desvio padrão Latência 13,96 ms 7,84 ms 279,85 ms 77,37% Req/seg 0,96 k 298,23 1,88 k 68,55% 3769861 solicitações em 3,00 m, 36,25 GB de leitura Solicitações/seg:  20934.34 Transferência/seg:    206,16 MB

Uso da CPU

Testamos o uso da CPU com mpstat (uma ferramenta Linux padrão para essa finalidade) enquanto executamos o comando wrk para chamadas de API por segundo. Exemplo de saída (distribuído em duas linhas para legibilidade):

$ mpstat Linux 4.18.0-13-generic (nbdw38) 29/04/2019 _x86_64_ (88 CPU) 15:34:50 CPU %usr %nice %sys %iowait %irq %soft %steal ...
03:34:50 PM todos 0,04 0,00 0,02 0,00 0,00 0,03 0,00 ... ... %convidado %gnice %ocioso ...   0.00    0.00   99.91

Chamadas de API por segundo com JWTs

Testamos o desempenho do JWT com o comando wrk para chamadas de API por segundo, com a adição do parâmetro -H para inserir o JWT na Autorização: Portador Cabeçalho HTTP. Geramos o JWT e as JSON Web Keys (JWKs) usando as instruções nesta postagem do blog , armazenando o JWT em um arquivo chamado test.jwt .

$ wrk -t 22 -c 300 -d 180 -H "Autorização: Portador `cat test.jwt`" \ http:// target-server

"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."