一、相关概念:
代理(你到我这请求我没有,我可以帮你去请求)
正向代理(forward proxy内网用户的client想上互联网,通过代理到互联网去取数据,数据返回到代理上,代理构建响应返回至client(代理内网用户访问互联网上服务器的数据);可将正向代理服务器理解为秘书(对内声称只要想上网我什么都能做,但实际是互联网上的某个服务器提供的内容))
反向代理(reverse proxy我们的服务器不允许直接访问,在前端放一代理,所有的互联网上的客户端想要访问,得将请求提交至前面的代理上,而代理服务器仅在需要时才找后端服务器;可将反向代理服务器理解为总管(它对外声称它就是web-server,但其实是它后端服务器提供的功能)
请求方法(GET、POST、HEAD、PUT、TRACE、OPTION、CONNECTION、DELETE)
常用指令:
proxy_pass(实现反向代理)
fastcgi_pass(php的反向代理)
upstream(实现负载均衡)
proxy_cache_path、proxy_cache、proxy_cache_valid(实现缓存功能)
add_header(在协议首部添加标签)
rewrite(URL重写)
valid_referers(防盗链功能,结合if实现)
gzip on;(开启此功能可节约带宽,并节省报文到达client的时间,并不是什么情况下都压缩,如果在缓存时候压缩会带来负作用,会降低命中率,如第一次第一个用户请求的内容缓存后压缩了,当第二个用户访问相同内容时将不能从缓存中响应)
gzip_proxied(设置压缩策略,什么情况下压缩,什么情况下不压缩,如有no-cache、expired、no-store、private、auth)
gzip_comp_level(设置响应时的压缩比,1-9个级别,默认1)
二、操作及相关要点(1、反向代理;2、负载均衡;3、缓存;4、rewrite和referer;5、读写分离):
准备:
node1(192.168.41.134 安装nginx)
node2(192.168.41.135 安装httpd)
node3(192.168.41.136 安装httpd)
1、反向代理:
在《第三阶段(十五)理解LNMP》中,提供的对fastcfgi的反向代理:
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
}
syntax:proxy_pass URL;
(1)实现对主页反向代理(将location中root换为proxy_pass):
node1-side:
[root@node1 ~]# vim /etc/nginx/nginx.conf
server {
listen 80;
server_name www.magedu.com;
location / {
proxy_pass http://192.168.41.135:80;
……
}
node2-side:
[root@node2 ~]# cd /var/www/html
[root@node2 html]# cat index.html
RS1.magedu.com
[root@node2 html]# service httpd status
httpd (pid 10858) 正在运行...
<a href="http://s5.51cto.com/wyfs02/M00/79/2B/wKiom1aKXNegEUkNAABKiTAtLJ4665.jpg" target="_blank"></a>
(2)实现对指定的URI反向代理:
[root@node1 ~]# cd /etc/nginx
[root@node1 nginx]# vim nginx.conf
location /forum {
proxy_pass http://192.168.41.135:80/bbs;
[root@node2 html]# cd
[root@node2 html]# mkdir bbs
[root@node2 html]# echo "bbs.magedu.com" > bbs/index.html
测试时在浏览器上输入URL会自动跳转至后端192.168.41.135/bbs
<a href="http://s4.51cto.com/wyfs02/M01/79/2A/wKioL1aKXQqSjw8sAABJ87EJ__U003.jpg" target="_blank"></a>
<a href="http://s3.51cto.com/wyfs02/M00/79/2B/wKiom1aKXPOBX3lIAABNcMdyAhQ340.jpg" target="_blank"></a>
(3)若在location中使用模式匹配,则在proxy_pass所指定的后端server上不能使用uri路径,否则提示配置文件语法错误:
location ~* ^/forum {
proxy_set_header X-Real-IP $remote_addr;
[root@node1 nginx]# !service
service nginx reload
nginx: the configuration file/etc/nginx/nginx.conf syntax is ok
nginx: configuration file/etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@node2 html]# mkdir forum
[root@node2 html]# echo "forum.magedu.com" > forum/index.html
[root@node2 html]# vim /etc/httpd/conf/httpd.conf(更改如下配置,真正实现让后端server记录的日志中是真正的client地址)
LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\"\"%{User-Agent}i\"" combined
[root@node2 html]# !service
service httpd restart
停止 httpd: [确定]
正在启动 httpd: [确定]
<a href="http://s5.51cto.com/wyfs02/M01/79/2B/wKiom1aKXQbCjJwyAABJRK0SeAc608.jpg" target="_blank"></a>
[root@node2 html]# tail -2 /var/log/httpd/access_log(第一条记录是更改前的是代理的地址,第二条记录则是真正client的地址,由于此处虚拟机网络设置的是NAT模式(我工作的场所需要安装iNODE客户端才能连接公司内网,所以只有虚拟机设置了NAT模式才能与本机连接)所以显示的是网关,这里就不再更改网络配置了)
192.168.41.134 - - [23/Dec/2015:06:05:59+0800] "GET /forum/ HTTP/1.0" 304 - "-" "Mozilla/5.0(Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.26Safari/537.36 OPR/32.0.1948.4 (Edition beta)"
192.168.41.1 - - [23/Dec/2015:06:07:51+0800] "GET /forum/ HTTP/1.0" 304 - "-" "Mozilla/5.0(Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.26Safari/537.36 OPR/32.0.1948.4 (Edition beta)"
2、负载均衡load balance:
upstream
将后端多个服务器归并为一组,在组中定义LB调度算法;
在http{}之内server{}之外定义;
upstream中的server定义每一个后端服务器,server之后只能跟IP或名称不能加入http://,之后还可跟其它参数,如weight=NUM、max_fails=NUM、fail_timeout=TIME、backup,其中有weight表示使用rr算法,默认值是1,若没写weight,server上方也没写schedule表示此server不参加LB;backup(类似keepalived中的sorry_server)表示备用服务器,可用于RS全挂掉后在反向代理服务器上提供错误页面;
schedule调度算法(rr、ip_hash、least_conn),默认roundrobin,ip_hash(始终将同一client的请求转至同一RS)
[root@node1 nginx]# !vim(websrvs为自定义的组名)
vim nginx.conf
upstream websrvs {
server 192.168.41.135 weight=1 max_fails=2 fail_timeout=2;
server 192.168.41.136 weight=1 max_fails=2 fail_timeout=2;
server 127.0.0.1:8080 backup;
}
server {
listen 80;
server_name www.magedu.com;
proxy_pass http://websrvs;
proxy_set_header X-Real-IP$remote_addr;
listen 8080;
server_name localhost;
root /web/errorpages;
index index.html;
[root@node1 nginx]# mkdir /web/errorpages-pv
mkdir: 已创建目录"/web/errorpages"
[root@node1 nginx]# echo "Sorry,the server is maintaining" > /web/errorpages/index.html
node3-side:
[root@node3 ~]# cd /var/www/html
[root@node3 html]# vim index.html
[root@node3 html]# echo "RS2.magedu.com" > index.html
[root@node3 html]# service httpd start
测试:
<a href="http://s4.51cto.com/wyfs02/M02/79/2A/wKioL1aKXTmwY3jcAAAhoXEdEUI274.jpg" target="_blank"></a>
<a href="http://s3.51cto.com/wyfs02/M00/79/2A/wKioL1aKXUWTUiQEAAAgI_voEo0160.jpg" target="_blank"></a>
[root@node2 html]# service httpd stop
[root@node3 html]# service httpd stop
停止 httpd: [确定]
<a href="http://s1.51cto.com/wyfs02/M02/79/2B/wKiom1aKX-uiU9oJAAAkHsuD1lg096.jpg" target="_blank"></a>
若schedule使用ip_hash,则不能使用backup,否则会报配置文件语法错误:
ip_hash;
server 192.168.41.135 max_fails=2 fail_timeout=2;
server 192.168.41.136 max_fails=2 fail_timeout=2;
[root@node1 nginx]# netstat -tnlua | awk '/:80/{S[$NF]++}END{for (A in S) print A,S[A]}'
TIME_WAIT 4
ESTABLISHED 1
LISTEN 2
LB扩展(当后端有不同的服务器组,如app-server组处理动态内容,image-server组,file-server组):
upstream phpsrvs {
server……;
location ~* \.php$ {
fastcgi_pass http://phpsrvs;
upstream imagesrvs {
location ~* “\.(jpg|jpeg|png|gif)$” {
upstream filesrvs {
location / {
root /web/htdoc;
index index.html;
3、缓存:
nginx有两类缓存cache:共享内存,主要用于键存储(缓存的查找键key)及缓存对象的元数据;磁盘空间(存储数据)
proxy_cache_path在http{}之内server{}之外定义,该指令定义的是nginx有缓存功能(缓存能力),但具体谁要用到缓存要在location{}中使用proxy_cache指令定义
注:缓存是分级的,浏览器自己的缓存是私有缓存(private cache),而nginx的缓存是公共的(public cache,所有用户都可用)
注:nginx不仅可以缓存web object(见以下举例),也可为日志提供缓存功能(client的每次访问都要记入日志,为日志打开缓冲区),还可为fastcgi打开缓存功能
open_log_cache(日志缓存,先写入内存中,在适当时间再同步到文件中)
open_file_cache(打开文件缓存,nginx作为server,要处理用户所请求的内容,要打开很多文件响应给用户,尤其是元数据,打开后缓存在nginx所管理的内存中,加速响应过程)
fastcgi_cache(慎用,若第一次将php的执行结果缓存好,之后后端server的处理逻辑改了,这时响应的还是之前的内容)
注:nginx的limit也基于共享内存实现
syntax:
proxy_cache_path PATH [levels=LEVELS] keys_zone=NAME:SIZE [max_size=SIZE];
其中levels=LEVELS(定义缓存目录(子目录级别,子目录级别最多三级且每级目录名最多两个字符),目的使命名方式简单,如要缓存1000W万个对象,若都放到一个目录下则需要有1000W个变化,命名会复杂,若一级子目录有10个,则每个子目录下有100W个对象,再分二级、三级子目录,则其下的每个子目录有1W个对象,不仅使得命名容易也使定位查找更快,而且路径引用也不复杂)
例:levels=1:2(1表示一级子目录,2表示二级子目录;同时1又表示一级子目录由1个字符组成,2同时又表示二级子目录由2个字符组成,最多可有三级子目录,每级子目录最多2个字符),常用的有levels=1:2、levels=1:2:1、levels=1:1:1
keys_zone=NAME:SIZE(给共享内存命名,重要,此处的名字要被使用缓存者引用)
max_size=SIZE(缓存空间并不是越大越好,大了管理会复杂,小了清理缓存会降低命中率(缓存空间若存满了,由cache_manager根据LRU算法将之前没用到的缓存清理掉,若刚清出去又要用,这就未命中,又要重新获取),空间多大合适,要根据实际情况测试,如果增大空间命中率提升,则这个空间就要加大)
proxy_cache ZONE_NAME;(define a shared memory zone used for caching)
proxy_cache_valid [CODE] TIME;(sets caching time for different response codes)
[root@node1 nginx]# !vim
proxy_cache_path /etc/nginx/cache/first levels=1:2:1 keys_zone=first:20m max_size=1g;
upstream websrvs {
server 192.168.41.135 weight=1 max_fails=2 fail_timeout=2;
server 192.168.41.136 weight=1 max_fails=2 fail_timeout=2;
server 127.0.0.1:8080 backup;
server {
location / {
proxy_pass http://websrvs;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache first;
proxy_cache_valid 200 10m;
}
}
[root@node1 nginx]# mkdir cache/first -pv
mkdir: 已创建目录 "cache"
mkdir: 已创建目录"cache/first"
[root@node1 nginx]# service nginx reload
验证:测试时因为缓存命中了,LB也不起作用将不再找后端server,使用浏览器快捷键ctrl+F5(或shift+F5)可控制不使用浏览器自身缓存(在开发者工具:request headers:no-cache),使用add_header(每一次构建响应时为client增加新的标签)这样在client就可看出缓存是否命中
<a href="http://s3.51cto.com/wyfs02/M02/79/2A/wKioL1aKYUGR8b2xAACwBycvCs4678.jpg" target="_blank"></a>
[root@node1 nginx]# !vim($server_addr服务器地址,$upstream_cache_status状态有HIT、MISS、EXPIRED、BYPASS、UPDATING、STALE、REVALIDATED)
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status;
location / {
proxy_cache first;
proxy_cache_valid 200 10m;
<a href="http://s2.51cto.com/wyfs02/M00/79/2B/wKiom1aKYUGg1JXwAACR14FSqsI491.jpg" target="_blank"></a>
注:此处语句可合并为:add_header X-Cache “$upstream_cache_status from $server_addr”;
$upstream_cache_status(该变量是ngx_http_upstream_module提供的)
$server_addr(该变量是由ngx_http_core_module提供的)
[root@node1 nginx]# service nginx stop
停止 nginx: [确定]
[root@node1 nginx]# ls cache/first/2/b3/7/bc9c9eed354a58d3c2bde97d0a7d7b32
[root@node1 nginx]# rm -rf cache/first/*(将缓存删除,再次重新验证)
[root@node1 nginx]# service nginx start
正在启动 nginx: [确定]
<a href="http://s3.51cto.com/wyfs02/M01/79/2B/wKiom1aKYU_j_gtdAAB1TC6ckYs652.jpg" target="_blank"></a>
再次ctrl+F5刷新
<a href="http://s2.51cto.com/wyfs02/M01/79/2A/wKioL1aKYYuRVYFXAACCIz4VDE4907.jpg" target="_blank"></a>
[root@node1 nginx]# cp nginx.conf nginx.conf.example
[root@node1 nginx]# cp nginx.conf.default nginx.conf
cp:是否覆盖"nginx.conf"? y
4、rewrite和referer:
ngx_http_rewrite_module支持正则表达式,指令有break、return、rewrite、if
if (condition) {……}
测试:单目;双目(=|!=|~|!~|~*|!~*)
注:~,区分字符大小写,匹配为真,不匹配为假;!~,区分字符大小写,不匹配为真,匹配为假;~*,不区分字符大小写,匹配为真,不匹配为假;!~*,不区分字符大小写,不匹配不真,匹配为假;=,精确匹配,匹配为真,不匹配为假;!=,精确匹配,不匹配为真,匹配为假
例:if ($request_method = “POST”) {}
if ($request_uri ~* “/forum” {}
rewrite REGEX REPLACEMENT [FLAG];(用在server、location和if上下文中)
FLAG有四个值:
last(本次重写完成之后,重启下轮检查)
break(本次重写结束之后,直接执行后续操作,通常在某个非根下使用break)
redirect(302,临时重定向,returns a temporary redirect with the 302 code)
permanent(301,永久重定向,returns a permanent redirect with the 301 code)
例1(跨服务器重定向):
root html;
index index.html index.htm;
rewrite ^/bbs/(.*)$ http://192.168.41.135/forum/$1;
[root@node1 nginx]# service nginx restart
[root@node2 html]# cat /var/www/html/forum/index.html
forum.magedu.com
<a href="http://s4.51cto.com/wyfs02/M02/79/2A/wKioL1aKYaORDB7FAABLyPo5KA4301.jpg" target="_blank"></a>
<a href="http://s3.51cto.com/wyfs02/M01/79/2B/wKiom1aKYZuQHWmtAACKl5Zbhpk920.jpg" target="_blank"></a>
例2(本机内重定向,隐式重定向,client看不出来状态码正常200):
rewrite ^/bbs/(.*)$ /forum/$1;
[root@node1 nginx]# mkdir /usr/html/forum
[root@node1 nginx]# echo "the serveris nginx,134" > /usr/html/forum/index.html
<a href="http://s4.51cto.com/wyfs02/M02/79/2B/wKiom1aKYcTxFGN-AACKpi7Co8w244.jpg" target="_blank"></a>
补充:若出现循环,则会持续定向10次自动退出,如:
ngx_http_referer_module(ngx_http_referer_moduleis used to block access to a site for requests with invalid values in the “referer”header field,定义哪些引用有效,防盗链,常用的指令valid_referers(定义有效的引用,specifies the “referer” request header field values that will causethe embedded $invalid_referer variable to be set to an empty string)
例:
location /photos/ {
if ($invalid_referer) {
return 403;
}
注:none(在地址栏输入的,the “referer” field is missing in the request header)
blocked(类似启用防火墙法则,只要valid_referers这行中没有定义的就是不合法的,the “referer” field is present in the request header,but its valuehas been deleted by a firewall or proxy server; such values are strings that donot start with http://or https://)
5、读写分离(指定仅允许后端某一server可上传文件,后端另一server可访问):
webDAV(web-based distributed authoring and versioning),一种基于HTTP/1.1的通信协议,并扩展了HTTP/1.1,在GET、POST、HEAD等几个HTTP方法以外添加了一些新的方法,使应用程序可直接对web server直接读写,并支持写文件锁定locking和解锁unlock,还可支持文件的版本控制
[root@node2 html]# vim /etc/httpd/conf/httpd.conf
……
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_modulemodules/mod_dav_fs.so
<Directory"/var/www/html">
Dav on
</Directory>
[root@node2 html]# service httpd restart
[root@node2 html]# setfacl -m u:apache:rwx /var/www/html
[root@node2 html]# getfacl /var/www/html
getfacl: Removing leading '/' from absolutepath names
# file: var/www/html
# owner: root
# group: root
user::rwx
user:apache:rwx
group::r-x
mask::rwx
other::r-x
[root@node3 ~]# cat /var/www/html/index.html
RS2.magedu.com
proxy_pass http://192.168.41.136;
if ($request_method ="PUT") {
proxy_pass http://192.168.41.135;
}
验证:读取
<a href="http://s1.51cto.com/wyfs02/M01/79/2B/wKiom1aKYfDRUEbxAAAkVAuDqeU674.jpg" target="_blank"></a>
验证:上传
<!DOCTYPE HTML PUBLIC "-//IETF//DTDHTML 2.0//EN">
<html><head>
<title>201 Created</title>
</head><body>
<h1>Created</h1>
<p>Resource /hostshas been created.</p>
<hr />
<address>Apache/2.2.15 (Red Hat)Server at 192.168.41.135 Port 80</address>
</body></html>
<a href="http://s4.51cto.com/wyfs02/M00/79/2B/wKiom1aKYf2DuTfnAABsaD1EGqw761.jpg" target="_blank"></a>
注:此处未将135、136做同步,所以只能直接访问192.168.41.135/hosts
本文转自 chaijowin 51CTO博客,原文链接:http://blog.51cto.com/jowin/1731505,如需转载请自行联系原作者