什么是动静分离?
其实就是七层调度,把动态文件的请求和静态文件的请求分别调到不同的后台服务器
什么是网站数据切分?
其实也是七层调度
比如我要把新浪新闻,新浪体育给分开
方法1:
用dns
www.baidu.com
news.baidu.com
tieba.baidu.com
这几个域名得到的ip不同,所以其实是不同的站点
方法2:
前端使用代理
通过代理软件七层调度来分离
以location来分
sports.sina.com.cn/nba/
sports.sina.com.cn/cba/
以文件名后缀来分
sports.sina.com.cn/xxx/xxxx/xxx/xxx.png
sports.sina.com.cn/xxx/xxxx/xxx/xxx.php
================================================================================================
1,四台机器,192.168.100.0/24为kvm的virbr1网络(模拟外网),172.16.25.0/24为桥接网络(模拟内网)
2,web1我这里用的是本来搭建好的lnmp(参考历史文章),为了后面方便测试(但这里直接把lnmp的web家目录改成discuz的家目录/usr/share/nginx/html/discuz)
3,web2这里简单的安装并启动rpm版的apache,并做一个简单主页就好
4,nginx这台需要按下面的第一步过程进行安装,这次只安装nginx就好,不用安装php,mysql等(因为是主要做代理)
5,客户端最好有图形界面,并安装firefox浏览器
nginx 反向代理
client(宿主机) 192.168.100.1
192.168.100.4 eth0 default
nginx(虚拟机1)
172.16.25.4 eth1 桥接
web1(虚拟机2) web2(虚拟机3)
172.16.25.2 172.16.25.3
(lnmp)
安装nginx
# yum install nginx
======================================================================================
例一:使用前端nginx代理后面一台web
client(宿主机) 192.168.100.1
|
|
| 192.168.100.4
nginx(虚拟机1)
172.16.25.4
|
|
|
web1(虚拟机2) 172.16.25.2
# cat /etc/nginx/nginx.conf |grep -v '#'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
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 /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name 192.168.100.4; --改成模拟nginx的外网ip
root /usr/share/nginx/html;
index index.php index.html;
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://172.16.25.2/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
} --这个例子主要讨论这一段,五行
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
--说明:下面这两句是做外网转内网双网段架构必需要加的
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
客户端使用firefox验证
访问 http://192.168.100.4/ --得到后台web上安装的lnmp
验证:
把后面的web关闭,客户端也访问不了,说明nginx默认没有缓存功能
例二:locate网站数据切分
client(宿主机) 192.168.100.1
192.168.100.4
nginx(虚拟机1)
172.16.25.4
web1(虚拟机2) web2(虚拟机3)
172.16.25.2 172.16.25.3
把例一nginx配置文件里的那五行改成下面两段(加在server { }配置段中 ):
location /nba/ {
proxy_pass http://172.16.25.2/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /cba/ {
proxy_pass http://172.16.25.3/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
# systemctl restart nginx
客户端验证
http://192.168.100.4/nba/
http://192.168.100.4/cba/
例三:网站动静分离
client(宿主机) 192.168.100.1
192.168.100.4
nginx(虚拟机1)
172.16.25.4
web1(虚拟机2) web2(虚拟机3)
172.16.25.2 172.16.25.3
把例二的配置再改成如下(加在server { }配置段中 ):
location ~ \.(html|htm|gif|jpeg|jpg|css|js|png|swf)$ {
proxy_pass http://172.16.25.2;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
location ~ \.(php|cgi)$ {
proxy_pass http://172.16.25.3;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
# systemctl restart nginx
客户端测试(过程省略)
例四:代理后端时使用负载均衡(load balance)
client(宿主机) 192.168.100.1
192.168.100.4
nginx(虚拟机1)
172.16.25.4
web1(虚拟机2) web2(虚拟机3)
172.16.25.2 172.16.25.3
下面一段加到http 和 server 之间
upstream backendweb {
server 172.16.25.2 weight=1 max_fails=2 fail_timeout=1s;
server 172.16.25.3 weight=1 max_fails=2 fail_timeout=1s;
}
--weight代表权重,max_fails=2 fail_timeout=1s代表健康检查(检查后台web是否ok,访问超时1秒,并两次超时,则认为不健康)
把例三的配置再改成如下(加在server { }配置段中 ):
location ~ \.(txt|html)$ {
proxy_pass http://backendweb; --backendweb是一个名称,对应上面upstream的配置
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
# systemctl restart nginx
客户端验证
访问http://192.168.100.4/1.txt
--验证时,会发现客户端针对同一个URL的访问也会一次web1一次web2,这再次验证说明了nginx默认并没有squid或varnish那样的缓存功能
负载均衡(lb load banlance)一般要注意四个方面:
1,算法 round-robin
2,健康检查
3,会话保持
4,数据一致 rsync drbd 共享存储 分布式存储
client request
LB(loaded balanced)
web1 web2
例五:使用ip_hash,实现同一IP客户端一旦调到一台,就一直调那一台
client(宿主机) 192.168.100.1
192.168.100.4
nginx(虚拟机1)
172.16.25.4
web1(虚拟机2) web2(虚拟机3)
172.16.25.2 172.16.25.3
upstream backendweb {
ip_hash; --在上个例子的基础上只加这一句;
server 172.16.25.2 weight=1 max_fails=2 fail_timeout=1s;
server 172.16.25.3 weight=1 max_fails=2 fail_timeout=1s;
}
# systemctl restart nginx
客户端验证
访问http://192.168.100.4/1.txt
--nginx的ip_hash的意思是,如果一个客户端的访问被调度到其中一台后台服务器,那么同一个IP来的访问都只会被调到这个后台服务器;这里测试时,如果都用同一个网段的内网IP来做客户端测试,可能会都只转到一个后台(因为nginx的hash算法是按网段来算的,如果是公网不同网段的客户端IP就不一样了)
对于nginx的upstrem算法总结:
1,round-robin 轮循(平均分配)
2,weight 权重(人为地分配权重,用于后台服务器性能不均的情况)
3,fair 响应时间(按后台的响应时间来分配,需要第三模块,但如果后台服务器都在内网,就没太大必要使用这种算法了)
4,url_hash 按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为多台缓存时比较有效,提高缓存命中率
5,ip_hash 在负载均衡的基础上加上会话保持(优点是配置方便,缺点是不能完全的负载均衡)
=======================================================================
client 192.168.100.1
|
| 192.168.100.4(模拟网站公网ip,整个架构的域名假设为web.cluster.com )
nginx 反向代理
| 172.16.25.4
|
-----------
| | 命中 hit 直接返回
动态程序文件.php | |
| squid(web加速,缓存静态文件或图片)
直接找web | |
---- | 没命中 miss 找后端web去取
| | 172.16.25.3
lnmp <---- |
172.16.25.2
实验前准备:
1,所有机器配置主机名并在/etc/hosts里互相绑定主机
2,关闭firewalld,selinux
3,关闭NetworkManager,并配置静态ip
4,配置本地yum,epel源,163源
5,时间同步
第一大步:在上图中的lnmp上安装并配置后面的网站
第二大步:在上图中的nginx服务器上安装并配置nginx
1,安装nginx
# yum install nginx
2,配置文件如下
# cat /etc/nginx/nginx.conf |grep -v '#'
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
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 /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
upstream squid {
server 172.16.25.3 weight=1 max_fails=2 fail_timeout=3s;
}
upstream web {
server 172.16.25.2 weight=1 max_fails=2 fail_timeout=3s;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name 192.168.100.4;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
location ~ .*\.php$ {
proxy_pass http://web;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
location ~ .*\.(html|htm|gif|jpeg|jpg|css|js|png|swf)$ {
proxy_pass http://squid;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
location / {
proxy_pass http://web;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
# systemctl restart nginx
第三大步:在上图中的squid服务器上安装并配置squid
1,安装squid
# yum install squid -y
2,配置squid主配置文件
# vim /etc/squid/squid.conf
http_access allow all --把这一行前面的全删除,再把这行修改成允许所有
http_port 80 accel vhost vport --修改成支持反向代理模式,端口也为80与nginx的配置对应
cache_dir ufs /var/spool/squid 256 16 256 --打开缓存目录的定义这一句
cache_peer 172.16.25.2 parent 80 0 no-query originserver name=web
cache_peer_domain web web.cluster.com --web.cluster.com就是我现在模拟的整个网站架构的域名
cache_peer_domain web 192.168.100.4 --加上这三句,表示代理后台的lnmp的80端口;web.cluster.com为网站的域名,192.168.100.4为我这个架构最前端的nginx的IP
3,启动squid
# systemctl restart squid
第四大步:验证
在客户端机器192.168.100.129上首先绑定静态DNS
--用于模拟DNS,如果不绑定,也可以直接使用公网IP192.168.100.4来访问,因为在squid里配置了(cache_peer_domain web web.cluster.com 和 cache_peer_domain web 192.168.100.4 两句)
cat /etc/hosts
192.168.100.4 web.cluster.com --IP要为前端nginx的IP,名字为这个网站的域名要和squid里的cache_peer_domain web web.cluster.com要对应
1,在客户端用firefox访问http://web.cluster.com/或http://192.168.100.4/是可以正常看到我的lnmp安装的discuz论坛
2,在客户端使用下面的命令验证discuz论坛的一个logo,可以看到在squid上命中的信息
# curl -I http://web.cluster.com/static/image/common/logo.png
HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Mon, 23 Nov 2015 08:10:09 GMT
Content-Type: image/png
Content-Length: 4425
Connection: keep-alive
Last-Modified: Tue, 09 Jun 2015 02:21:12 GMT
ETag: "55764d98-1149"
Accept-Ranges: bytes
Age: 3227
X-Cache: HIT from squid.cluster.com
X-Cache-Lookup: HIT from squid.cluster.com:3128
Via: 1.0 squid.cluster.com (squid/3.1.10)
3,关闭squid,在客户端用firefox访问,会发现整个网站都没有图片(静态的元素)
用curl -I http://web.cluster.com/static/image/common/logo.png来验证也会报错
因为我的架构里只有一台squid,再次启动squid后,一切又恢复正常
4,关于squid手动清缓存
# vim /etc/squid/squid.conf
acl purge_admin src 127.0.0.1
acl purge method PURGE
http_access allow purge_admin purge
http_access deny all purge
# systemctl restart squid
最基本的清除一条缓存的操作,必须要在squid本机执行
# squidclient -m PURGE -h 127.0.0.1 -p 80 http://192.168.100.4/static/image/common/logo.png
-- -h参数后只能接127.0.0.1;-p 80是squid的监听端口;最后的路径就是客户端访问的路径
如果要批量清除squid,可以使用下面的脚本(你需要修改成自己对应的路径)
# vim /tmp/purge_squid.sh
#!/bin/bash
squidcache_path="/var/spool/squid/"
squidclient_path="/usr/bin/squidclient"
grep -a -r $1 $squidcache_path/* | strings | grep "http" | while read url
do
$squidclient_path -h 127.0.0.1 -m PURGE -p 80 $url > /dev/null 2>&1
echo "$url被清除"
done
--注意:脚本的squidcache_path修改成你对应的缓存目录,squidclient_path修改成squidclient命令的路径;-h 127.0.0.1是因为我做了acl限制的,所以只能在squid本机上清除
批量清除的方法:
sh /tmp/purge_squid.sh .txt --表示清除所有的.txt结尾的缓存
sh /tmp/purge_squid.sh . --表示清除所有缓存
sh /tmp/purge_squid.sh /aaa/ --表示url里有/aaa/路径就清掉缓存
===============================================================================
在上面的架构基础上多加一台squid2(我这里IP为172.16.25.5)
client 192.168.100.1
|
| 192.168.100.4
nginx
| 172.16.25.4
|
|------------|
| |
| squid1 squid2
| 172.16.25.3 172.16.25.5
|------------|
|
|
lnmp
172.16.25.2
做法,在nginx配置要修改的为下面一段
upstream squid {
server 172.16.25.3 weight=1 max_fails=2 fail_timeout=3s;
server 172.16.25.5 weight=1 max_fails=2 fail_timeout=3s;
}
# systemctl restart nginx
在客户端用curl -I去测试多个不同的文件请求,看缓存情况,如:
curl -I http://web.cluster.com/static/image/common/logo.png
curl -I http://web.cluster.com/static/image/feed/task_b.png
curl -I http://web.cluster.com/static/image/feed/album_b.png
curl -I http://web.cluster.com/static/image/feed/portal_b.png
curl -I http://web.cluster.com/static/image/feed/wall_b.png
测试结果为:第一次squid1,第二次squid2,第三次squid1...以此类推(round-robin)
但这个做法的缺点为:比如同一个url的请求,连续访问,它也会RR轮循给squid1和squid2,这样会造成两个squid重复缓存。
改进的做法为:使用nginx的url_hash的算法,把同一个url的请求只给同一个后台squid,以提高缓存命中率。如果要做这个改进的话,只需要把nginx的配置再修改成如下:
upstream squid {
hash $request_uri;
server 172.16.25.3 weight=1 max_fails=2 fail_timeout=3s;
server 172.16.25.5 weight=1 max_fails=2 fail_timeout=3s;
}
# systemctl restart nginx
再次测试:
结果为:新的请求仍然会RR轮循调给squid1和squid2,但已经请求过的地址再次被请求,会调给第一次调的squid,提高缓存命中率。
=================================================================================