在单机系统中,任何硬件或软件故障都会导致服务中断。随着业务规模扩大,可用性成为衡量系统质量的核心指标。高可用(High Availability, HA)架构旨在通过冗余和自动故障转移,确保系统在部分组件失效时仍能持续提供服务。
高可用架构核心模式:
关键组件:
# 主备模式 (健康检查 + 故障转移)
upstream backend {
server 192.168.1.10:8080 max_fails=2 fail_timeout=10s;
server 192.168.1.11:8080 backup; # 备节点
}
# 主主模式 (多节点负载均衡)
upstream backend {
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=3;
server 192.168.1.12:8080 weight=3;
}
# 使用 keepalived 实现 VIP 自动切换 (主备)
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
virtual_ipaddress {
192.168.1.100
}
}
即使是高可用集群,也无法避免自然灾害、电力中断、网络分区等地域性故障。容灾设计的目标是:在发生大规模故障时,能够快速恢复业务,数据不丢失。常用的容灾模式包括冷备、温备、热备、双活、多活。
| 模式 | RTO | RPO | 成本 | 适用场景 |
|---|---|---|---|---|
| 冷备 | 小时级 | 天级 | 低 | 非关键业务 |
| 温备 | 分钟级 | 分钟级 | 中 | 关键业务,可接受少量数据丢失 |
| 热备 | 秒级 | 秒级 | 高 | 核心业务,数据零丢失要求 |
| 双活/多活 | 接近零 | 接近零 | 极高 | 互联网核心服务,全球业务 |
# 双主复制配置 (双向同步)
server-id = 1
log-bin = mysql-bin
auto-increment-increment = 2
auto-increment-offset = 1
# 另一节点的配置
server-id = 2
log-bin = mysql-bin
auto-increment-increment = 2
auto-increment-offset = 2
# 复制过滤 (避免循环复制)
replicate-do-db = mydb
replicate-ignore-db = mysql
在互联网系统中,流量可能因为促销活动、爬虫、攻击等原因突然暴涨,导致系统过载甚至崩溃。限流(Rate Limiting)通过控制请求速率,保护后端服务不被压垮。
| 算法 | 原理 | 突发支持 | 实现复杂度 |
|---|---|---|---|
| 计数器 | 固定时间窗口内计数 | 不支持 | 低 |
| 滑动窗口 | 将时间窗口细分为多个小窗口 | 不支持 | 中 |
| 漏桶 | 先进先出队列,匀速处理 | 不支持 | 中 |
| 令牌桶 | 定时生成令牌,请求消耗令牌 | 支持 (积累令牌) | 中 |
// 令牌桶限流器 (使用 go.uber.org/ratelimit)
import "go.uber.org/ratelimit"
// 每秒 10 个请求,允许突发 10 个
limiter := ratelimit.New(10)
func handleRequest() {
// 获取令牌,若没有则阻塞
limiter.Take()
// 处理业务逻辑
process()
}
// 滑动窗口限流 (使用 Redis)
// Redis 4.0 支持滑动窗口限流
redis.replicate("CL.THROTTLE", "user:123", "10", "10", "60")
当系统出现故障或资源不足时,强制拒绝所有请求(熔断)或返回简化结果(降级)可以防止故障扩大。熔断和降级是系统性容错的核心手段,它们与限流共同构成了高并发保护的三大支柱。
熔断器状态:
降级策略:
// HystrixCommand 配置熔断器
@HystrixCommand(fallbackMethod = "fallbackMethod",
commandProperties = {
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000")
})
public String callService() {
// 调用远程服务
return remoteService.call();
}
public String fallbackMethod() {
// 降级逻辑:返回默认值
return "default response";
}
# 使用 Sentinel 实现熔断降级 (Spring Cloud)
@SentinelResource(value = "resourceName", fallback = "fallback")
public String process() {
// 业务逻辑
}
系统容量不足会导致服务不可用,容量过剩则浪费成本。容量规划的目标是:在保证服务质量的前提下,以最优的成本满足业务需求。它需要综合考虑业务增长、峰值流量、弹性扩展等因素。
容量规划步骤:
# HPA (Horizontal Pod Autoscaler)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
# 查看 HPA 状态
kubectl get hpa myapp-hpa
# Cluster Autoscaler (节点自动扩缩)
# 在云平台配置 Cluster Autoscaler,节点不足时自动添加
在讨论高可用时,我们常说「99.99% 可用」,但这具体意味着什么?SLI(服务等级指标)定义了具体的可测量指标,SLO(服务等级目标)设定了期望的目标值,SLA(服务等级协议)则是对外承诺的合同。三者构成了一个完整的可靠性量化体系。
SLI (Service Level Indicator): 常见的 SLI 包括:
SLO (Service Level Objective): 例如「P99 延迟 < 200ms」或「可用性 > 99.99%」。
SLA (Service Level Agreement): 包含 SLO 和违反时的处罚条款。
# P99 延迟超过 SLO 告警
groups:
- name: slo_alerts
rules:
- alert: HighLatency
expr: histogram_quantile(0.99, sum by(le) (http_request_duration_seconds_bucket)) > 0.2
for: 5m
labels:
severity: warning
annotations:
summary: P99 延迟超过 200ms
description: P99 延迟为 {{ $value }}s,超过 SLO 阈值
# 错误率 SLO 告警
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.001
for: 5m
labels:
severity: critical
annotations:
summary: 错误率超过 0.1%
传统的高可用测试都是预期内的(如模拟故障关闭节点),但现实中的故障往往不可预测。混沌工程通过主动注入故障(如网络延迟、丢包、节点崩溃),来验证系统的弹性和容错能力。它源自 Netflix 的 Simian Army,现在已经发展为一套成熟的实践体系。
混沌工程实验流程:
# 使用 Chaos Mesh 注入网络延迟
apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
name: network-delay
spec:
action: delay
mode: one
selector:
labelSelectors:
app: myapp
delay:
latency: 200ms
correlation: 50
jitter: 50ms
# 注入 Pod 崩溃
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
name: pod-failure
spec:
action: pod-failure
mode: one
selector:
labelSelectors:
app: myapp
# 运行混沌实验
kubectl apply -f chaos-experiment.yaml
kubectl get chaos