最近同学出去面试经常会被问到一个问题。
面试官:你说你们公司使用nginx反向代理tornado,部署了多少多少台机器,好像很牛逼的样子,但是我问你,如果主机也就是部署了nginx那台机器并发过大导致宕机了怎么办?
答曰:不考虑带宽峰值的话,比较新的 CPU 跑 nginx 单核每秒能接近 2 万请求,而且nginx如果纯做 HTTP 转发的话,Nginx 的性能高到恐怖,会挂掉很不科学。。。。
面试官:好吧,算你会忽悠,那如果插头被扫地大妈踢掉了怎么办,因为没电导致服务器宕机
答曰:阿里云机房会断电。。。你特么在逗我吧。。
其实负责转发的主机宕机概率很小,但是绝对不是没有,任何事都不是绝对,所谓的高可用架构就是体现在容灾机制上,如果主机宕机我们必须要做预案,万无一失才叫高可用架构,这里我们使用docker-compose来部署nginx-keepalived双机热备机制,vip主机可以进行漂移,这样主机挂掉了,还有备用机可以顶上
Keepalived是Linux下面实现VRRP备份路由的高可靠性运行件。基于Keepalived设计的服务模式能够真正做到主服务器和备份服务器故障时IP瞬间无缝交接。二者结合,可以构架出比较稳定的软件LB方案。
简单点说,就是keepalived可以将下面这种简单的负载均衡模式
当有主机挂掉的时候,服务能瞬间切换到备用机
首先,安装docker和docker-compose按下不表,可以参考这篇文章,在centos7.6上利用docker-compose统一管理容器和服务
建立nginx_keepalived文件夹
建立Dockerfile文件,这里我们使用alpine作为基础镜像,原因很简单,因为它体积小啊
FROM nginx:1.13.5-alpine RUN apk update && apk upgrade RUN apk add --no-cache bash curl ipvsadm iproute2 openrc keepalived && rm -f /var/cache/apk/* /tmp/* COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh CMD ["/entrypoint.sh"]然后建立docker-compose.yml文件,这里我们仿照线上环境,部署一台主机和一台从机,分别安装nginx
version: "3" services: nginx_master: build: context: ./ dockerfile: ./Dockerfile volumes: - ./index-master.html:/usr/share/nginx/html/index.html - ./favicon.ico:/usr/share/nginx/html/favicon.ico - ./keepalived-master.conf:/etc/keepalived/keepalived.conf networks: static-network: ipv4_address: 172.20.128.2 cap_add: - NET_ADMIN nginx_slave: build: context: ./ dockerfile: ./Dockerfile volumes: - ./index-slave.html:/usr/share/nginx/html/index.html - ./favicon.ico:/usr/share/nginx/html/favicon.ico - ./keepalived-slave.conf:/etc/keepalived/keepalived.conf networks: static-network: ipv4_address: 172.20.128.3 cap_add: - NET_ADMIN proxy: image: haproxy:1.7-alpine ports: - 8000:6301 volumes: - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg networks: - static-network networks: static-network: ipam: config: - subnet: 172.20.0.0/16随后,撰写nginx配置文件,keepalived-master.conf 这里由于我们没有后端tornado服务,所以使用虚拟代理服务
vrrp_script chk_nginx { script "pidof nginx" interval 2 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 33 priority 200 advert_int 1 unicast_src_ip 172.20.128.2 unicast_peer { 172.20.128.3 } authentication { auth_type PASS auth_pass letmein } virtual_ipaddress { 172.20.128.4/24 dev eth0 } track_script { chk_nginx } }
同理再复制一份从机的nginx配置keepalived-slave.conf
vrrp_script chk_nginx { script "pidof nginx" interval 2 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 33 priority 100 advert_int 1 unicast_src_ip 172.20.128.3 unicast_peer { 172.20.128.2 } authentication { auth_type PASS auth_pass letmein } virtual_ipaddress { 172.20.128.4/24 dev eth0 } track_script { chk_nginx } }
随后为后端服务做两个网页,一个主机index-master.html一个从机index-slave.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>主机</title> <style> #box{ margin: 0px auto; font-family: 'Times New Roman', Times, serif; font-size: 30px; font-style: initial; color: aliceblue; } body{ background-color: black } </style> </head> <body> <div id="box"> 主机 </div> </body> </html>从机的复制一份,将主机改成从机即可
因为我们要模拟后台服务,所以需要haproxy.cfg配置文件
global log 127.0.0.1 local0 maxconn 4096 daemon nbproc 4 defaults log 127.0.0.1 local3 mode http option dontlognull option redispatch retries 2 maxconn 2000 balance roundrobin timeout connect 5000ms timeout client 5000ms timeout server 5000ms frontend main bind *:6301 default_backend webserver backend webserver server ngxin_master 172.20.128.4:80 check inter 2000 rise 2 fall 5最后,撰写服务的shell脚本entrypoint.sh
#!/bin/sh /usr/sbin/keepalived -n -l -D -f /etc/keepalived/keepalived.conf --dont-fork --log-console & nginx -g "daemon off;"
整个项目结构如下:
现在我们来启动容器集群,输入命令:docker-compose up
发现容器已经启动
另外一个命令行,输入:docker ps
可以看到,后台分别三个容器正在启动,两台nginx反向代理8000端口的后台服务,访问 localhost:8000
现在我们来模仿一下nginx主机宕机的情况
docker pause nginx_keepalive_nginx_master_1再次访问 localhost:8000
发现已经自动无缝切换到备用机,整个过程非常流畅
高可用架构的特性就体现在这里,所以在面试中,对于面试官提出的问题要不断的总结,对于不熟悉不知道的问题,一定要深入研究一下,这样才可以在面试中无往而不胜。