Go microservices cho nền tảng đặt sân bóng. Repo này hoạt động song song với NestJS backend — giao tiếp hoàn toàn qua Kafka và chia sẻ PostgreSQL/Redis trên cùng Docker network. Không có HTTP call nào giữa Go và NestJS.
Tại sao cần Go services?
| Vấn đề |
Giải pháp |
| PDF/QR generation tốn CPU, block NestJS event loop |
Go worker pool xử lý bất đồng bộ qua Kafka |
| 10.000+ WebSocket connections đồng thời quá nặng với NestJS |
Go goroutine-per-connection ~1KB RAM mỗi conn |
| VNPay IPN cần respond < 50ms, không thể chờ NestJS xử lý |
Go verify HMAC-MD5 ~0.1ms, respond 200 OK ngay |
| ClickHouse batch insert từ nhiều Kafka topics |
Go channel + ticker = native batching, không cần framework |
Kiến trúc tổng quan
football-booking-network (Docker)
┌─────────────────────────────────────────────────────────────────┐
│ │
│ NestJS payment-service ──── payment.completed ─────────────┐ │
│ NestJS field-service ──── report.requested ──────────┐ │ │
│ ▼ ▼ │
│ [Go] document-worker │
│ PDF + QR → MinIO │
│ └── document.ready → notification-service
│ │
│ NestJS booking-service ─── booking.* ──────────────────────┐ │
│ ▼ │
│ [Go] availability-engine │
│ WebSocket hub :3011 │
│ ← api-gateway proxies WS │
│ │
│ Tất cả domain events ──────────────────────────────────────┐ │
│ ▼ │
│ [Go] analytics-pipeline │
│ batch insert → ClickHouse │
│ │
│ VNPay/Stripe → Nginx → :3013 │
│ ▼ │
│ [Go] webhook-receiver │
│ verify sig → 200 OK → Kafka │
│ │
└─────────────────────────────────────────────────────────────────┘
Nguyên tắc bất biến: Go services không bao giờ gọi HTTP endpoint của NestJS. Chỉ giao tiếp qua Kafka produce. Chỉ availability-engine được đọc trực tiếp PostgreSQL (booking_db, read-only).
4 Services
| Service |
Port |
Nhiệm vụ |
document-worker |
3010 |
Consume payment.completed → generate PDF receipt + QR → upload MinIO → emit document.ready |
availability-engine |
3011 |
WebSocket hub realtime slot update; consume booking.* → invalidate Redis cache → broadcast |
analytics-pipeline |
3012 |
Consume tất cả domain events → batch insert ClickHouse (500 rows hoặc 500ms) |
webhook-receiver |
3013 |
Receive VNPay/Stripe IPN, verify HMAC signature → respond 200 OK → emit Kafka event |
Cấu trúc thư mục
football-booking-go-services/
├── cmd/ ← entry points — một binary mỗi service
│ ├── document-worker/
│ │ ├── main.go
│ │ └── Dockerfile
│ ├── availability-engine/
│ │ ├── main.go
│ │ └── Dockerfile
│ ├── analytics-pipeline/
│ │ ├── main.go
│ │ └── Dockerfile
│ └── webhook-receiver/
│ ├── main.go
│ └── Dockerfile
│
├── internal/ ← business logic riêng của từng bucket
│ ├── document/ ← Bucket 1: CPU-bound file generation
│ │ ├── consumer/ ← subscribe Kafka topics
│ │ ├── generator/ ← pdf.go, excel.go, qr.go
│ │ ├── storage/ ← minio.go
│ │ ├── publisher/ ← emit document.ready
│ │ └── config/
│ ├── availability/ ← Bucket 2: WebSocket + Redis cache
│ │ ├── hub/ ← hub.go (rooms map), client.go (goroutines)
│ │ ├── consumer/ ← booking events → invalidate cache + broadcast
│ │ ├── checker/ ← overlap logic + pgx query
│ │ ├── cache/ ← Redis "avail:{fieldId}:{date}" TTL 60s
│ │ ├── handler/ ← ws.go: GET /ws?fieldId=xxx
│ │ └── config/
│ ├── analytics/ ← Bucket 3: Kafka → ClickHouse
│ │ ├── consumer/ ← domain events consumer group
│ │ ├── transformer/ ← payload → ClickHouse row structs
│ │ ├── writer/ ← batch writer (channel + ticker)
│ │ ├── schema/ ← CREATE TABLE IF NOT EXISTS (idempotent)
│ │ └── config/
│ └── webhook/ ← Bucket 4: IPN receiver
│ ├── handler/ ← vnpay.go, stripe.go HTTP handlers
│ ├── verifier/ ← HMAC-MD5 (VNPay), HMAC-SHA256 (Stripe)
│ ├── publisher/ ← emit webhook.*.received
│ └── config/
│
├── pkg/ ← shared packages dùng chung tất cả services
│ ├── events/ ← Kafka topics + payload structs (mirror NestJS)
│ ├── kafka/ ← consumer group, sync producer, W3C traceparent
│ ├── redis/ ← go-redis/v9 client
│ ├── postgres/ ← pgx/v5 pool
│ ├── otel/ ← OTLP gRPC → SigNoz
│ └── health/ ← GET /health → 200 OK + uptime
│
├── deployments/
│ ├── docker-compose.yml ← local dev (build from source, join shared infra network)
│ └── .env.example
│
├── scripts/
│ ├── build-and-push.sh ← build 4 images (ad-hoc/manual push)
│ └── migrate-clickhouse.sh ← chạy schema init thủ công
│
├── .github/workflows/
│ ├── ci.yml ← lint + test + build (on PR)
│ └── cd.yml ← build → push GHCR → update football-booking-gitops (ArgoCD sync)
│
├── go.mod ← single module: github.com/sangtrandev00/football-booking-go
├── Makefile
└── .golangci.yml
Dependencies chính
| Package |
Version |
Dùng cho |
github.com/IBM/sarama |
v1.43.3 |
Kafka consumer group + sync producer |
github.com/gorilla/websocket |
v1.5.3 |
WebSocket server (availability-engine) |
github.com/go-pdf/fpdf/v2 |
v2.7.0 |
PDF receipt generation |
github.com/xuri/excelize/v2 |
v2.8.1 |
Excel report generation |
github.com/skip2/go-qrcode |
latest |
QR code PNG embedded trong PDF |
github.com/minio/minio-go/v7 |
v7.0.77 |
Upload PDF/Excel lên MinIO |
github.com/ClickHouse/clickhouse-go/v2 |
v2.29.0 |
Native ClickHouse driver |
github.com/redis/go-redis/v9 |
v9.7.0 |
Redis cache (availability) |
github.com/jackc/pgx/v5 |
v5.7.1 |
PostgreSQL read (booking_db) |
github.com/stripe/stripe-go/v81 |
v81.0.0 |
Stripe webhook signature verify |
github.com/spf13/viper |
v1.19.0 |
Config từ env vars |
go.opentelemetry.io/otel |
v1.31.0 |
Distributed tracing → SigNoz |
Kafka Topics (mirror từ NestJS)
File pkg/events/topics.go phải luôn đồng bộ với libs/shared/src/constants/kafka-topics.ts trong NestJS repo.
NestJS phát → Go consume
─────────────────────────────────────────
booking.created → availability-engine, analytics-pipeline
booking.confirmed → availability-engine
booking.cancelled → availability-engine
booking.expired → availability-engine
payment.completed → document-worker, analytics-pipeline
report.requested → document-worker
field.created → analytics-pipeline
Go phát → NestJS consume
─────────────────────────────────────────
document.ready → notification-service
webhook.vnpay.received → payment-service
webhook.stripe.received→ payment-service
Observability
- Tracing: OTLP gRPC →
otel-collector:4317 → SigNoz (cùng collector với NestJS)
- W3C traceparent được inject/extract qua Kafka message headers → cross-service trace NestJS ↔ Go hiển thị trong SigNoz
- Health check:
GET /health trả về {"status":"ok","uptime":"..."} trên port của mỗi service
- Logs:
log/slog structured JSON — tương thích với ELK/Loki
| Repo |
Mô tả |
football-booking-backend-boilerplate |
NestJS microservices (api-gateway, booking, payment, field, user, notification) |
football-booking-chatbot-service |
Python FastAPI chatbot với RAG (Pinecone + Groq) |
football-booking-infra-k3s |
Ansible + Helm + k3s infra cho Oracle VM |
football-booking-go-services |
← repo này |