高可用(High Availability,简称 HA)是指系统在面对各种可能出现的故障或错误时,能够持续保持服务可用状态的一种能力。
高可用使用“9”的数量衡量,行业内常用数字“9”来衡量网站的可用性。例如,QQ 的可用性是 4 个 9,这意味着 QQ 能够保证在一年内,服务在 99.99% 的时间是可用的,只有 0.01% 的时间不可用,大约最多 53 分钟。
对于大多数网站:
2 个 9(99%):这是基本可用的标准。意味着在一年 365 天中,系统允许有 3.65 天的停机时间。
3 个 9(99.9%):属于较高可用,一年内允许停机时间约为 8.76 小时。
4 个 9(99.99%):具备自动恢复能力的高可用,一年内停机时间约为 52.56 分钟。
甚至还有 5 个 9(99.999%),一年内停机时间仅约为 5.26 分钟。
将数据复制多份存储在不同的物理位置或存储设备上。
当某一处的数据存储出现故障(如硬盘损坏、数据丢失等)时,可以从备份的数据中快速恢复,保证系统的数据完整性和可用性。例如,数据库系统通常会采用主从复制的方式,主数据库负责写入操作,从数据库负责读取操作,同时从数据库也是主数据库的数据备份,一旦主数据库出现故障,从数据库可以迅速接管服务。
将多个相同的服务器组成一个集群,共同对外提供服务。
通过集群管理软件来分配和协调各个服务器的工作负载。当其中一台服务器出现故障时,其他服务器可以继续处理请求,用户不会察觉到服务的中断。例如,Web 服务器集群可以通过负载均衡器将用户的 HTTP 请求均匀地分配到各个服务器上。
将工作负载(如网络流量、计算任务等)均匀地分配到多个服务器或计算资源上。
避免单个服务器过载,提高系统整体的处理能力和响应速度。同时,当某台服务器出现故障时,负载均衡器可以将请求自动转发到其他正常的服务器上。常见的负载均衡算法有轮询、加权轮询、最小连接数等。
定期对服务器、网络设备、应用程序等进行检查,以确定其是否正常运行。
作用:能够及时发现故障,为后续的故障处理和恢复提供依据。例如,在服务器集群中,负载均衡器可以通过发送心跳包等方式对服务器进行健康检查,一旦发现某台服务器无响应,就将其从集群中移除,不再分配任务给它。
当系统中的某个节点(如服务器、服务进程等)出现故障(如软件崩溃、死机等)时,能够自动重新启动该节点。
快速恢复服务,减少人工干预的时间和成本。例如,一些监控软件可以监控服务器上的服务进程,一旦发现进程意外终止,就会自动重启该进程。
当后端服务出现故障或响应过慢时,为了防止故障蔓延,暂时切断对该服务的调用,并返回预设的错误响应。
保护系统的整体稳定性,避免因某个服务的故障导致整个系统崩溃。例如,在微服务架构中,如果某个微服务频繁超时,调用方可以启动熔断机制,暂时停止对该微服务的调用,直到该微服务恢复正常。
在系统面临高负载或部分服务出现故障时,有选择性地降低某些非核心功能的服务质量,以保障核心功能的正常运行。
确保系统在资源受限的情况下,能够尽可能地满足用户的关键需求。例如,在电商促销活动期间,当订单处理系统压力过大时,可以暂时关闭商品推荐功能,集中资源处理订单。
当调用外部接口(如 API)失败时,在一定条件下(如重试次数限制、时间间隔等)自动重新发起调用请求。
在一些可能是由于网络抖动等临时性故障导致的接口调用失败情况下,通过重试可以成功获取数据或完成操作,提高系统的可靠性。例如,当调用支付接口失败时,在合理的重试次数内再次发起支付请求。
对于 Zuul 网关来说,实现高可用意味着确保它在处理大量请求以及面对各种可能的故障场景(如服务器宕机、网络故障等)时,能够不间断地为后端服务提供可靠的请求转发和相关功能。
下面将启动多个 Zuul 网关实例,组成 Zuul 集群。多个 Zuul 实例可以分布在不同的物理服务器或虚拟机上。然后利用 Nginx 实现负载均衡,将对 Zuul 的请求均匀分布到各个 Zuul 实例上。
架构如下图:
使用 IDEA 启动相关的服务,如:产品服务、Eureka 注册中心、Zuul 网关服务,网关服务分别运行在 9000 和 9001 端口上,如下图:
当服务启动完成后,使用浏览器分别访问验证:
这里使用 nginx-1.21.3 版本,nginx.conf 配置文件内容如下:
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; # 看这里 # 定义一组后端服务器,这里定义的组名为gateway # 采用默认轮训负载均衡策略 upstream gateway { server 127.0.0.1:9000; server 127.0.0.1:9001; } # 看这里 server { listen 80; server_name localhost; location / { proxy_pass http://gateway; } } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} }
保存配置,使用 nginx -t 验证配置文件是否存在语法错误,没有语法错误,则启动 nginx 服务,或者使用 nginx -s reload 加载配置文件。
使用浏览器访问 http://localhost/api/product/product/get?id=1 地址,走 80 端口,如下图:
此时,我们将 9001 端口的网关服务停掉,如下图:
再次访问,依然正常,如下图:
到这里,Zuul + Nginx 高可用环境搭建成功了。
注意:当一个请求过来时,首先经过 Nginx 的一层负载,到达网关,然后由网关负载到真实后端。若后端有问题,网关会进行重试访问,多次访问后仍返回失败,可以通过熔断或服务降级立即返回结果。而且,由于是负载均衡,网关重试时不一定会访问到出错的后端。
点击下载/查看本教程相关资料或者源代码。