Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解

来源:互联网 发布:电脑淘宝卖家中心 编辑:程序博客网 时间:2024/06/06 18:42

一、关于Nginx

nginx在启动后,在unix系统中会以daemon的方式在后台运行,后台进程包含一个master进程和多个worker进程。

master进程主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。

而基本的网络事件,则是放在worker进程中来处理了。

多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。

关于nginx,主要由3大模块,内核模块,事件模块,http核心模块。

nginx模块一般被分成三大类:handler、filter和upstream。

handler源码分析,可以去看 tengine的介绍 http://tengine.taobao.org/book/chapter_03.html
filter源码分析,可以去看 tengine的介绍 http://tengine.taobao.org/book/chapter_04.html
upstream源码分析,可以去看 tengine的介绍 http://tengine.taobao.org/book/chapter_05.html

Nginx开发从入门到精通

二、安装Nginx

1、安装yum源

rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6

2、安装nginx
① gzip 模块需要 zlib 库 ( 下载: http://www.zlib.net/zlib-1.2.8.tar.gz )
② rewrite 模块需要 pcre 库 ( 下载: http://www.pcre.org/ 下载: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.37.tar.gz)
③ ssl 功能需要 openssl 库 ( 下载: http://www.openssl.org/source/openssl-fips-2.0.12.tar.gz )
④ Nginx包下载: http://nginx.org/download/nginx-1.9.13.tar.gz
依赖包安装顺序依次为:openssl、zlib、pcre, 然后安装Nginx包.

[root@nginx ~]# yum install -y pcre-devel openssl-devel zlib-devel[root@nginx ~]# wget http://nginx.org/download/nginx-1.9.13.tar.gz[root@nginx ~]# tar -xvf nginx-1.9.13.tar.gz[root@nginx ~]#./configure --with-pcre=../pcre-8.21 --with-zlib=../zlib-1.2.7 --with-openssl=../openssl-fips-2.0.2[root@nginx ~]#make && make install

3、为nginx提供SysV init脚本
cat /etc/init.d/nginx

#!/bin/sh # # nginx - this script starts and stops the nginx daemon # # chkconfig:   - 85 15 # description:  Nginx is an HTTP(S) server, HTTP(S) reverse \ #               proxy and IMAP/POP3 proxy server # processname: nginx # config:      /etc/nginx/nginx.conf # config:      /etc/sysconfig/nginx # pidfile:     /var/run/nginx.pid # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ "$NETWORKING" = "no" ] && exit 0 nginx="/usr/sbin/nginx" prog=$(basename $nginx) NGINX_CONF_FILE="/etc/nginx/nginx.conf" [ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx lockfile=/var/lock/subsys/nginx make_dirs() {    # make required directories    user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`    options=`$nginx -V 2>&1 | grep 'configure arguments:'`    for opt in $options; do        if [ `echo $opt | grep '.*-temp-path'` ]; then            value=`echo $opt | cut -d "=" -f 2`            if [ ! -d "$value" ]; then                # echo "creating" $value                mkdir -p $value && chown -R $user $value            fi        fi    done } start() {     [ -x $nginx ] || exit 5     [ -f $NGINX_CONF_FILE ] || exit 6     make_dirs     echo -n $"Starting $prog: "     daemon $nginx -c $NGINX_CONF_FILE     retval=$?     echo     [ $retval -eq 0 ] && touch $lockfile     return $retval } stop() {     echo -n $"Stopping $prog: "     killproc $prog -QUIT     retval=$?     echo     [ $retval -eq 0 ] && rm -f $lockfile     return $retval } restart() {     configtest || return $?     stop     sleep 1     start } reload() {     configtest || return $?     echo -n $"Reloading $prog: "     killproc $nginx -HUP     RETVAL=$?     echo } force_reload() {     restart } configtest() {   $nginx -t -c $NGINX_CONF_FILE } rh_status() {     status $prog } rh_status_q() {     rh_status >/dev/null 2>&1 } case "$1" in     start)         rh_status_q && exit 0         $1         ;;     stop)         rh_status_q || exit 0         $1         ;;     restart|configtest)         $1         ;;     reload)         rh_status_q || exit 7         $1         ;;     force-reload)         force_reload         ;;     status)         rh_status         ;;     condrestart|try-restart)         rh_status_q || exit 0             ;;     *)         echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"         exit 2 esac

4、为此脚本赋予执行权限,添加至服务管理列表,并让其开机自动启动

[root@nginx ~]# chmod +x /etc/init.d/nginx[root@nginx ~]# chkconfig --add nginx[root@nginx ~]# chkconfig nginx on

5、启动nginx,并用浏览器访问 htpp://192.168.1.22, 即主机ip, 如果有欢迎进入nginx则说明nginx配置安装成功, 否则可能需要关闭防火墙。

[root@nginx ~]# service nginx start 

6、关闭防火墙

[root@nginx ~]# service iptables stop[root@nginx ~]# chkconfig iptables off [root@nginx ~]# getenforce 

三、nginx.conf 配置文件

Nginx 配置文件主要分成四部分:main(全局设置)、http(HTTP 的通用设置)、server(虚拟主机设置)、location(匹配 URL 路径)。还有一些其他的配置段,如 event,upstream 等。

通用设置说明

user nginx #指定运行 nginx workre 进程的用户和组
worker_rlimit_nofile #指定所有 worker 进程能够打开的最大文件数
worker_cpu_affinity #设置 worker 进程的 CPU 粘性,以避免进程在 CPU 间切换带来的性能消耗.如 worker_cpu_affinity 0001 0010 0100 1000;(四核)
worker_processes 4 #worker 工作进程的个数,这个值可以设置为与 CPU 数量相同,如果开启了 SSL 和 Gzip,那么可以适当增加此数值
worker_connections 1000 #单个 worker 进程能接受的最大并发连接数,放在 event 段中
error_log logs/error.log info #错误日志的存放路径和记录级别
use epoll #使用 epoll 事件模型,放在 event 段中

server 配置示例

# server {}: 定义一个虚拟主机server { # 定义监听的地址和端口,默认监听在本机所有地址上 listen  80; # 定义虚拟主机名,可以使用多个名称,还可以使用正则表达式或通配符。 server_name www.example.com; # 开启 sendfile 调用来快速的响应客户端 sendfile on # 长连接超时时间,单位是秒。 keepalive_timeout 65 # 指定响应客户端的超时时间 send_timeout # 允许客户端请求的实体最大大小 client_max_body_size 10m # 设置请求 URL 所对应资源所在文件系统上的根目录 root /web/htdocs; # location [ = | ~ | ~* | ^~ ] URI { ... } # 设置一个 URI 匹配路径 # =:精确匹配 # ~:正则表达式匹配,区分字符大小写 # ~*:正则表达式匹配,不区分字符大小写 # ^~:URI 的前半部分匹配,且不实用正则表达式 # 优先级:= > location 完整路径 > ^~ > ~ > ~* > location 起始路径 > location / location / {  index index.html index.htm; } location /status {  stub_status on;  # 基于 IP 访问控制: allow 和 deny, 允许10.0.0.0网段客户进行访问  allow 10.0.0.0/8;  # 拒绝其他所有网段进行访问  deny all;  # 访问日志是否开启  access_log off;  # 重定向: rewrite <REGEX> <REPL> <FLAG>  # 可用的 flag:  # - last:重写完成后,继续匹配其他 rewrite 规则  # - break:重写完成后不再继续匹配  # - redirect:返回 302 重定向(临时重定向),客户端对重定向的 URL 发起新的请求  # - permanent:返回 301 重定向(永久重定向),客户端对重定向的 URL 发起新的请求  rewrite  ^(/status/.*)/media/(.*)\..*$  $1/mp3/$2.mp3  last; }

四、nginx配置ssl

server {  listen 443;  server_name example.com;  root /apps/www;  index index.html index.htm;  ssl on;  # ssl_certificate 表示 CA 文件  ssl_certificate /etc/nginx/ssl/nginx.crt;  # 表示密钥文件  ssl_certificate_key /etc/nginx/ssl/nginx.key;#  ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;#  ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;#  ssl_prefer_server_ciphers on;}

五、nginx防盗图配置

防盗图主要是针对定向的路径,当用户访问该路径,检测域名,如果域名不对,重定向。

location ~ \/public\/(css|js|img)\/.*\.(js|css|gif|jpg|jpeg|png|bmp|swf) {    valid_referers none blocked *.homeway.me;    if ($invalid_referer) {            rewrite ^/  http://xiaocao.u.qiniudn.com/blog%2Fpiratesp.png;    }}

六、Nginx之反向代理

关于反向代理和正向代理的说明请阅读:http://blog.csdn.net/xlxxcc/article/details/52640432
在配置nginx反向代理之间我们得先准备两台测试服务器,Web1与Web2。
注意:每次修改配置,需要重新加载配置或者重新启动。

# 重启apacheservice httpd restart# 重新加载nginx配置service nginx reload

1、安装httpd

[root@web1 ~]# yum install -y httpd[root@web2 ~]# yum install -y httpd

2、提供测试页面

[root@web1 ~]# echo "<h1>web1.test.com</h1>" > /var/www/html/index.html[root@web2 ~]# echo "<h1>web2.test.com</h1>" > /var/www/html/index.html

3、启动httpd服

 [root@web1 ~]# service httpd start  [root@web2 ~]# service httpd start 

4、浏览器访问 http://localhost/, 浏览器显示web1.test.com和web2.test.com说明正常。

5、nginx 代理模块 : proxy_pass ,
注意,当使用http proxy模块(甚至FastCGI),所有的连接请求在发送到后端服务器之前nginx将缓存它们,因此,在测量从后端传送的数据时,它的进度显示可能不正确。
配置http反向代理:

location / {  # 这个指令设置被代理服务器的地址和被映射的URI,地址可以使用主机名或IP加端口号的形式  proxy_pass        http://192.168.1.12;  proxy_set_header  X-Real-IP  $remote_addr;}

6、浏览器访问代理主机,会发现跳转达到192.168.1.12, 显示web1.test.com
7、查看web1的访问日志: tail /var/log/httpd/access_log可以看到我们这里的客户的IP全是,nginx代理服务器的IP,并不是真实客户端的IP。下面我们修改一下,让日志的IP显示真实的客户端的IP。

location / {        proxy_pass      http://192.168.18.201;        # 记录访问用户真实ip        proxy_set_header  X-Real-IP  $remote_addr; #加上这一行}

8、还需要配置被代理的apache配置: vim /etc/httpd/conf/httpd.conf, 才能在apache的访问日志中。 这里写图片描述
改成:
这里写图片描述
注,这是修改后的参数,将h%修改为%{X-Real-IP}i,好的下面我们再来测试一下。

好了,到这里Nginx代理后端一台服务器,看到日志里记录的IP地址就是真实的客户端地址了。

七、Nginx之负载均衡

1.upstream 负载均衡模块说明,示例:

upstream test.net{ip_hash;server 192.168.10.13:80;server 192.168.10.14:80  down;server 192.168.10.15:8009  max_fails=3  fail_timeout=20s;server 192.168.10.16:8080;}server {  location / {    proxy_pass  http://test.net;  }}

2、upstream的几种调度方式和示例,请查阅:http://blog.csdn.net/xlxxcc/article/details/52641063

3、.配置nginx负载均衡, vim /etc/nginx/nginx.conf

upstream webservers {      server 192.168.1.12 weight=1;      server 192.168.1.13 weight=1;  }  server {      listen       80;      server_name  localhost;      #charset koi8-r;      #access_log  logs/host.access.log  main;      location / {              # 此处不可少, 指向上面的均衡负载配置              proxy_pass      http://webservers;              proxy_set_header  X-Real-IP  $remote_addr;      }}

4、重新加载nginx配置

service nginx reload

5、浏览器访问代理主机,会发现浏览器偶尔显示web1.test.com, 偶尔显示web2.test.com。两者交替出现,说明达到了负载均衡的效果。

6、配置nginx进行健康状态检查

upstream webservers {        #max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。        server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;        # fail_timeout,在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用,进行健康状态检查。        server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;    } 

7、配置backup服务器, 应对所有服务器都不能提供服务

[root@nginx ~]# vim /etc/nginx/nginx.conf upstream webservers {        server 192.168.18.201 weight=1 max_fails=2 fail_timeout=2;        server 192.168.18.202 weight=1 max_fails=2 fail_timeout=2;        server 127.0.0.1:8080 backup;    } [root@nginx ~]# mkdir -pv /data/www/errorpage[root@nginx errorpage]# cat index.html<h1>Sorry......</h1> 

8、关闭web1和web2,浏览器访问服务器,会发现浏览器显示 Sorry……

八、Nginx之页面缓存

1、页面缓存指令说明,请查阅:http://blog.csdn.net/xlxxcc/article/details/52641496
2、定义一个简单nginx缓存服务器,

[root@nginx ~]# vim /etc/nginx/nginx.confproxy_cache_path /data/nginx/cache/webserver levels=1:2 keys_zone=webserver:20m max_size=1g;   server {       listen       80;       server_name  localhost;       #charset koi8-r;       #access_log  logs/host.access.log  main;       location / {               proxy_pass      http://webservers;               proxy_set_header  X-Real-IP  $remote_addr;               proxy_cache webserver;               proxy_cache_valid 200 10m;       }}

3、新建缓存目录, 并重新加载配置文件

[root@nginx ~]# mkdir -pv /data/nginx/cache/webserver

4、配置$server_addr和$upstream_cache_status缓存变量
$server_addr: 服务器地址,在完成一次系统调用后可以确定这个值,如果要绕开系统调用,则必须在listen中指定地址并且使用bind参数。
$upstream_cache_status: 其值可能为:

  • MISS 未命中
  • EXPIRED - expired。请求被传送到后端。
  • UPDATING - expired。由于proxy/fastcgi_cache_use_stale正在更新,将使用旧的应答。
  • STALE - expired。由于proxy/fastcgi_cache_use_stale,后端将得到过期的应答。
  • HIT 命中
[root@nginx ~]# vim /etc/nginx/nginx.confproxy_cache_path /data/nginx/cache/webserver levels=1:2 keys_zone=webserver:20m max_size=1g;    server {        listen       80;        server_name  localhost;        #charset koi8-r;        #access_log  logs/host.access.log  main;       #增加两头部        add_header X-Via $server_addr;        add_header X-Cache $upstream_cache_status;        location / {                proxy_pass      http://webservers;                proxy_set_header  X-Real-IP  $remote_addr;                proxy_cache webserver;                proxy_cache_valid 200 10m;        }}

5、重新加载配置文件

 [root@nginx ~]# service nginx reload 

6、谷歌浏览器访问服务,点击F12 -> Network, 查看Response Headers, 我们可以看到X-Cache: HIT, 说明访问的服务器是缓存命中。

7、查看缓存目录

[root@nginx ~]# cd /data/nginx/cache/webserver/f/63/[root@nginx 63]# ls681ad4c77694b65d61c9985553a2763f

注,缓存目录里确实有缓存文件。好了,nginx缓存配置就到这边了,更多配置请根据需要看配置文档。

九、Nginx之URL重写

1、Nginx Rewrite 指令说明,请查阅:http://blog.csdn.net/xlxxcc/article/details/52641293
2、简单案例
注,由于配置文件内容较多,为了让大家看着方便,我们备份一下配置文件,打开一个新的配置文件。

[root@nginx ~]# cd /etc/nginx/[root@nginx nginx]# mv nginx.conf nginx.conf.proxy[root@nginx nginx]# cp nginx.conf.bak nginx.conf[root@nginx nginx]# vim /etc/nginx/nginx.confserver {      listen       80;      server_name  localhost;      #charset koi8-r;      #access_log  logs/host.access.log  main;      location / {          root   html;          index  index.html index.htm;          rewrite ^/bbs/(.*)$ http://192.168.1.12/forum/$1;      }}

[root@nginx ]# service nginx reload
web1 准备forum目录与测试文件

[root@web1 ~]# cd /var/www/html/[root@web1 html]# lsindex.html[root@web1 html]# mkdir forum[root@web1 html]# cd forum/[root@web1 forum]# vim index.html<h1>forum page!</h1>

3、浏览测试一下, 显示 forum page! 谷歌浏览器打开F12 -> Network -> Headers,可以看到status code 302指的是临时重定向,那就说明我们rewrite重写配置成功。大家知道302是临时重定向而301是永久重定向,那么怎么实现永久重定向呢。一般服务器与服务器之间是临时重定向,服务器内部是永久重定向。下面我们来演示一下永久重定向。

4、配置永久重定向

[root@nginx nginx]# vim /etc/nginx/nginx.confserver {        listen       80;        server_name  localhost;        #charset koi8-r;        #access_log  logs/host.access.log  main;        location / {            root   html;            index  index.html index.htm;            rewrite ^/bbs/(.*)$ /forum/$1;        }}

准备forum目录与测试文件

[root@nginx ~]# cd /usr/html/[root@nginx html]# ls50x.html  index.html[root@nginx html]# mkdir forum[root@nginx html]# cd forum/[root@nginx forum]# vim index.html<h1>192.168.18.208 forum page</h1>

5.重新加载一下配置文件

 [root@nginx ~]# service nginx reload 

6、测试一下,谷歌浏览器打开F12 -> Network -> Headers,我们访问bbs/是直接帮我们跳转到forum/下,这种本机的跳转就是永久重定向也叫隐式重定向。好了,rewrite重定向我们就说到这里了,想要查询更多关于重定向的指令请参考官方文档。

十、Nginx之URL重写

1、实验拓扑
需求分析,前端一台nginx做负载均衡反向代理,后面两台httpd服务器。整个架构是提供BBS(论坛)服务,有一需求得实现读写分离,就是上传附件的功能,我们上传的附件只能上传到Web1,然后在Web1上利用rsync+inotify实现附件同步,大家都知道rsync+inotify只能是主向从同步,不能双向同步。所以Web1可进行写操作,而Web2只能进行读操作,这就带来读写分离的需求,下面我们就来说一下,读写分离怎么实现。

2、WebDAV功能说明
WebDAV (Web-based Distributed Authoring and Versioning) 一种基于 HTTP 1.1协议的通信协议。它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。这样我们就能配置读写分离功能了,下面我们来具体配置一下。

3、修改配置文件

[root@nginx nginx]# vim /etc/nginx/nginx.confserver {        listen       80;        server_name  localhost;        #charset koi8-r;        #access_log  logs/host.access.log  main;        location / {                proxy_pass http://192.168.18.202;                if ($request_method = "PUT"){                        proxy_pass http://192.168.18.201;                }        }}

4、重新加载一下配置文件

 [root@nginx ~]# service nginx reload 

5、配置httpd的WebDAV功能

[root@web1 ~]# vim /etc/httpd/conf/httpd.conf<Directory "/var/www/html">Dav on....</Directory>

6、重新启动一下httpd

[root@web1 ~]# service httpd restart 

7、测试一下

[root@nginx ~]# curl http://192.168.18.201<h1>web1.test.com</h1>[root@nginx ~]# curl http://192.168.18.202<h1>web2.test.com</h1>

注,web1与web2访问都没问题。

[root@nginx ~]# curl -T /etc/issue  http://192.168.18.202<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>405 Method Not Allowed</title></head><body><h1>Method Not Allowed</h1>The requested method PUT is not allowed for the URL /issue.<hr><address>Apache/2.2.15 (CentOS) Server at 192.168.18.202 Port 80</address></body></html>

注,我们上传文件到,web2上时,因为web2只人读功能,所以没有开户WebDAV功能,所以显示是405 Method Not Allowed。

 [root@nginx ~]# curl -T /etc/issue  http://192.168.18.201<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>403 Forbidden</title></head><body><h1>Forbidden</h1>You don't have permission to access /issueon this server.<hr><address>Apache/2.2

注,我们在Web1开启了WebDAV功能,但我们目录是root目录是不允许apache用户上传的,所以显示的是403 Forbidden。下面我们给apache授权,允许上传。

[root@web1 ~]# setfacl -m u:apache:rwx /var/www/html/

下面我们再来测试一下,

[root@nginx ~]# curl -T /etc/issue  http://192.168.18.201<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>201 Created</title></head><body><h1>Created</h1>Resource /issue has been created.<hr /><address>Apache/2.2.15 (CentOS) Server at 192.168.18.201 Port 80</address></body></html>

注,大家可以看到我们成功的上传了文件,说明nginx读写分离功能配置完成。最后,我们来查看一下上传的文件。

[root@web1 ~]# cd /var/www/html/[root@web1 html]# ll总用量 12drwxr-xr-x 2 root   root   4096 94 13:16 forum-rw-r--r-- 1 root   root     23 93 23:37 index.html-rw-r--r-- 1 apache apache   47 94 14:06 issue

好了,到这里nginx的反向代理、负载均衡、页面缓存、URL重写及读写分离就全部讲解完成。希望大家有所收获,^_^……

原文出自:陈明乾 的BLOG
原文出处:http://freeloda.blog.51cto.com/2033581/1288553

0 0
原创粉丝点击