天天看点

Linux运维 第三阶段 (七) nginx(2)

一、相关概念:

代理(你到我这请求我没有,我可以帮你去请求)

正向代理(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" &gt; 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" &gt; forum/index.html

[root@node2 html]# vim /etc/httpd/conf/httpd.conf(更改如下配置,真正实现让后端server记录的日志中是真正的client地址)

LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %&gt;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" &gt; /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" &gt; 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" &gt; /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

&lt;Directory"/var/www/html"&gt;

Dav on

&lt;/Directory&gt;

[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>

验证:上传

&lt;!DOCTYPE HTML PUBLIC "-//IETF//DTDHTML 2.0//EN"&gt;

&lt;html&gt;&lt;head&gt;

&lt;title&gt;201 Created&lt;/title&gt;

&lt;/head&gt;&lt;body&gt;

&lt;h1&gt;Created&lt;/h1&gt;

&lt;p&gt;Resource /hostshas been created.&lt;/p&gt;

&lt;hr /&gt;

&lt;address&gt;Apache/2.2.15 (Red Hat)Server at 192.168.41.135 Port 80&lt;/address&gt;

&lt;/body&gt;&lt;/html&gt;

<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,如需转载请自行联系原作者

继续阅读