Skip to content

Vận hành

1. Triển khai

Thuộc tínhGiá trị
Imageregistry/nx-seller-payment:<tag>
Container Port3000
External Port31040
Mode mặc địnhFULL (snowflake 4)
Mode productionAPI (snowflake 8) + N× WORKER (snowflake 91+i)
Replicas (FULL)1 (chỉ dev)
Replicas (API)1+ (scale theo lưu lượng)
Replicas (WORKER)1+ (scale theo độ sâu queue)
Resources (req/lim)200m / 1 CPU, 512Mi / 1Gi memory
Live probeGET /v1/api/payment/healthz
Ready probeGET /v1/api/payment/readyz
Migrationchạy như Job riêng trước khi rollout (RUN_MODE=migrate)

Label routing Traefik

yaml
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.payment.rule=PathPrefix(`/v1/api/payment`)"
  - "traefik.http.services.payment.loadbalancer.server.port=3000"

Pod WORKER không expose REST — không cần label Traefik.

Hạ tầng yêu cầu

Phụ thuộcLý do
PostgreSQLbảng Configuration, WebhookConfig, MQ-Pay
RedisBullMQ cho queue scheduler + confirmation; WS emitter
@nx/identity reachablexác minh JWKS
VN Pay reachabletích hợp nhà cung cấp
Webhook subscriber reachableít nhất sale phải chấp nhận phân phối webhook

2. Observability

Tín hiệuNguồnTìm ở đâu
Logsstdoutkubectl logs deploy/payment-{api,worker}
Health/healthz, /readyzGateway portal
OpenAPI live specGET /v1/api/payment/doc/openapi.jsonGateway portal
Độ sâu queue BullMQRedisbull-board / Burrow
Lỗi dispatch webhooklogsgrep WebhookDispatcherService

Trường log quan trọng

TrườngNguồnGhi chú
modeenv APP_ENV_MQ_PAY_MODElog khi boot
transactionId / attemptIdper-eventtrace vòng đời theo từng thanh toán
webhookConfigIdlog dispatchsubscriber nào đã nhận
paymentProviderevent payloadVNPAY_QR_MMS / v.v.

3. Bảo mật

Mối quan tâmGiải pháp
Rò rỉ credential nhà cung cấpLưu mã hóa AES-256-GCM trong Configuration.credential; cột ẩn khỏi CRUD; key từ K8s secret
Tính nhất quán khóa mã hóaAPP_ENV_APPLICATION_SECRET PHẢI giống nhau trên tất cả các pod (API + WORKER)
Giả mạo IPNChữ ký nhà cung cấp được xác minh trong @nx/mq-pay PaymentVerificationService
Tampering webhookWebhookConfig.signingMethod (HMAC_SHA256) — subscriber xác minh HMAC của timestamp + eventType + body
AuthNJWT (xác minh cục bộ)
AuthZCasbin qua PolicyDefinition
Network policyCilium — cho phép gateway + sale + identity + Redis + Postgres + VN Pay (egress)
Xoay vòng secretXoay vòng APP_ENV_APPLICATION_SECRET yêu cầu mã hóa lại tất cả row Configuration.credential (quy trình thủ công)

4. Runbook

4.1 Các loại cảnh báo

Cảnh báoKích hoạtKiểm traKhắc phụcEscalate
PaymentHighErrorRate5xx >5% trong 5mlogs, xác định endpointrollback nếu mới deployon-call backend
PaymentQueueLagBullMQ pending >1000Redis bull-boardscale replica WORKERon-call SRE
PaymentWorkerStarvationPod WORKER 0 active job nhưng queue có việckiểm tra snowflake ID duy nhất (xung đột = không có job)sửa APP_ENV_NODE_ID cho từng workeron-call SRE
PaymentWebhookDispatchFailuresTỷ lệ lỗi phân phối webhook >10%logs WebhookDispatcherServicekiểm tra sức khỏe subscriber (sale, v.v.)on-call backend
PaymentProviderUnreachableVN Pay 5xxlogs + provider status pageđợi nhà cung cấp; chuyển sang phương án thay thế nếu được cấu hìnhon-call backend
PaymentEncryptionMismatchspike log "decrypt failed"kiểm tra tính nhất quán APP_ENV_APPLICATION_SECRET giữa các podredeploy với secret nhất quánon-call SRE — HIGH

4.2 Thao tác phổ biến

Thao tácLệnh
Tail log APIkubectl logs -n <ns> -f deploy/payment-api
Tail log workerkubectl logs -n <ns> -f deploy/payment-worker
Chạy migrationskubectl run payment-migrate --image=...:tag --env="RUN_MODE=migrate" --rm --restart=Never
Liệt kê webhook đã đăng kýSELECT id, name, url, event_types, status FROM "WebhookConfig" WHERE deleted_at IS NULL;
Replay transaction bị kẹtQua admin UI MQ-Pay hoặc DB: UPDATE Transaction SET status = 'NEW' WHERE id = '...' (cần phê duyệt cấp cao)
Kiểm tra config đã mã hóaSELECT id, code, principal_type, principal_id, environment FROM "Configuration" WHERE group = 'INTEGRATION'; (không select credential)

4.3 Kịch bản khôi phục

Kịch bảnKhôi phục
Pod WORKER crash giữa jobBullMQ phân phối lại; idempotent ở lớp MQ-Pay
Pod API crash khi tạo transactionSale nhận 5xx; sale retry create — MQ-Pay dedupe theo transaction reference của sale
Webhook subscriber downWebhookDispatcherService retry theo WebhookConfig.metadata.maxRetries; cuối cùng fail. Công cụ replay thủ công lấy trạng thái transaction và dispatch lại
Xoay vòng secret mã hóa saiWorker không thể giải mã credential nhà cung cấp → mọi transaction fail. Roll back env change ngay.
Xung đột Snowflake ID (hai pod WORKER cùng NODE_ID)Trùng primary key trong bảng MQ-Pay → INSERT lỗi. Xác minh mỗi worker có APP_ENV_NODE_ID duy nhất (91, 92, …)

5. Runbook Cross-Service

6. Trang liên quan

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.