问题背景:
- 之前前端调用 /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>
278 lines
7.8 KiB
YAML
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
|