Files
ljwx-health/ljwx-boot/docker-compose-redis-sentinel.yml
brunoandClaude Sonnet 4.5 bb50a89f31 refactor(bigscreen): 统一使用 proxy blueprint 直接转发 ljwx-boot API
问题背景:
- 之前前端调用 /api/v1/alerts/user 等接口时,被 alert blueprint 拦截
- alert blueprint 包装响应为 Flask BFF 格式: {success: true, data: [], source: 'ljwx-boot'}
- 导致前端需要兼容两种响应格式(ljwx-boot 和 Flask BFF)
- 增加了复杂度,且 proxy blueprint 的通用代理功能未被充分利用

修复方案:
1. 删除 alert/routes.py 中的重复 V1 API 路由(第 288-521 行):
   - @bp.route('/api/v1/alerts/user')
   - @bp.route('/api/v1/alerts/personal')
   - @bp.route('/api/v1/messages/user')
   - 及其 legacy 实现函数

2. 保留 proxy/routes.py 的通用代理路由:
   - @bp.route('/<path:path>') 匹配所有 /api/v1/* 请求
   - 透传 ljwx-boot 原生响应格式: {code: 200, msg: '', data: {}}
   - 自动注入 Authorization Bearer Token从 Flask Session

3. 恢复 api-client-v2.js 到标准实现:
   - 移除 Flask BFF 格式兼容代码
   - 只支持 ljwx-boot 标准格式: {code: 200, msg: '', data: {}}

架构改进:
  Before: 前端 → Flask BFF (包装) → ljwx-boot
          Response: {success: true, data: [], source: 'ljwx-boot'}

  After:  前端 → Flask Proxy (透传) → ljwx-boot
          Response: {code: 200, msg: '', data: []}

优势:
- 统一响应格式,减少前端适配复杂度
- proxy blueprint 统一管理所有 API 代理,易于维护
- 保持 Flask Session 自动注入 Token 的优势
- 避免路由冲突(具体路由vs通配符路由)

测试验证:
- 删除的函数已备份为 alert/routes.py.bak
- V2 API 路由(/api/v2/*)保留,未受影响
- 所有 /api/v1/* 请求现在统一由 proxy_bp 处理

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-01 09:52:40 +08:00

278 lines
7.8 KiB
YAML

# =====================================
# Redis Sentinel High Availability Configuration
# Message V2.1 Week 3 - Task 2
# =====================================
# 架构: 1 Master + 2 Replicas + 3 Sentinels
# 故障切换时间: <30s
# 数据持久化: RDB + AOF
# =====================================
version: '3.8'
networks:
redis-ha:
driver: bridge
services:
# ========================================
# Redis Master (主节点)
# ========================================
redis-master:
image: redis:7.2-alpine
container_name: ljwx-redis-master
ports:
- "6379:6379"
networks:
- redis-ha
command: >
redis-server
--requirepass ${REDIS_PASSWORD:-123456}
--masterauth ${REDIS_PASSWORD:-123456}
--appendonly yes
--appendfilename "master-appendonly.aof"
--dbfilename "master-dump.rdb"
--save 900 1
--save 300 10
--save 60 10000
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--tcp-keepalive 60
--timeout 300
volumes:
- redis-master-data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-123456}", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
# ========================================
# Redis Replica 1 (从节点1)
# ========================================
redis-replica-1:
image: redis:7.2-alpine
container_name: ljwx-redis-replica-1
ports:
- "6380:6379"
networks:
- redis-ha
command: >
redis-server
--requirepass ${REDIS_PASSWORD:-123456}
--masterauth ${REDIS_PASSWORD:-123456}
--replicaof redis-master 6379
--appendonly yes
--appendfilename "replica1-appendonly.aof"
--dbfilename "replica1-dump.rdb"
--save 900 1
--save 300 10
--save 60 10000
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--tcp-keepalive 60
--timeout 300
--replica-read-only yes
volumes:
- redis-replica-1-data:/data
depends_on:
redis-master:
condition: service_healthy
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-123456}", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
# ========================================
# Redis Replica 2 (从节点2)
# ========================================
redis-replica-2:
image: redis:7.2-alpine
container_name: ljwx-redis-replica-2
ports:
- "6381:6379"
networks:
- redis-ha
command: >
redis-server
--requirepass ${REDIS_PASSWORD:-123456}
--masterauth ${REDIS_PASSWORD:-123456}
--replicaof redis-master 6379
--appendonly yes
--appendfilename "replica2-appendonly.aof"
--dbfilename "replica2-dump.rdb"
--save 900 1
--save 300 10
--save 60 10000
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--tcp-keepalive 60
--timeout 300
--replica-read-only yes
volumes:
- redis-replica-2-data:/data
depends_on:
redis-master:
condition: service_healthy
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-123456}", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
# ========================================
# Sentinel 1 (哨兵1)
# ========================================
redis-sentinel-1:
image: redis:7.2-alpine
container_name: ljwx-redis-sentinel-1
ports:
- "26379:26379"
networks:
- redis-ha
command: >
sh -c "echo 'port 26379
sentinel monitor ljwx-master redis-master 6379 2
sentinel auth-pass ljwx-master ${REDIS_PASSWORD:-123456}
sentinel down-after-milliseconds ljwx-master 5000
sentinel parallel-syncs ljwx-master 1
sentinel failover-timeout ljwx-master 30000
sentinel deny-scripts-reconfig yes' > /tmp/sentinel.conf &&
redis-server /tmp/sentinel.conf --sentinel"
volumes:
- redis-sentinel-1-data:/data
depends_on:
redis-master:
condition: service_healthy
redis-replica-1:
condition: service_healthy
redis-replica-2:
condition: service_healthy
healthcheck:
test: ["CMD", "redis-cli", "-p", "26379", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
# ========================================
# Sentinel 2 (哨兵2)
# ========================================
redis-sentinel-2:
image: redis:7.2-alpine
container_name: ljwx-redis-sentinel-2
ports:
- "26380:26379"
networks:
- redis-ha
command: >
sh -c "echo 'port 26379
sentinel monitor ljwx-master redis-master 6379 2
sentinel auth-pass ljwx-master ${REDIS_PASSWORD:-123456}
sentinel down-after-milliseconds ljwx-master 5000
sentinel parallel-syncs ljwx-master 1
sentinel failover-timeout ljwx-master 30000
sentinel deny-scripts-reconfig yes' > /tmp/sentinel.conf &&
redis-server /tmp/sentinel.conf --sentinel"
volumes:
- redis-sentinel-2-data:/data
depends_on:
redis-master:
condition: service_healthy
redis-replica-1:
condition: service_healthy
redis-replica-2:
condition: service_healthy
healthcheck:
test: ["CMD", "redis-cli", "-p", "26379", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
# ========================================
# Sentinel 3 (哨兵3)
# ========================================
redis-sentinel-3:
image: redis:7.2-alpine
container_name: ljwx-redis-sentinel-3
ports:
- "26381:26379"
networks:
- redis-ha
command: >
sh -c "echo 'port 26379
sentinel monitor ljwx-master redis-master 6379 2
sentinel auth-pass ljwx-master ${REDIS_PASSWORD:-123456}
sentinel down-after-milliseconds ljwx-master 5000
sentinel parallel-syncs ljwx-master 1
sentinel failover-timeout ljwx-master 30000
sentinel deny-scripts-reconfig yes' > /tmp/sentinel.conf &&
redis-server /tmp/sentinel.conf --sentinel"
volumes:
- redis-sentinel-3-data:/data
depends_on:
redis-master:
condition: service_healthy
redis-replica-1:
condition: service_healthy
redis-replica-2:
condition: service_healthy
healthcheck:
test: ["CMD", "redis-cli", "-p", "26379", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
# ========================================
# Volumes (数据持久化)
# ========================================
volumes:
redis-master-data:
driver: local
redis-replica-1-data:
driver: local
redis-replica-2-data:
driver: local
redis-sentinel-1-data:
driver: local
redis-sentinel-2-data:
driver: local
redis-sentinel-3-data:
driver: local
# ========================================
# 使用说明
# ========================================
#
# 1. 启动集群:
# docker-compose -f docker-compose-redis-sentinel.yml up -d
#
# 2. 查看集群状态:
# docker exec ljwx-redis-sentinel-1 redis-cli -p 26379 sentinel master ljwx-master
#
# 3. 查看从节点:
# docker exec ljwx-redis-sentinel-1 redis-cli -p 26379 sentinel replicas ljwx-master
#
# 4. 查看哨兵:
# docker exec ljwx-redis-sentinel-1 redis-cli -p 26379 sentinel sentinels ljwx-master
#
# 5. 测试故障切换:
# docker stop ljwx-redis-master
# # 等待30秒,Sentinel会自动选举新的Master
# docker exec ljwx-redis-sentinel-1 redis-cli -p 26379 sentinel get-master-addr-by-name ljwx-master
#
# 6. 连接客户端测试:
# redis-cli -h 127.0.0.1 -p 6379 -a 123456 ping
# redis-cli -h 127.0.0.1 -p 6380 -a 123456 ping
#
# 7. 停止集群:
# docker-compose -f docker-compose-redis-sentinel.yml down
#
# 8. 清理数据(危险操作):
# docker-compose -f docker-compose-redis-sentinel.yml down -v