5.6 KiB
Migrare RabbitMQ: staging-dataLayer-rabbitmq local → cluster HA 10.11.50.100
Autor: refactor 2026-04-22 (după Redis migration)
Scop: mutarea cozilor async (cele 31 de cozi analysis.*) de pe containerul RabbitMQ local pe clusterul HA managed cu vhost dedicat /didi.
Stare actuală (post-cutover)
- Codul RabbitMQ era deja centralizat în 3 fișiere:
src/queue/connection.ts— manager singleton conexiune + channelssrc/shared/queue/constants.ts—getRabbitMQConfig()+getRabbitMQUrl()src/scripts/init-priority-queues.ts— script standalone
- Zero refactor pe cod aplicație. Un singur punct de schimbat.
- URL-encoding corect pentru vhost
/didiadăugat îngetRabbitMQUrl()(foloseșteencodeURIComponentpentru user/pass/vhost). CONNECTION_RETRY_DELAYtuned de la 5s la 2s pentru failover HA mai rapid.- Logging îmbunătățit: arată host+vhost+user la conectare/eroare/close.
Target
| Parametru | Valoare |
|---|---|
| AMQP | 10.11.50.100:16672 |
| Management UI | http://10.11.50.100:16673 |
| Username | didi |
| Password | $CLUSTER_PASSWORD |
| Vhost dedicat | /didi (izolat de alte proiecte) |
| URI encoded | amqp://didi:...@10.11.50.100:16672/%2Fdidi |
| Cluster HA | 3 noduri rag01/02/03 + HAProxy VIP |
Diferență critică față de Redis
Nu a fost nevoie de migrare de date. Cozile RabbitMQ sunt efemere — topologia (exchange + 31 queues) se creează automat de workeri la assertExchange() / assertQueue() pe prima conectare. Mesajele în zbor la cutover se pierd (erau 0 la momentul migrării).
Pași executați la cutover
1. Refactor cod (minim)
src/queue/connection.ts:- Retry: 5s → 2s
- Logging:
[RabbitMQ] Connecting to HOST:PORT/VHOST (user: USER)... - Error messages: includ host+vhost pentru debug
- Add
blocked/unblockedhandlers (broker flow control)
src/shared/queue/constants.ts:getRabbitMQUrl()foloseșteencodeURIComponent()pentru user/pass/vhost- Fix critical: vhost
/didiacum devine%2Fdidiîn URL (fără asta, amqplib parsa ca vhostdidifără slash)
2. docker-compose (agent-v3)
x-worker-env schimbate din hardcoded la fallbacks:
RABBITMQ_HOST: ${RABBITMQ_HOST:-staging-dataLayer-rabbitmq}
RABBITMQ_PORT: ${RABBITMQ_PORT:-5672}
RABBITMQ_USER: ${RABBITMQ_USER:-admin}
RABBITMQ_PASS: ${RABBITMQ_PASS:-rabbitmq123}
RABBITMQ_VHOST: ${RABBITMQ_VHOST:-/}
3. .env agent-v3
Adăugat bloc:
RABBITMQ_HOST=10.11.50.100
RABBITMQ_PORT=16672
RABBITMQ_USER=didi
RABBITMQ_PASS=$CLUSTER_PASSWORD
RABBITMQ_VHOST=/didi
4. Rebuild + restart
docker compose build(toate 8 imagini, cache fast)docker compose up -d --force-recreatepe agent-v3 stack- Workerii s-au conectat în < 1s și au creat automat toate 31 cozile
5. Verificare
- 31/31 cozi prezente pe
/didicu consumerii corespunzători (claims×3, rest×2) - 14 conexiuni active de la workeri prin HAProxy VIP
- Smoke test: analiză async plan 4 = pro, status
completedîn 3.9s, risk MOSTLY_RELIABLE (22)
Script de verificare: scripts/verify-rabbitmq-cluster.ts
Mirror al verify-redis-cluster.ts. Rulează cu:
RABBITMQ_HOST=10.11.50.100 RABBITMQ_PORT=16672 \
RABBITMQ_USER=didi RABBITMQ_PASS='...' RABBITMQ_VHOST=/didi \
node_modules/.bin/ts-node --transpile-only scripts/verify-rabbitmq-cluster.ts
Verifică:
- Conectivitate + auth pe vhost
- Channel creation
- Assert exchange
analysis(topic, durable) - Write privilege (creează + șterge coadă temporară)
- Topologie expected (31 cozi) — WARN dacă workerii nu au rulat încă
Exit codes: 0 = OK sau WARN (topology lipsă pre-cutover), 1 = FATAL.
Fallback LOCAL păstrat
Containerul staging-dataLayer-rabbitmq e oprit dar nu șters — rollback rapid prin script.
Switch rapid: services/orchestration-layer/scripts/redis-switch.sh
Scriptul acoperă ACUM ambele servicii (Redis + RabbitMQ):
# Arată status curent
./redis-switch.sh status
# Switch ambele (Redis + Rabbit) la cluster
./redis-switch.sh cluster
# Switch ambele la local
./redis-switch.sh local
# Doar unul:
./redis-switch.sh cluster redis # Redis → cluster, Rabbit neschimbat
./redis-switch.sh local rabbit # Rabbit → local, Redis neschimbat
Script-ul:
- Pornește containerul local dacă e oprit (
docker startsaudocker compose up -d) - Rescrie blocul corespunzător în
.env(fără să atingă celelalte) - Restart
didi-framework+agent-v3stack
Rollback în 30s
./redis-switch.sh local rabbit # doar RabbitMQ înapoi la local
Cleanup DEFINITIV (după 30+ zile stabil)
-
Stop + remove container local:
docker stop staging-dataLayer-rabbitmq # deja oprit docker rm staging-dataLayer-rabbitmq docker volume rm didi-staging-rabbitmq-data -
Șterge secțiunea din
data-layer/docker-compose.yml -
Update
didiQueue/INDEX.mdmarcat ca deprecated -
Admin dashboard nginx — șterge
/health-check/rabbitmq(pointa la container local)
Riscuri cunoscute / TODO
- amqplib nu are Sentinel/discovery nativ — la failover cluster, ioredis-style "învață" singur noul master. amqplib doar se deconectează și se reconectează la VIP (care rutează la noul master). Downtime client: 5-15s acceptabil.
- init-priority-queues.ts — neinvestigat în detaliu dacă mai e rulat. Cozile se creează oricum prin workeri.
- Monitoring: management UI-ul e pe
10.11.50.100:16673— accesibil doar din LAN. Admin dashboard nu-l embedă direct; user poate deschide browser separat.