Pular para o conteúdo principal

Relatório de Infraestrutura — 07/01/2026

Resumo Executivo

Sessão de otimização de performance e estabilização do sistema ArboreoLab, focada no motor de busca vetorial (motor-rag) e infraestrutura Node.js/MariaDB.

Duração: ~3 horas
Participantes: Engenheiro Sênior, Técnico Sênior, Diretor
Status Final: ✅ Sistema estável e otimizado


Problemas Identificados e Resolvidos

1. Pool Exhausted no motor-rag (CRÍTICO)

Sintoma: Erros 500 intermitentes com mensagem "Failed getting connection; pool exhausted"
Causa: Pool de conexões por tenant limitado a 3 conexões, insuficiente sob concorrência
Solução:

  • Aumentado pool para 8 conexões/tenant via FREGERAG_TENANT_POOL_SIZE
  • Adicionado retry com wait (2s) antes de falhar por pool esgotado
  • Alterado response de 500 para 503 (backpressure) quando pool saturado

Arquivos modificados:

  • estudos/1_funcionais/fregeRAG_v1/motorRag/services/tenant_manager.py
  • estudos/1_funcionais/fregeRAG_v1/motorRag/services/tenant_search_engine.py
  • estudos/1_funcionais/fregeRAG_v1/motorRag/server/routes/search.py

2. PM2 não aplicando cluster mode (ALTO)

Sintoma: Node backend rodando com 1 worker mesmo com instances: 'max'
Causa: pm2 restart não relê configurações de fork→cluster; env vars não propagadas
Solução:

  • Usar pm2 delete + pm2 start ecosystem.config.js para forçar releitura
  • Documentar comportamento do PM2 para futuras manutenções

Arquivo modificado:

  • Clio/node/ecosystem.config.js — cluster mode + env vars FREGERAG_*

3. motor-rag usando uvicorn com flags de gunicorn (ALTO)

Sintoma: Erro "No such option: -w" no startup do motor-rag
Causa: PM2 config apontava para uvicorn mas passava args de gunicorn
Solução:

  • Alterado script para usar gunicorn explicitamente
  • Args: -w 4 -k uvicorn.workers.UvicornWorker -b 127.0.0.1:8768

4. Disk I/O alto durante buscas vetoriais (MÉDIO)

Sintoma: Latência de 20-38s por busca; gráficos mostrando 400-600 MiB/s de I/O
Causa: Buffer pool do MariaDB muito pequeno (default ~128MB); vetores lidos do disco
Solução:

  • Criado script update_performance_mariadb.sh
  • Buffer pool aumentado para 18GB (60% de 31GB RAM)
  • Configurações de I/O otimizadas para SSD

Arquivos criados:

  • Clio/update_performance_mariadb.sh

Arquivo modificado:

  • /etc/mysql/mariadb.conf.d/50-server.cnf

5. Access Denied após restart do MariaDB (ALTO)

Sintoma: Frontend retornando 500 em todas as rotas de API
Causa: Usuário MySQL existia apenas para localhost; com skip-name-resolve=1, conexões TCP vêm como 127.0.0.1
Solução:

  • Criado usuário arboreolab_38g57g0kO0dh@127.0.0.1 com mesmos grants

Métricas de Performance

Antes vs Depois

MétricaAntesDepoisMelhoria
Node workers1 (fork)8 (cluster)+700% capacidade
motor-rag workers1 (uvicorn)4 (gunicorn)+300% capacidade
DB Buffer Pool~128 MB18 GB+140x cache
Pool/tenant3 conexões8 conexões+166%
Pool exhaustedFrequenteEliminado
ConcorrênciaTotal Timep50p90RPSSucesso
1233s (10 req)22.9s29.1s0.04100%
2154s (10 req)27.5s38.4s0.06100%

Nota: A latência alta (20-38s) é limitante do MariaDB (busca vetorial em 145k entidades). Buffer pool de 18GB deve melhorar após "aquecer" o cache.


Arquitetura Atual

┌─────────────────────────────────────────────────────────────────┐
│ PRODUÇÃO │
├─────────────────────────────────────────────────────────────────┤
│ Node.js (PM2 Cluster) │ motor-rag (Gunicorn) │
│ ├── 8 workers │ ├── 4 workers │
│ ├── Port 3000 │ ├── Port 8768 │
│ └── Rotas leves: ~3ms │ └── /search: 20-38s │
├─────────────────────────────────────────────────────────────────┤
│ MariaDB 11.8.5 │
│ ├── Buffer Pool: 18 GB │
│ ├── 145.478 entidades vetorizadas │
│ ├── 13.969 segmentos de documentos │
│ └── Pool: 8 conexões/tenant │
└─────────────────────────────────────────────────────────────────┘

🆕 Atualização: Embeddings Worker (08/01/2026)

Novo Nó de Processamento: MacBook Air M2

Adicionado worker remoto para geração de embeddings vetoriais usando aceleração Apple Silicon (MPS).

┌─────────────────────────────────────────────────────────────────┐
│ NOVA ARQUITETURA │
├─────────────────────────────────────────────────────────────────┤
│ Servidor (srv1.arboreolab.com.br) │
│ ├── Node.js (PM2 Cluster) - 8 workers - Port 3000 │
│ ├── motor-rag (Gunicorn) - 4 workers - Port 8768 │
│ └── SSH Tunnel Listener - Port 9002 (→ Mac:9999) │
├─────────────────────────────────────────────────────────────────┤
│ MacBook Air M2 (Worker Remoto via SSH Tunnel) │
│ ├── Embeddings Worker (Flask) - Port 9999 │
│ ├── Modelo: paraphrase-multilingual-mpnet-base-v2 │
│ ├── Aceleração: MPS (Metal Performance Shaders) │
│ └── SSH Forward: localhost:3306 → Server:3306 (MariaDB) │
├─────────────────────────────────────────────────────────────────┤
│ MariaDB 11.8.5 (compartilhado via túnel) │
│ ├── Buffer Pool: 18 GB │
│ ├── Novas colunas VECTOR(768) em clio_entidades_vector │
│ └── Usuário: embeddings_worker (SELECT/UPDATE em *Vector) │
└─────────────────────────────────────────────────────────────────┘

Teste de Validação (08/01/2026 14:47 UTC)

MétricaValor
DatabaseGeopoliticasVector
Records processados32
Tempo total~15 segundos
Taxa3.2 records/segundo
DeviceMPS (Apple Silicon)

Arquivos Criados

ArquivoDescrição
embeddings-worker-interface/api_server.pyFlask API multi-tenant
embeddings-worker-interface/ssh_tunnel.shTúnel duplo (API + MariaDB)
embeddings-worker-interface/install_mac.shInstalador automatizado

Documentação completa: RELATORIO_EMBEDDINGS_WORKER_2026-01-08.md


Warnings Pendentes (Baixa Prioridade)

MariaDB 11.8 removeu algumas opções que ainda estão no config:

  • innodb_buffer_pool_instances — gerenciado automaticamente
  • innodb_thread_concurrency — gerenciado automaticamente

Impacto: Apenas warnings no log, sem efeito funcional.


Próximos Passos Recomendados

PrioridadeAçãoImpacto Esperado
MédiaCriar índice vetorial no MariaDBReduzir latência de 25s → ~5s
BaixaRemover opções depreciadas do MariaDB 11.8Limpeza de logs
BaixaImplementar cache Redis para queries frequentesEvitar reprocessamento

Lições Aprendidas

  1. PM2 restart vs delete/start: pm2 restart --update-env nem sempre aplica mudanças de fork→cluster. Usar pm2 delete + pm2 start é mais confiável.

  2. skip-name-resolve: Ao habilitar no MariaDB, criar usuários tanto para localhost quanto para 127.0.0.1.

  3. Validação de config MariaDB: Não usar grep "error" no output de --help — palavras como --log-error causam falso positivo.

  4. Pool sizing: Com Gunicorn (4 workers) + queries paralelas (entidades + documentos), cada request pode usar 2+ conexões. Pool de 3 era insuficiente.

  5. Benchmark com ab: Usar -s para timeout alto em endpoints lentos; "Failed requests: Length" não é erro real, é variação no tamanho do response.


Arquivos Modificados/Criados

ArquivoAçãoDescrição
Clio/node/ecosystem.config.jsModificadoCluster mode, Gunicorn, env vars
estudos/.../tenant_manager.pyModificadoPool size configurável
estudos/.../tenant_search_engine.pyModificadoRetry com wait no pool
estudos/.../routes/search.pyModificado503 para pool exhausted
Clio/update_performance_mariadb.shCriadoScript de tuning MariaDB
/etc/mysql/.../50-server.cnfModificadoBuffer pool 18GB

Relatório gerado por: Engenheiro Sênior ArboreoLab
Data: 07/01/2026 23:30 UTC