2. Aplicando teste de carga na plataforma Dojot

Neste tutorial será demonstrado como rodar um teste de carga usando a implementação do Locust feita para a dojot.

Atenção

A implementação do Locust foi feita para realizar testes com o VerneMQ. Testes com o Mosca não têm garantia de funcionamento.

2.1. Preparando o ambiente

Primeiramente, você precisa de um ambiente dojot rodando. Verifique o Guia de instalação para mais informações.

To access the Locust implementation, download the dojot repository on your machine and switch to the same version as your current environment:

git clone https://github.com/dojot/dojot.git
cd dojot
git checkout v0.5.0

Entre na pasta do Locust:

cd connector/mqtt/locust

2.2. Rodando um teste simples

In this section, it will be shown how to configure and run Locust, and also how to generate certificates with the generate_certs script in order to execute the load test. This is a simple test where will be created 100 clients to send messages to dojot.

2.2.1. Configuração

Nota

Verifique o README incluído no diretório do Locust para aprender mais sobre a arquitetura e configurações. Neste tutorial serão cobertas somente as configurações mais importantes.

Antes de rodar os testes, algumas configurações nos arquivos de docker compose do Locust precisam ser alteradas.

Abra o arquivo Docker/docker-compose-master.yml e mude as seguintes variáveis de ambiente:

# The location of your dojot installation
DOJOT_URL: "http://1.2.3.4"
# Usually it's the dojot address too (if you don't know for sure, keep the same address as dojot)
DOJOT_MQTT_HOST: "1.2.3.4"
# The default MQTTS port
DOJOT_MQTT_PORT: "8883"

Abra o arquivo Docker/docker-compose-slave.yml e mude as seguintes variáveis de ambiente:

# The location of your dojot installation
DOJOT_URL: "http://1.2.3.4"
# Usually it's the dojot address too (if you don't know for sure, keep the same address as dojot)
DOJOT_MQTT_HOST: "1.2.3.4"
# The default MQTTS port
DOJOT_MQTT_PORT: "8883"

Nota

Estamos assumindo que você está rodando o master e o slave na mesma máquina, i.e. no modo não distribuído. Mais à frente será mostrado como distribuir os slaves em múltiplas máquinas.

Abra o arquivo Docker/scripts/generate_certs/docker-compose.yml e mude as seguintes variáveis de ambiente:

# The location of your dojot installation
DOJOT_URL: "http://1.2.3.4"

2.2.2. Gerando os certificados

As said before, the communication from Locust to dojot is secure, then, it is necessary to use certificates.

Existem duas maneiras de se simular os dispositivos: você pode criar dispositivos falsos (que não aparecerão na GUI da dojot) ou dispositivos reais. Nesta parte do tutorial serão criados os dispositivos reais para que você possa verificar a chegada das mensagens na GUI.

Antes de rodar o script, é necessário inicializar o Locust master. Dentro do repositório do Locust, rode:

docker-compose -f Docker/docker-compose-master.yml up

Após sua inicialização, rode o contêiner do script generate_certs e entre nele:

docker-compose -f Docker/scripts/generate_certs/docker-compose.yml up -d
docker-compose -f Docker/scripts/generate_certs/docker-compose.yml exec generate-certs bash

Crie os dispositivos na dojot:

generate_certs dojot create --devices 100

Agora é possível verificar que os dispositivos foram criados na dojot.

_images/img1.png

Fig. 2.1 : Alguns dos dispositivos que o generate_certs criou na dojot.

_images/img2.png

Fig. 2.2 : O template usado pelo generate_certs para criar os dispositivos.

Gere os certificados para eles:

generate_certs cert --dojot

Os certificados são exportados para a pasta cert. Agora o teste pode ser inicializado!

2.2.3. Inicializando os slaves

O Locust master não faz nada por si só. Quem realmente faz todo o trabalho de enviar as requisições é o contêiner do Locust slave. Para inicializá-lo, rode:

docker-compose -f Docker/docker-compose-slave.yml up

Você deve ver no Locust master uma mensagem dizendo que há um slave conectado a ele.

2.2.4. Rodando o teste

Está tudo pronto para inicializar o teste. Para rodá-lo, é preciso acessar a interface do Locust em seu navegador no endereço localhost:8089 (supondo que você está rodando o Locust master no localhost).

Digite 100 em Number of users to simulate, 10 em Hatch rate e clique em Start swarming. Isso dirá ao Locust para rodar 100 clientes, criando 10 deles por segundo.

_images/img3.png

Fig. 2.3 : Configurando o Locust para rodar os clientes.

A configuração padrão dita que cada cliente mande uma mensagem a cada 30 segundos, então você deverá aguardar um pouco para ver as mensagens chegando na dojot.

_images/img4.png

Fig. 2.4 : As estatísticas do Locust após rodar os testes por alguns minutos.

Você pode ir até a dojot e ver as mensagens chegando por lá.

_images/img5.png

Fig. 2.5 : Um dispositivo de exemplo recebendo mensagens.

2.3. Rodando um teste distribuído

Para testes pequenos, o procedimento supracitado deve ser o suficiente, mas se você deseja realmente forçar a dojot, barreiras serão encontradas ao usar somente um slave e/ou uma máquina. Para solucionar este problema, o Locust provê o modo distribuído, permitindo a inicialização de múltiplos slaves em múltiplas máquinas, limitando o desempenho do Locust ao montante de poder de processamento (e orçamento!) que você tem.

Serão utilizadas duas máquinas virtuais rodando 4 slaves (2 em cada VM) e 1 master (em uma das VMs) para criar os 1.000 dispositivos falsos. Vamos nos referir à máquina com o master como primária e à outra como secundária.

Atenção

Não há uma correlação entre os números escolhidos: o número de clientes que cada slave suporta é dependente de diversas variáveis, como o número de núcleos de CPU disponíveis.

Dica

Recomendamos que você rode 1 slave por núcleo da CPU de sua máquina, i.e. se você tem uma VM com 4 CPUs, rode 4 slaves.

2.3.1. Configuração para o modo distribuído

Antes de rodar os testes, há mudanças a serem feitas nos docker compose do Locust. Note que você deve clonar o repositório da dojot em cada máquina em que o Locust rodará.

Dica

Como as configurações podem ser as mesmas para os slaves e para o script generate_certs, você pode os compartilhar entre máquinas usando o sshfs. Assumindo que você esteja na pasta do Locust na máquina secundária, rode o comando:

sshfs -o allow_other -o nonempty <user>@<ip>:/path/to/dojot/connector/mqtt/locust/Docker Docker

Verifique a documentação do sshfs para mais detalhes.

Abra o arquivo Docker/docker-compose-master.yml na máquina primária e mude as seguintes variáveis de ambiente:

# The location of your dojot installation
DOJOT_URL: "http://1.2.3.4"
# Usually it's the dojot address too (if you don't know for sure, keep the same address as dojot)
DOJOT_MQTT_HOST: "1.2.3.4"
# The default MQTTS port
DOJOT_MQTT_PORT: "8883"

Abra o arquivo Docker/docker-compose-slave.yml e mude as seguintes variáveis de ambiente:

# The location of your dojot installation
DOJOT_URL: "http://1.2.3.4"
# Usually it's the dojot address too (if you don't know for sure, keep the same address as dojot)
DOJOT_MQTT_HOST: "1.2.3.4"
# The default MQTTS port
DOJOT_MQTT_PORT: "8883"

# If it's in the same machine as the master, you can leave as it is
LOCUST_MASTER_HOST: "locust-master"

# If it's in the same machine as the master, you can leave as it is
REDIS_HOST: "redis"
# Change to 6380 if the master is in another machine
REDIS_PORT: "6379"

Abra o arquivo Docker/scripts/generate_certs/docker-compose.yml e mude as seguintes variáveis de ambiente:

# The location of your dojot installation
DOJOT_URL: "http://1.2.3.4"

# If it's in the same machine as the master, you can leave as it is
REDIS_HOST: "redis"
# Change to 6380 if the master is in another machine
REDIS_PORT: "6379"

As you can see, the configurations have changed a little bit, with the changes being only about the master and Redis location.

2.3.2. Gerando os certificados

Nesta parte do tutorial, serão criados dispositivos falsos que, ao contrário do teste simples, não aparecerão na GUI da dojot.

Antes de rodar o script, precismos inicializar o Locust master. Dentro da pasta do Locust na máquina primária, rode:

docker-compose -f Docker/docker-compose-master.yml up

After its initialization, initialize the docker compose generate_certs script in the primary machine and enter in it:

docker-compose -f Docker/scripts/generate_certs/docker-compose.yml up -d
docker-compose -f Docker/scripts/generate_certs/docker-compose.yml exec generate-certs bash

Crie os certificados:

generate_certs cert --devices 1000

Nota

Os dispositivos falsos são simulados como certificados.

Agora entre em sua máquina secundária, inicialize o generate_certs e, dentro dele, rode:

generate_certs redis --export

Como os certificados são armazenados no Redis, você pode simplesmente exportá-los com o comando mostrado em qualquer máquina, prevenindo o trabalho tedioso de copiar em cada VM a pasta cert com os certificados.

2.3.3. Inicialização do slave

Rode em suas máquinas primária e secundária:

docker-compose -f Docker/docker-compose-slave.yml up --scale locust-slave=2

Este comando criará dois contêineres do Locust slave em cada máquina. Você deverá notar no Locust master mensagens confirmando a conexão de cada slave.

2.3.4. Rodando o teste distribuído

Está tudo pronto para a realização do teste. Para iniciá-lo, você deve acessar a interface do Locust no seu navegador através do domínio do Locust master, e.g. localhost:8089.

Digite 1000 em Number of users to simulate, 10 em Hatch rate e clique em Start swarming. Isso dirá ao Locust para rodar 1.000 clientes, criando 10 deles por segundo.

_images/img6.png

Fig. 2.6 : Configurando o Locust para rodar os clientes.

_images/img7.png

Fig. 2.7 : As estatísticas do Locust após rodar os testes por alguns minutos.

2.4. Usando o dashboard do Locust no Grafana

The Locust web interface is easy and simple to use, but there are some downsides. The major one is the persistence: The history data will be deleted as soon as you close or refresh the page.

Para resolver este problema, foi adicionada a imagem Locust Exporter no docker compose do Locust master, permitindo a exportação das métricas em um formato compatível com o Prometheus. Desta forma, é possível armazenar estas informações no Prometheus e centralizar todos os dashboards no Grafana. Infelizmente ainda é necessário acessar a interface web do Locust para começar o teste.

Atenção

Como a stack Grafana/Prometheus só está disponível na instalação por meio de Kubernetes, esta seção não é aplicável para a instalação por meio de docker compose. Nós o encorajamos a verificar o Guia de instalação para mais informações sobre os métodos de instalação da dojot.

2.4.1. Configuração do Ansible

Você deve decidir onde o seu Locust master estará de antemão antes de rodar o playbook do Ansible. As configurações do Ansible que você precisa modificar para conectar o Locust Exporter com o Prometheus são:

dojot_enable_locust_exporter: true
dojot_locust_exporter:
  ip: 1.2.3.4

Mude o IP para o do Locust master e rode o playbook. Agora você pode inicializar um teste (distribuído ou não) como mostrado nas seções anteriores e deverá ver os dados do Locust sendo enviados ao dashboard do Locust no Grafana.

_images/img8.png

Fig. 2.8 Estatísticas do Locust no Grafana - antes de começar o teste.

_images/img9.png

Fig. 2.9 Estatísticas do Locust no Grafana - depois da inicialização do teste.

2.5. Requisitos para um teste com 100.000 clientes

Agora que você sabe como rodar testes distribuídos utilizando o Locust, você consegue executar o teste com 100.000 clientes. Para tal, você precisará de bastante poder computacional e múltiplas máquinas, tanto para a dojot como para o Locust, O objectivo é chegar a 100.000 conexões MQTTS simultâneas com taxa de ~3.333 RPS (tanto para publicação quanto para recepção), i.e. uma mensagem a cada 30 segundos para cada cliente conectado.

Como este é somente um caso especial de teste distribuído, cobriremos somente as especificações e algumas dicas para o teste, já que o procedimento para configuração é o mesmo que nós já fizemos.

Nota

Como você já deve saber, este teste só é possível na instalação via Kubernetes da dojot.

2.5.1. Especificações de hardware

Para a plataforma dojot:

Nome da máquina

Serviços presentes

CPU

RAM

dojot-verne-1

VerneMQ, K2V e V2K

8

8GB

dojot-verne-2

VerneMQ, K2V e V2K

8

8GB

dojot-verne-3

VerneMQ, K2V e V2K

8

8GB

dojot-x509

x509 identity manager

4

4GB

dojot-kafka

Kafka e Zookeeper

6

6GB

dojot-dojot

O restante dos serviços

4

4GB

haproxy

Load balancer

4

4GB

Para o Locust, usaremos 5 réplicas da mesma máquina, com 14GB de RAM e 9 CPUs.

2.5.2. Dicas gerais para o teste

  • O Ansible tem a tag 100k para preparar o ambiente para um teste com 100.000 clientes. Isto roda uma versão minificada da dojot, excluindo alguns serviços; tal estratégia foi adotada pois nem todos os serviços da dojot suportam tamanha carga.

  • Ao compartilhar um volume persistente entre pods da EJBCA, é possível escalá-la para aumentar a velocidade de criação de certificados.

  • A criação de certificados pode ser distribuída entre todas as máquinas de Locust. Em nosso exemplo - com 5 máquinas para o Locust - nós conseguimos gerar 20.000 certificados em cada máquina. Isso aumenta substancialmente a velocidade de criação de certificados quando aliado ao aumento de instâncias da EJBCA rodando.

  • Após gerar os certificados, confirme que todas as máquinas estão com todos os certificados. Você pode os exportar rodando o comando generate_certs redis --export dentro do contêiner do generate_certs.

  • Para verificar o número de certificados, rode:

    ls cert | wc -l
    

    O valor retornado deve ser 200.003. Este número inclui a chave e o certificado de cada dispositivo, o certificado da CA e as pastas renew e revoke.

  • É altamente recomendado rodar um slave por núcleo, totalizando 45 slaves neste exemplo.

  • Como a interface web do Locust não persiste nenhum dado, use o dashboard do Locust no Grafana para monitorar o seu teste. Verifique a seção anterior para mais informações sobre como configurar o Locust Exporter.

  • Você também pode rodar o teste com revoke e renew. Verifique o README do repositório para mais detalhes de configuração.