logo-mini

瞎折腾之-负载均衡集群实践

瞎折腾之-负载均衡集群实践

好就没出来水文章了,为了表示我还活着,就出来发发牢骚

PS:这是本博客分享的第一篇原创的技术类文章,其实我一直觉得在博客写这些技术文有点太大众化,可能是有点强迫症。另外本文涉及代码较少主要谈心得,还请包涵(大神勿喷)

本文中提到的demo网站即:
IT派对云中心-ITpaidui.com

其实在2月份前,IT派对云中心一直采用单机的解决方案,即一台高配服务器上搭建了云中心(whmcs)程序所需要的所有运行环境,然后在这台服务器外面通过反向代理的方式额外套了两台高防的服务器(安装了抗cc攻击和缓存模块),然后将加速型CDN解析到高防IP。

看起来上面这种做法似乎不错,不过经过实际运行分析log和多次压力观测发现,当出现单IP多线程攻击时,防火墙能有效清洗掉频繁请求的IP,但是对于攻击IP数量非常大,而IP的访问频率比较低时,那很有可能在IP还没有触发防火墙阈值时网站就已经瘫痪了。经过实际数据分析,网站上httpd服务消耗的资源明显大于其他服务。于是决定实现站库分离。为httpd腾出更多空间。(至于为什么不采用Nginx加PHP-fpm架构,原因是这个架构运行whmcs太容易出现502了,考虑稳定性只能用Apache了)

于是乎,准备了四台服务器后,开始动手搭建。服务器(A,B,C,D)。服务器A安装了Nginx,起到负载均衡分配器和端口映射的作用(至于为什么不用CDN的负载均衡,后文会提到),服务器B和C安装Apache开启8080端口并配置好了PHP7和必要的ioncube解密扩展,服务器D安装MySQL数据库。四台服务器都位于一个内网中,服务器BCD绑定带宽1M,服务器A绑定了千兆的公网IP。

搭一个网站当然是很容易的事情,很快,通过服务器B,C已经可以看到网站了。我起初以为大功告成,绑定了CDN后就开始测试,结果发现,当我模拟用户登录用户中心时发现了登录成功后又跳转会登录界面的问题。通过curl命令多次观察后发现,是因为第一次登录,CDN的负载均衡将请求发送到了服务器B,而我刷新后,CDN将请求发送到了服务器C,而服务器C中不能识别刚才登录到服务器B的cookies于是又要求重新登录,如此循环导致无法登录成功。为了解决cookies问题,只能让服务器A出场了。通过查阅Google,得知Nginx的up-stream负载均衡模块可以同时使用基于cookies粘滞的sticky。于是乎,开始编译安装配置Nginx。

##Nginx负载均衡关键配置文件
upstream cluster_test {
sticky expires=10min;#代表启用cookie粘滞,cookies有效期10分钟
server 192.168.100.2:8080;#服务器B
server 192.168.100.3:8080;#服务器C
#服务器B,C内网监听端口为8080
}

Cookies粘滞的原理其实就是让前置负载均衡服务器在HTTP包头部植入了一串射了有效期的cookies,有效期内浏览器在访问网页时,负载均衡服务器会将用户锁定在某一台后端服务器上以避免会话中断。也就是说我第一次是在B服务器登录的话在cookies有效期内,就是B服务器一直为我服务,负载均衡将不会再把我转发到C服务器。

这样负载均衡模组就基本能够正常工作了。为了能提升网站速度减轻负载,这里额外使用Nginx开启了了内存缓存进行动静文件分离并编译了安全软件的抗CC攻击模块。动静分离的好处就不言而喻了对于静态文件交由负载均衡服务器之间拉取,动态PHP请求再转发给后端服务器的Apache。简单来说,这个就是大家常说的的lnmpa结构。
下面附上负载均衡Nginx的部分配置文件:

server {
listen 443 default http2;#监听443端口并启用HTTP/2
#PS:后来因为CDN厂商不支持HTTP/2,所以最终用户看到的还是HTTP1.1
server_name cloud.itpaidui.com ; #绑定域名
add_header Strict-Transport-Security "max-age=31536000; preload" always; #启用HSTS(大家使用时可以注释掉这一行,HSTS的装B性明显高于实用性)
add_header X-Frame-Options "DENY";#防止被iframe嵌套
set $proxy_pass itpaidui;#定义后端服务器模组,其中itpaidui和文章提到的上一段代码中服务器池名称一致
location / {
proxy_pass itpaidui; #后端应用服务器池
location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|tif|tiff|css|js|htm|html|ttf|otf|webp|woff|txt|csv|rtf|doc|docx|xls|xlsx|ppt|pptx|odf|odp|ods|odt|pdf|psd|ai|eot|eps|ps|zip|tar|tgz|gz|rar|bz2|7z|aac|m4a|mp3|mp4|ogg|wav|wma|3gp|avi|flv|m4v|mkv|mov|mpeg|mpg|wmv|exe|iso|dmg|swf)$ {
root /web/cloud.itpaidui.com/
#在/web/cloud.itpaidui.com/下面创建目录,设置上面目录中匹配的的静态文件由Nginx直接从A服务器磁盘拉取,对上面的正则表达式匹配的扩展名都生效
expires max;
try_files $uri @fallback; }
include /home/*.conf #嘿嘿这里还得包含一些比较重要的配置文件,就不贴出来了
}

这里细心的人会发现,上述配置中,C服务器只作为负载均衡服务器,那Nginx如何调取在/root /web/cloud.itpaidui.com/下的静态资源呢?
其实方法很简单,让A,B,C服务器的文件通过局域网内部同步不就完事了?
查阅资料后我最终采用了rsync和inotify协作同步的方案,rsync是一个高效的支持增量备份的Linux系统中文件同步软件,而Inotify 是一种强大的文件系统事件监控程序。通过这两个软件的配合可以实现当其中某一台服务器中的文件变化时,inotify可以很快激活rsync的同步。
确定了软件后,就立刻安装啦。帆帆用的服务器系统是CentOS7,所以就使用yum命令一键安装喽。打开xshell,用ssh连接B服务器后在终端输入

yum -y update #日常更新
yum -y install rsync inotify #安装软件

这里因为我偷懒了所以用yum一键安装。这里推荐大家下载完整包编译安装。
然后继续在终端输入命令 vim tongbu.sh 然后粘贴下列代码

#!/bin/bash
host=192.168.1.1 #被同步的服务器IP(负载均衡A服务器IP)
src=/web/cloud.itpaidui.com/ #设置变量(监听路径)
des=web
user=webuser #设置同步用户名
inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $src \
| while read files
do
rsync -vzrtopg --delete --progress --password-file=/usr/local/passwd.txt $src [email protected]$host::$des
echo "${files} was rsynced">>/tmp/rsync.log 2>&1
done

除此外我们还需要上传/usr/local/passwd.txt文件,里面填写同步密码,这个密码等下还会用到,做完这一切,我们还需要在终端输入

chmod 600 /usr/local/passwd.txt #修改文件权限600(为了安全和避免报错)

接下来在A服务器安装rsync,终端执行 yum -y install rsync 然后编辑配置文件 vim reync.conf 如下图

uid = root
gid = root #用户组
use chroot = no
max connections = 10 #最大连接线程数
strict modes = yes
pid file = /var/run/rsyncd.pid #进程路径
[web]
path = /web/cloud.itpaidui.com/ #你需要同步的目录
comment = web file
ignore errors
read only = no
write only = no
hosts allow = 192.168.1.3 #填写B服务器的IP地址
hosts deny = *
list = false
auth users = itpaidui
secrets file = /usr/local/passwd.txt #密码文件

然后在/usr/local/passwd.txt创建密码文件,里面填写 用户名:密码 注意,此处需要填写用户名,同样给文件600权限

然后就是在A服务器启动reync在B服务器启动脚本即可。这里为了保证稳定运行,我额外安装了守护程序supervisor来守护脚本防止意外退出。这样就彻底实现了动静分离,所有的静态文件交由A服务器Nginx处理。动静分离不仅能保证良好的负载和性能,更重要的是,这样彻底杜绝了在静态文件中植入恶意代码被执行的情况。有效提高安全性。

动静分离作为一项成熟的技术在IT派对所以对虚拟主机中都用上了,哈哈哈

当然rsync后来我在ABC三台服务器都做了配置,实现任意两台互相同步。这样动态PHP产生的PHP-Tpl模板缓存也能在服务器之间同步,加快了访问速度。

经过这样的内部负载均衡处理后,我就放心的将A服务器的IP添加到CDN的源站中。经过大量的压力测试,在高并发下,网站仍然能保持平均负载小于1.5打开无卡顿。

水了那么多,宝宝吃饭去了嘿嘿。


本文为 live-帆 原创,转载请注明出处

晓帆

I am a silly guy who always care you!


5 评论

    • LT-
    • 2017年5月27日 在 下午9:24-
    • 回复

    Nginx服务器很不错!干的漂亮,确实需要不停的尝试,希望越做越好

    • 瞎折腾的,,,,,,,,,

    • 呵呵-
    • 2017年3月2日 在 下午4:50-
    • 回复

    厉害死了你

    • ヽ(^。^)ノ滑稽

  • 实在太牛逼了,可惜我看不懂

留下你的评论