在互联网项目开发中,总是不断针对新的需求去研发新的系统,而很多系统的设计都是可以触类旁通的:
描述 | 通俗叫法 | 可用性级别 | 年度停机时间 |
---|---|---|---|
基本可用性 | 2个9 | 99% | 87.6小时 |
较高可用性 | 3个9 | 99.9% | 8.8小时 |
具有故障自动恢复能力的可用性 | 4个9 | 99.99% | 53分钟 |
极高可用性 | 5个9 | 99.999% | 5分钟 |
* 故障时间 = 故障修复时间点 - 故障发现(报告)时间点
* 服务年度可用时间% =(1-故障时间/年度时间)× 100%
故障的度量与考核
类别 | 描述 |
---|---|
高危S级事故故障 | 一旦出问题,可能会导致服务整体不可用 |
严重A级故障 | 客户明细感知服务异常:错误的回答 |
中级B级故障 | 客户能感知服务异常:响应比较慢 |
一般C级故障 | 服务出现短时间抖动 |
服务级别可用性
类别 | 服务 | 可用性要求 | 描述 |
---|---|---|---|
一级核心服务 | 核心产品或者服务 | 99.99% | 系统引擎部分:一旦出现故障,整个系统瘫痪 |
二级核心服务 | 重要的产品功能 | 99.95% | 类比汽车轮子:该服务出现问题,该重要功能不可用 |
三级核心服务 | 一般功能 | 99.9% | 类比汽车倒车影像:该部分出现问题,稍微影响用户体验 |
四级核心服务 | 工具类服务 | 99% | 非业务功能:比如爬虫、管理后台、运维工具 |
* 负载均衡
* 限流
* 降级
* 隔离
* 超时与重试
* 回滚
* 压测与预案
以上负载均衡方案是接入层的方案,实际上负载均衡的地方还有很多:
# 给Nginx配置上游服务器,即负载均衡到的真实处理业务的服务器,通过在http指令下配置upstream即可
upstream backend {
server 192.168.254.100:8080 weight=1;
server 192.168.254.120:8080 weight=2;
}
# proxy_pass来处理用户请求
location / {
proxy_pass http://backend;
}
负载均衡用来解决用户请求到来时如何选择upstream server进行处理,默认采用的是round-robin(轮询),同时支持其他几种算法。
upstream backend {
ip_hash;
server 192.168.254.100:8080 weight=1;
server 192.168.254.120:8080 weight=2;
}
upstream backend {
hash $uri;
server 192.168.254.100:8080 weight=1;
server 192.168.254.120:8080 weight=2;
}
upstream backend {
hash $consistent_key consistent;
server 192.168.254.100:8080 weight=1;
server 192.168.254.120:8080 weight=2;
}
location / {
set $consistent_key $arg_cat;
if ($consistent_key = "") {
set $consistent_key $request_uri;
}
}
set_by_lua_file $consistent_key "lua_balancing.lua";
local consistent_key = args.cat;
if not consistent_key or consistent_key == '' then
consistent_key = ngx_var.request_uri
end
local value = balancing_cache:get(consistent_key)
if not value then
upstream backend {
server 192.168.254.100:8080 max_fails=2 fail_timeout=10s weight=1;
server 192.168.254.120:8080 max_fails=2 fail_timeout=10s weight=2;
}
location /test {
proxy_connect_timeout 5s;
proxy_read_timeout 5s;
proxy_send_timeout 5s;
proxy_next_upstream_error timeout;
proxy_next_upstream_timeout 10s;
proxy_next_upstream_tries 2;
}
upstream backend {
server 192.168.254.100:8080 weight=1;
server 192.168.254.120:8080 weight=2;
check interval=3000 rise=1 fall=3 timeout=2000 type=tcp;
}
upstream backend {
server 192.168.254.100:8080 weight=1;
server 192.168.254.120:8080 weight=2;
check interval=3000 rise=1 fall=3 timeout=2000 type=http;
check_http_send "HEAD /status HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
upstream backend {
server 192.168.254.100:8080 weight=1;
server 192.168.254.100:9090 weight=2 backup;
}
upstream backend {
server 192.168.254.100:8080 weight=1;
server 192.168.254.100:9090 weight=2 down;
}
漏斗有一个进水口和一个出水口,出水口以一定速率出水,并且有一个最大出水速率:
long limit = 1000;
while(true) {
// 得到当前秒
long currentSeconds = System.currentTimeMillis() / 1000;
if(counter.get(currentSeconds).incrementAndGet() > limit) {
System.out.println("限流了:" + currentSeconds);
continue;
}
// 业务处理
}
local key = KEYS[1] --限流KEY(一秒一个)
local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call("INCRBY", key, "1")) --请求数+1
if current > limit then --如果超出限流大小
return 0
elseif current == 1 then --只有第一次访问需要设置2秒的过期时间
redis.call("expire", key, "2")
end
return 1
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn_log_level error;
limit_conn_status 503;
...
server {
...
location /limit {
limit_conn addr 1;
}
}
}
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
limit_conn_log_level error;
limit_conn_status 503;
...
server {
...
location /limit {
limit_req zone=one burst=5 nodelay;
}
}
}
* 降级按照是否自动化可分为:自动开关降级和人工开关降级。
* 降级按照功能可分为:读服务降级和写服务降级。
* 降级按照处于的系统层次可分为:多级降级。
* 降级的功能点主要从服务器端链路考虑,即根据用户访问的服务调用链路来梳理哪里需要降级。
退款: 按钮 – 手抖,多点击几次----------- 接口 幂等性