前言
使用集群是网站解决高并发, 海量数据问题的常用手段. 当一台服务器的处理能力, 存储空间不足时, 不要企图去换更强大的服务器, 对大型网站而言, 不管多么强大的服务器, 都满足不了网站持续增长的业务需求. 这种情况下, 更恰当的做法是增加一台服务器分担原有服务器的访问及存储压力.
通过负载均衡调度服务器, 将来自浏览器的访问请求分发到应用服务器集群中的任何一台服务器上, 如果有更多的用户, 就在集群中加入更多的应用服务器, 使应用服务器的负载压力不再成为整个网站的瓶颈.
摘自《大型网站技术架构_核心原理与案例分析》
环境准备
- 192.168.0.221:nginx + keepalived master
- 192.168.0.222:nginx + keepalived backup
- 192.168.0.223:tomcat
- 192.168.0.224:tomcat
虚拟 ip(VIP):192.168.0.200, 对外提供服务的 ip, 也可称作浮动 ip
各个组件之间的关系图如下:
tomcat 做应用服务器
tomcat 的安装不在本博客范围之内, 具体可参考 VirtualBox 安装 CentOS, 并搭建 tomcat,tomcat 的 webapps 下记得放自己的应用, 我的是 myWeb, 如果大家也用我的 myWeb, 那么 index.jsp 中的 ip 需要换成自己的
将 192.168.0.223,192.168.0.224 上的 tomcat 启动起来, tomcat 的路径可能和我的不一致, 需要写成自己的
- # cd /usr/local/tomcat7/bin
- # ./startup.sh
访问 myWeb 如下
nginx 做负载均衡
nginx 的安装, 本文就不讲述了.
nginx.conf 内容如下
- user root; #运行用户
- worker_processes 1; #启动进程, 通常设置成和 CPU 的数量相等
- # 全局错误日志及 PID 文件
- error_log /usr/local/nginx/logs/error.log;
- error_log /usr/local/nginx/logs/error.log notice;
- error_log /usr/local/nginx/logs/error.log info;
- pid /usr/local/nginx/logs/nginx.pid;
- # 工作模式及连接数上线
- events
- {
- use epoll; #epoll 是多路复用 IO(I/O Multiplexing)中的一种方式, 但是仅用于 linux2.6 以上内核, 可以大大提高 nginx 的性能
- worker_connections 1024; #单个后台 worker process 进程的最大并发链接数
- }
- # 设定 http 服务器, 利用它的反向代理功能提供负载均衡支持
- http
- {
- include mime.types;
- default_type application/octet-stream;
- #设定请求缓冲
- server_names_hash_bucket_size 128;
- client_header_buffer_size 32K;
- large_client_header_buffers 4 32k;
- # client_max_body_size 8m;
- #sendfile 指令指定 nginx 是否调用 sendfile 函数 (zero copy 方式) 来输出文件, 对于普通应用,
- #必须设为 on, 如果用来进行下载等应用磁盘 IO 重负载应用, 可设置为 off, 以平衡磁盘与网络 I/O 处理速度, 降低系统的 uptime.
- sendfile on;
- tcp_nopush on;
- tcp_nodelay on;
- #连接超时时间
- keepalive_timeout 65;
- #开启 gzip 压缩, 降低传输流量
- gzip on;
- gzip_min_length 1k;
- gzip_buffers 4 16k;
- gzip_http_version 1.1;
- gzip_comp_level 2;
- gzip_types text/plain application/x-JavaScript text/CSS application/xml;
- gzip_vary on;
- #添加 tomcat 列表, 真实应用服务器都放在这
- upstream tomcat_pool
- {
- #server tomcat 地址: 端口号 weight 表示权值, 权值越大, 被分配的几率越大;
- server 192.168.0.223:8080 weight=4 max_fails=2 fail_timeout=30s;
- server 192.168.0.224:8080 weight=4 max_fails=2 fail_timeout=30s;
- }
- server
- {
- listen 80; #监听端口
- server_name localhost;
- #默认请求设置
- location / {
- proxy_pass http://tomcat_pool; #转向 tomcat 处理
- }
- #所有的 jsp 页面均由 tomcat 处理
- location ~ \.(jsp|jspx|dp)?$
- {
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_pass http://tomcat_pool; #转向 tomcat 处理
- }
- #所有的静态文件直接读取不经过 tomcat,nginx 自己处理
- location ~ .*\.(htm|html|gif|jpg|jpeg|PNG|bmp|swf|IoC|rar|zip|txt|flv|mid|doc|ppt|PDF|xls|mp3|wma)$
- {
- expires 30d;
- }
- location ~ .*\.(JS|CSS)?$
- {
- expires 1h;
- }
- #定义错误提示页面
- error_page 500 502 503 504 /50x.HTML;
- location = /50x.HTML {
- root HTML;
- }
- }
- }
主从 nginx 的配置文件完全一样, nginx.conf 配置可复杂可简单, 大家根据自己的情况自行配置, 照搬上述配置也是可以的.
配置好后, 启动 nginx, 路径要写自己的
- # cd /usr/local/nginx/sbin
- # ./nginx
访问 nginx, 效果如下:
两台 nginx 服务器服务正常, 此时是没有主从之分的, 两者级别一样高, 当配置 keepalived 之后就有了主从之分了.
keepalived 实现 nginx 高可用(HA)
keepalived 的安装本文就不讲述了. keepalived 作用其实在第一张图中已经有所体现, 主要起到两个作用: 实现 VIP 到本地 ip 的映射; 以及检测 nginx 状态.
master 上的 keepalived.conf 内容如下:
- global_defs {
- notification_email {
- 997914490@qq.com
- }
- notification_email_from sns-lvs@gmail.com
- smtp_server smtp.hysec.com
- smtp_connection_timeout 30
- router_id nginx_master # 设置 nginx master 的 id, 在一个网络应该是唯一的
- }
- vrrp_script chk_http_port {
- script "/usr/local/src/check_nginx_pid.sh" #最后手动执行下此脚本, 以确保此脚本能够正常执行
- interval 2 #(检测脚本执行的间隔, 单位是秒)
- weight 2
- }
- vrrp_instance VI_1 {
- state MASTER # 指定 keepalived 的角色, MASTER 为主, BACKUP 为备
- interface eth0 # 当前进行 vrrp 通讯的网络接口卡(当前 CentOS 的网卡)
- virtual_router_id 66 # 虚拟路由编号, 主从要一直
- priority 100 # 优先级, 数值越大, 获取处理请求的优先级越高
- advert_int 1 # 检查间隔, 默认为 1s(vrrp 组播周期秒数)
- authentication {
- auth_type PASS
- auth_pass 1111
- }
- track_script {
- chk_http_port #(调用检测脚本)
- }
- virtual_ipaddress {
- 192.168.0.200 # 定义虚拟 ip(VIP), 可多设, 每行一个
- }
- }
backup 上的 keepalived.conf 内容如下:
- global_defs {
- notification_email {
- 997914490@qq.com
- }
- notification_email_from sns-lvs@gmail.com
- smtp_server smtp.hysec.com
- smtp_connection_timeout 30
- router_id nginx_backup # 设置 nginx backup 的 id, 在一个网络应该是唯一的
- }
- vrrp_script chk_http_port {
- script "/usr/local/src/check_nginx_pid.sh"
- interval 2 #(检测脚本执行的间隔)
- weight 2
- }
- vrrp_instance VI_1 {
- state BACKUP # 指定 keepalived 的角色, MASTER 为主, BACKUP 为备
- interface eth0 # 当前进行 vrrp 通讯的网络接口卡(当前 CentOS 的网卡)
- virtual_router_id 66 # 虚拟路由编号, 主从要一直
- priority 99 # 优先级, 数值越大, 获取处理请求的优先级越高
- advert_int 1 # 检查间隔, 默认为 1s(vrrp 组播周期秒数)
- authentication {
- auth_type PASS
- auth_pass 1111
- }
- track_script {
- chk_http_port #(调用检测脚本)
- }
- virtual_ipaddress {
- 192.168.0.200 # 定义虚拟 ip(VIP), 可多设, 每行一个
- }
- }
nginx 检测脚本 check_nginx_pid.sh 内容如下:
- #!/bin/bash
- A=`ps -C nginx --no-header |wc -l`
- if [ $A -eq 0 ];then
- /usr/local/nginx/sbin/nginx #重启 nginx
- if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then #nginx 重启失败
- exit 1
- else
- exit 0
- fi
- else
- exit 0
- fi
启动 keepalived
# service keepalived start
访问 VIP, 效果如下:
我们来看下 keepalived 的日志信息
master(192.168.0.221):
backup(192.168.0.222):
当我们把 master 上的 keepalived 停掉(模拟宕机), 再来看下 keepalived 日志
原 master(192.168.0.221):
原 backup(192.168.0.222):
通过 VIP 可以正常访问服务, 前端请求感受不到后端 nginx 的切换; 重新唤醒原 master(192.168.0.221)的测试这里就不进行了, 大家自行测试
注意点
1, 执行脚本时报错:/bin/sh^M: bad interpreter: 没有那个文件或目录
因为操作系统是 Windows, 我在 Windows 下编辑的脚本, 所以有可能有不可见字符. 脚本文件是 DOS 格式的, 即每一行的行尾以回车符和换行符来标识, 其 ASCII 码分别是 0x0D, 0x0A. 可以有很多种办法看这个文件是 DOS 格式的还是 UNIX 格式的, 还是 Mac 格式的
解决方法:
- VIM filename
- :set ff? #可以看到 dos 或 unix 的字样. 如果的确是 dos 格式的.
- :set ff=unix #把它强制为 unix 格式的, 然后存盘退出.
再次运行脚本.
从 Windows 编辑文件再拷贝到 Linux 时要特别注意, 另外, 脚本需要赋予可执行权限才能执行, 可执行文件的一种直观表现就是文件本身呈绿色.
2, 负载均衡最好进行多浏览器测试, 有些浏览器会缓存, 会产生没有负载均衡的效果.
例如我这次测试中谷歌浏览器就出现了类似的情况(还没搞清楚是否是缓存的原因), 火狐, 360,IE 浏览器都是正常的负载均衡效果.
3, 请求走向
访问虚拟 IP(VIP),keepalived 将请求映射到本地 nginx,nginx 将请求转发至 tomcat, 例如: http://192.168.0.200/myWeb/, 被映射成 http://192.168.0.221/myWeb/, 端口是 80, 而 221 上 nginx 的端口正好是 80; 映射到 nginx 上后, nginx 再进行请求的转发.
keepalived 服务器的 ip 情况
VIP 总会在 keepalived 服务器中的某一台上, 也只会在其中的某一台上; VIP 绑定的服务器上的 nginx 就是 master, 当 VIP 所在的服务器宕机了, keepalived 会将 VIP 转移到 backup 上, 并将 backup 提升为 master.
4,VIP 也称浮动 ip, 是公网 ip, 与域名进行映射, 对外提供服务; 其他 ip 一般而言都是内网 ip, 外部是直接访问不了的
来源: https://juejin.im/post/5c7fce89f265da2ddb298d5d