Skip to content

Operations

1. Triển khai

Thuộc tínhGiá trị
Base imagedebian:12-slim (binary Bun standalone)
Containervd dev-nx-signal
Internal port3000 (ngoài 31090)
Networknx-network (external, dùng chung)
Replicasscale ngang được (state ở Redis + DB, không phải pod)
Snowflake ID9
Migration modeseed run-on-boot (alwaysRun) — chỉ permissions + role-permissions
HealthGET /v1/api/signal/health (public, từ VerifierApplication)

Volumes

Host PathContainer PathMục đích
packages/signal/dist/bin/app/binBinary đã compile (bun run rebuild)
packages/signal/resources/app/resourcesBanner, HTML test client
infrastructure/deployments/develop/signal/start.sh/app/start.shScript khởi động

Traefik — dual routing

Signal expose hai router chia sẻ một backend (port 3000):

RouterRuleMiddlewareVì sao
signal-restPathPrefix(/v1/api/signal)rate-limit, circuit-breaker, security-headersBảo vệ chuẩn cho request HTTP ngắn ngủi
signal-wsPathPrefix(/stream)noneKết nối WS bền vỡ dưới rate-limiting / circuit-breaking theo request
yaml
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.signal-rest.rule=PathPrefix(`/v1/api/signal`)"
  - "traefik.http.routers.signal-rest.middlewares=rate-limit@file,circuit-breaker@file,security-headers@file"
  - "traefik.http.routers.signal-ws.rule=PathPrefix(`/stream`)"
  - "traefik.http.services.signal.loadbalancer.server.port=3000"

Router WS riêng (không middleware) là bất biến triển khai then chốt. Xem ADR-0003ADR-0001.

Bus Redis

WebSocketServerHelper của Signal và WebSocketEmitter của mỗi publisher phải trỏ tới cùng instance/cluster Redis (APP_ENV_WEBSOCKET_REDIS_*):

ServiceComponentVai trò
SignalWebSocketServerHelpersubscribe + publish (server đầy đủ)
Sale / PaymentWebSocketEmitterchỉ publish

Fan-out đa instance

Kịch bảnHành vi
Deliver cục bộClient đích trên instance này → deliver trực tiếp (không round-trip Redis)
Deliver từ xaĐích trên instance khác → publish tới Redis, instance sở hữu deliver
Broadcast / roomPublish tới Redis; mỗi instance deliver tới client khớp cục bộ của nó

2. Observability

Tín hiệuNguồnXem ở đâu
Logsstdout (key-value có cấu trúc)kubectl logs / Loki
HealthGET /v1/api/signal/healthPortal gateway / Traefik check (30s)
OpenAPIGET /v1/api/signal/doc, /explorerScalar UI
Tracesnone (no-op)

Dòng log chính

Khu vựcCho bạn biết gì
Kafka consumertopic / partition / offset mỗi message; broker connect/disconnect
Push notificationtopic / room / recipientId mỗi WS emit; warn khi emitter chưa sẵn
Handshakewarn khi thiếu/sai public key hoặc loại auth không hỗ trợ

3. Bảo mật

Mối quan tâmGiảm thiểu
AuthN (REST)JWT + Basic, xác minh qua JWKS từ xa
AuthN (WS)JWT type=Bearer xác minh bởi JWKSVerifierTokenService lúc handshake
AuthZPermission WebSocketClient.* trên route quản lý client; /notifications scope theo subject JWT
Mã hoá E2EBắt buộc ECDH P-256 + AES-256-GCM trên /stream (requireEncryption: true); khoá ephemeral theo từng client (forward secrecy), xoá khi disconnect
Ngoại lệ plaintextchỉ sự kiện connectederror
TLSwss:// kết thúc tại Traefik trong production
Endpoint public/health, /doc, /openapi.json, /explorer, và GET /socket/websocket/clients/status
Room ACLhiện passthrough (chấp nhận mọi room) — ACL phạm vi merchant là TODO đã biết
Networkinternal port 3000 không expose host; truy cập chỉ qua Traefik

4. Runbook

4.1 Lớp cảnh báo

Cảnh báoKích hoạtKiểm traKhắc phụcLeo thang
signalConsumerStalledoffset không tiến trên signal.activity-notificationlogs consumer / lagrestart pod; xác minh brokers + SASLbackend on-call
signalWsEmitterNotReadywarn "WebSocket emitter not ready" lặp lạikết nối Rediskiểm APP_ENV_WEBSOCKET_REDIS_*, sức khoẻ RedisSRE on-call
signalHandshakeRejectstăng vọt handshake bị từ chốikhả năng tới JWKS identity, lệch clockxác minh URL identity + parity APP_ENV_WEBSOCKET_ECDH_INFObackend on-call
signalDuplicateNotificationshàng trùng sau redeliverylogs offset/commit consumerquery de-dup; giảm thiểu (không dedup built-in — xem ADR-0002)backend on-call

4.2 Thao tác thường gặp

Thao tácLệnh
Tail logskubectl logs -n <ns> -f deploy/signal
Kiểm sẵn sàng WScurl /v1/api/signal/socket/websocket/clients/status
Xem client đã kết nốiGET /socket/websocket/clients (JWT + permission)
Replay notificationre-publish tới signal.activity-notification (lưu ý: tạo hàng trùng)
Reseed permissionchạy migration signal (idempotent) — chỉ operator chạy

5. Trang liên quan

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