nginx配置详解(虚拟主机、负载均衡和反向代理)

今天终于整理一下nginx的配置!

请参考:https://www.zybuluo.com/phper/note/89391

https://yq.aliyun.com/articles/47359


Nginx配置文件主要分成六部分:

main(全局设置)、

events(nginx工作模式)

http(http设置)、

server(主机设置)、

upstream(上游服务器设置,主要为反向代理、负载均衡相关配置)

location(URL匹配特定位置后的设置),每部分包含若干个指令

 
 
  1. main
  2. events {
  3. ....
  4. }
  5. http {
  6. ....
  7. upstream myproject {
  8. .....
  9. }
  10. server {
  11. ....
  12. location {
  13. ....
  14. }
  15. }
  16. server {
  17. ....
  18. location {
  19. ....
  20. }
  21. }
  22. ....
  23. }

main模块

下面时一个main区域,他是一个全局的设置:

 
 
  1. user nobody nobody;
  2. worker_processes 2;
  3. error_log /usr/local/var/log/nginx/error.log notice;
  4. pid /usr/local/var/run/nginx/nginx.pid;
  5. worker_rlimit_nofile 1024;

user   来指定Nginx Worker进程运行用户以及用户组,默认由nobody账号运行。

worker_processes  来指定了Nginx要开启的子进程数。每个Nginx进程平均耗费10M~12M内存。我这里写2,那么就会开启2个子进程,总共3个进程。这个数值简单一点可以设置为cpu的核数grep ^processor /proc/cpuinfo | wc -l,也是 auto 值,如果开启了ssl和gzip更应该设置成与逻辑CPU数量一样甚至为2倍,可以减少I/O操作。如果nginx服务器还有其它服务,可以考虑适当减少。

error_log  用来定义全局错误日志文件。日志输出级别有debug、info、notice、warn、error、crit可供选择,其中,debug输出日志最为最详细,而crit输出日志最少。

pid  用来指定进程id的存储文件位置。

worker_rlimit_nofile  用于指定一个nginx进程可以打开的最多文件描述符数目,这里是65535,需要使用命令“ulimit -n 65535”来设置。


events 模块

events模块来用指定nginx的工作模式和工作模式及连接数上限,一般是这样:

 
 
  1. events {
  2. use kqueue; #mac平台
  3. worker_connections 1024;
  4. }

use  用来指定Nginx的工作模式。Nginx支持的工作模式有select、poll、kqueue、epoll、rtsig和/dev/poll。其中select和poll都是标准的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用在Linux平台上,而kqueue用在BSD系统中,因为Mac基于BSD,所以Mac也得用这个模式,对于Linux系统,epoll工作模式是首选。

worker_connections  用于定义Nginx每个进程的最大连接数,即接收前端的最大请求数,默认是1024。最大客户端连接数由worker_processesworker_connections决定,即Max_clients=worker_processes*worker_connections,在作为反向代理时,Max_clients变为:Max_clients = worker_processes * worker_connections/4
进程的最大连接数受Linux系统进程的最大打开文件数限制,在执行操作系统命令“ulimit -n 65536”后worker_connections的设置才能生效


http 模块

http模块可以说是最核心的模块了,它负责HTTP服务器相关属性的配置,它里面的server和upstream子模块,至关重要,等到反向代理和负载均衡以及虚拟目录等会仔细说。

 
 
  1. http{
  2. include mime.types;
  3. default_type application/octet-stream;
  4. log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  5. '$status $body_bytes_sent "$http_referer" '
  6. '"$http_user_agent" "$http_x_forwarded_for"';
  7. access_log /usr/local/var/log/nginx/access.log main;
  8. sendfile on;
  9. tcp_nopush on;
  10. tcp_nodelay on;
  11. keepalive_timeout 10;
  12. #gzip on;
  13. upstream myproject {
  14. .....
  15. }
  16. server {
  17. ....
  18. }
  19. }

下面详细介绍下这段代码中每个配置选项的含义。
include   来用设定文件的mime类型,类型在配置文件目录下的mime.type文件定义,来告诉nginx来识别文件类型。

default_type  设定了默认的类型为二进制流,也就是当文件类型未定义时使用这种方式,例如在没有配置asp 的locate 环境时,Nginx是不予解析的,此时,用浏览器访问asp文件就会出现下载了。

log_format  用于设置日志的格式,和记录哪些参数,这里设置为main,刚好用于access_log来纪录这种类型。


main 的类型日志如下:也可以增删部分参数。

127.0.0.1 - - [21/Apr/2015:18:09:54 +0800] "GET /index.php HTTP/1.1" 200 87151 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36"

access_log   用来纪录每次的访问日志的文件地址,后面的main是日志的格式样式,对应于log_formatmain

sendfile  参数用于开启高效文件传输模式。将tcp_nopush和tcp_nodelay两个指令设置为on用于防止网络阻塞。

keepalive_timeout  长连接超时时间,单位是秒,这个参数很敏感,涉及浏览器的种类、后端服务器的超时设置、操作系统的设置,可以另外起一片文章了。长连接请求大量小文件的时候,可以减少重建连接的开销,但假如有大文件上传,65s内没上传完成会导致失败。如果设置时间过长,用户又多,长时间保持连接会占用大量资源。send_timeout  用于指定响应客户端的超时时间。这个超时仅限于两个连接活动之间的时间,如果超过这个时间,客户端没有任何活动,Nginx将会关闭连接。client_max_body_size 10m 允许客户端请求的最大单文件字节数。如果有上传较大文件,请设置它的限制值

client_body_buffer_size 128k 缓冲区代理缓冲用户端请求的最大字节数

还有很多各种配置,以后等用到来再说。


模块http_proxy:
这个模块实现的是nginx作为反向代理服务器的功能,包括缓存功能(另见文章

  • proxy_connect_timeout 60
    nginx跟后端服务器连接超时时间(代理连接超时)
  • proxy_read_timeout 60
    连接成功后,与后端服务器两个成功的响应操作之间超时时间(代理接收超时)

  • proxy_buffer_size 4k
    设置代理服务器(nginx)从后端realserver读取并保存用户信息的缓冲区大小,默认与proxy_buffers大小相同,其实可以将这个指令值设的小一点

  • proxy_buffers 4 32k
    proxy_buffers缓冲区,nginx针对单个连接缓存来自后端realserver的响应,网页平均在32k以下的话,这样设置

  • proxy_busy_buffers_size 64k
    高负荷下缓冲大小(proxy_buffers*2)

  • proxy_max_temp_file_size
    当proxy_buffers放不下后端服务器的响应内容时,会将一部分保存到硬盘的临时文件中,这个值用来设置最大临时文件大小,默认1024M,它与proxy_cache没有关系。大于这个值,将从upstream服务器传回。设置为0禁用。

  • proxy_temp_file_write_size 64k
    当缓存被代理的服务器响应到临时文件时,这个选项限制每次写临时文件的大小。proxy_temp_path(可以在编译的时候)指定写到哪那个目录。

proxy_pass,proxy_redirect见 location 部分。

模块http_gzip:

  • gzip on : 开启gzip压缩输出,减少网络传输。

    • gzip_min_length 1k : 设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。默认值是20。建议设置成大于1k的字节数,小于1k可能会越压越大。
    • gzip_buffers 4 16k : 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。4 16k代表以16k为单位,安装原始数据大小以16k为单位的4倍申请内存。
    • gzip_http_version 1.0 : 用于识别 http 协议的版本,早期的浏览器不支持 Gzip 压缩,用户就会看到乱码,所以为了支持前期版本加上了这个选项,如果你用了 Nginx 的反向代理并期望也启用 Gzip 压缩的话,由于末端通信是 http/1.0,故请设置为 1.0。
    • gzip_comp_level 6 : gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)
    • gzip_types :匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的。
    • gzip_proxied any : Nginx作为反向代理的时候启用,决定开启或者关闭后端服务器返回的结果是否压缩,匹配的前提是后端服务器必须要返回包含”Via”的 header头。
    • gzip_vary on : 和http头有关系,会在响应头加个 Vary: Accept-Encoding ,可以让前端的缓存服务器缓存经过gzip压缩的页面,例如,用Squid缓存经过Nginx压缩的数据。。

server 模块

sever 模块是http的子模块,它用来定一个虚拟主机,我们先讲最基本的配置,这些在后面再讲。

我们看一下一个简单的server 是如何做的?

 
 
  1. server {
  2. listen 8080;
  3. server_name localhost 192.168.12.10 www.yangyi.com;
  4. # 全局定义,如果都是这一个目录,这样定义最简单。
  5. root /Users/yangyi/www;
  6. index index.php index.html index.htm;
  7. charset utf-8;
  8. access_log usr/local/var/log/host.access.log main;
  9. aerror_log usr/local/var/log/host.error.log error;
  10. ....
  11. }

server  标志定义虚拟主机开始。
listen  用于指定虚拟主机的服务端口。
server_name  用来指定IP地址或者域名,多个域名之间用空格分开。
root  表示在这整个server虚拟主机内,全部的root web根目录。注意要和locate {}下面定义的区分开来。
index   全局定义访问的默认首页地址。注意要和locate {}下面定义的区分开来。
charset  用于设置网页的默认编码格式。
access_log  用来指定此虚拟主机的访问日志存放路径,最后的main用于指定访问日志的输出格式。


location 模块

location模块是nginx中用的最多的,也是最重要的模块了,什么负载均衡啊、反向代理啊、虚拟域名啊都与它相关。慢慢来讲:

location 根据它字面意思就知道是来定位的,定位URL,解析URL,所以,它也提供了强大的正则匹配功能,也支持条件判断匹配,用户可以通过location指令实现Nginx对动、静态网页进行过滤处理。像我们的php环境搭建就是用到了它。

我们先来看这个,设定默认首页和虚拟机目录。

 
 
  1. location / {
  2. root /Users/yangyi/www;
  3. index index.php index.html index.htm;
  4. }

location /表示匹配访问根目录。

root  定义服务器的默认网站根目录位置。指令用于指定访问根目录时,虚拟主机的web目录,这个目录可以是相对路径(相对路径是相对于nginx的安装目录)。也可以是绝对路径。

index  用于设定我们只输入域名后访问的默认首页地址,有个先后顺序:index.php index.html index.htm,如果没有开启目录浏览权限,又找不到这些默认首页,就会报403错误。

location  还有一种方式就是正则匹配,开启正则匹配这样:location ~。后面加个~

下面这个例子是运用正则匹配来链接php。我们之前搭建环境也是这样做:

 
 
  1. location ~ \.php$ {
  2. root /Users/yangyi/www;
  3. fastcgi_pass 127.0.0.1:9000;
  4. fastcgi_index index.php;
  5. include fastcgi.conf;
  6. }

\.php$ 熟悉正则的我们直到,这是匹配.php结尾的URL,用来解析php文件。里面的root也是一样,用来表示虚拟主机的根目录。
fast_pass  链接的是php-fpm 的地址,之前我们也搭建过。其他几个参数我们以后再说。

location 还有其他用法,等讲到实例的时候,再看吧。


  • proxy_pass http:/backend
    请求转向backend定义的服务器列表,即反向代理,对应upstream负载均衡器。也可以proxy_pass http://ip:port

  • proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    这四个暂且这样设,如果深究的话,每一个都涉及到很复杂的内容,也将通过另一篇文章来解读。

关于location匹配规则的写法,可以说尤为关键且基础的,参考文章 nginx配置location总结及rewrite规则写法;

upstram 模块

upstream 模块负债负载均衡模块,通过一个简单的调度算法来实现客户端IP到后端服务器的负载均衡。我先学习怎么用,具体的使用实例以后再说。

 
 
  1. upstream iyangyi.com{
  2. ip_hash;
  3. server 192.168.12.1:80;
  4. server 192.168.12.2:80 down;
  5. server 192.168.12.3:8080 max_fails=3 fail_timeout=20s;
  6. server 192.168.12.4:8080;
  7. }

在上面的例子中,通过upstream指令指定了一个负载均衡器的名称iyangyi.com。这个名称可以任意指定,在后面需要的地方直接调用即可。

里面是ip_hash这是其中的一种负载均衡调度算法,下面会着重介绍。紧接着就是各种服务器了。用server关键字表识,后面接ip。

Nginx的负载均衡模块目前支持4种调度算法:

  1. weight 轮询(默认)。每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。weight。指定轮询权值,weight值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况下。
  2. ip_hash。每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。
  3. fair。比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块。
  4. url_hash。按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx 的hash软件包。

在HTTP Upstream模块中,可以通过server指令指定后端服务器的IP地址和端口,同时还可以设定每个后端服务器在负载均衡调度中的状态。常用的状态有:

  • down,表示当前的server暂时不参与负载均衡。
  • backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
  • max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
  • fail_timeout,在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用。

注意 当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup。


其它

访问控制 allow/deny

Nginx 的访问控制模块默认就会安装,而且写法也非常简单,可以分别有多个allow,deny,允许或禁止某个ip或ip段访问,依次满足任何一个规则就停止往下匹配。如:

location /nginx-status {
  stub_status on;
  access_log off;
#  auth_basic   "NginxStatus";
#  auth_basic_user_file   /usr/local/nginx-1.6/htpasswd;

  allow 192.168.10.100;
  allow 172.29.73.0/24;
  deny all;
}

我们也常用 httpd-devel 工具的 htpasswd 来为访问的路径设置登录密码:

# htpasswd -c htpasswd admin
New passwd:
Re-type new password:
Adding password for user admin

# htpasswd htpasswd admin    //修改admin密码
# htpasswd htpasswd sean    //多添加一个认证用户

这样就生成了默认使用CRYPT加密的密码文件。打开上面nginx-status的两行注释,重启nginx生效。

列出目录 autoindex

Nginx默认是不允许列出整个目录的。如需此功能,打开nginx.conf文件,在location,server 或 http段中加入autoindex on;,另外两个参数最好也加上去:

  • autoindex_exact_size off; 默认为on,显示出文件的确切大小,单位是bytes。改为off后,显示出文件的大概大小,单位是kB或者MB或者GB
  • autoindex_localtime on;
    默认为off,显示的文件时间为GMT时间。改为on后,显示的文件时间为文件的服务器时间
location /images {root /var/www/nginx-default/images;autoindexon; autoindex_exact_sizeoff;autoindex_localtime on; }

参考文件:
http://blog.csdn.net/xifeijian/article/details/20956605
http://www.360doc.com/content/13/1114/12/7694408_329125489.shtml
http://www.cnblogs.com/xiaogangqq123/archive/2011/03/02/1969006.html
http://ixdba.blog.51cto.com/2895551/790611
http://freeloda.blog.51cto.com/2033581/1288553



就来几个实际的例子来看下虚拟主机、负债均衡和反向代理,是如何做到的。

1. 基于域名的虚拟主机

在apache上搭建基于域名的虚拟主机很简单,我之前也写过一篇,来讲述如何搭建。在nginx上搭建也不难。

假设我们在本地开发有3个项目,分别在hosts里映射到本地的127.0.0.1上:

127.0.0.1 www.iyangyi.com iyangyi.com
127.0.0.1 api.iyangyi.com
127.0.0.1 admin.iyangyi.com

有这样3个项目,分别对应于web根目录下的3个文件夹,我们用域名对应文件夹名字,这样子好记:

/Users/yangyi/www/www.iyangyi.com/
/Users/yangyi/www/api.iyangyi.com/
/Users/yangyi/www/admin.iyangyi.com/

每个目录下都有一个index.php文件,都素简单的输入自己的域名。

下面我们就来搭建这3个域名的虚拟主机,很显然,我们要新建3个server来完成。为了看起来简洁好看,我们使用require来包含外面的3个servernginx.conf中,这样就清晰了很多。不会使得这个nginx.conf内容太多:

 
 
  1. main
  2. events {
  3. ....
  4. }
  5. http {
  6. ....
  7. include vhost/www.iyangyi.conf;
  8. include vhost/api.iyangyi.conf;
  9. include vhost/admin.iyangyi.conf;
  10. #或者用 *.conf 包含
  11. # include vhost/*.conf
  12. }

既然每一个conf都是一个server,前面已经学习了一个完整的server写的了。下面就开始:

 
 
  1. # www.iyangyi.conf
  2. server {
  3. listen 80;
  4. server_name www.iyangyi.com iyangyi.com;
  5. root /Users/yangyi/www/www.iyangyi.com/;
  6. index index.php index.html index.htm;
  7. access_log /usr/local/var/log/nginx/www.iyangyi.access.log main;
  8. error_log /usr/local/var/log/nginx/www.iyangyi.error.log error;
  9. location ~ \.php$ {
  10. fastcgi_pass 127.0.0.1:9000;
  11. fastcgi_index index.php;
  12. include fastcgi.conf;
  13. }
  14. }
 
 
  1. # api.iyangyi.conf
  2. server {
  3. listen 80;
  4. server_name api.iyangyi.com;
  5. root /Users/yangyi/www/api.iyangyi.com/;
  6. index index.php index.html index.htm;
  7. access_log /usr/local/var/log/nginx/api.iyangyi.access.log main;
  8. error_log /usr/local/var/log/nginx/api.iyangyi.error.log error;
  9. location ~ \.php$ {
  10. fastcgi_pass 127.0.0.1:9000;
  11. fastcgi_index index.php;
  12. include fastcgi.conf;
  13. }
  14. }
 
 
  1. # admin.iyangyi.conf
  2. server {
  3. listen 80;
  4. server_name admin.iyangyi.com;
  5. root /Users/yangyi/www/admin.iyangyi.com/;
  6. index index.php index.html index.htm;
  7. access_log /usr/local/var/log/nginx/admin.iyangyi.access.log main;
  8. error_log /usr/local/var/log/nginx/admin.iyangyi.error.log error;
  9. location ~ \.php$ {
  10. fastcgi_pass 127.0.0.1:9000;
  11. fastcgi_index index.php;
  12. include fastcgi.conf;
  13. }
  14. }

这样3个很精简的虚拟域名就搭建好了。重启下nginx,然后打开浏览器访问一下这3个域名,就能看到对应的域名内容了。

2.反向代理

正向代理

在说啥啥反向代理之前,先说下什么是代理或者正向代理

正向代理也就是代理,他的工作原理就像一个跳板,简单的说,我访问不了google.com,但是我能访问一个代理服务器A,A能访问google.com,于是我先连上代理服务器A,告诉他我需要google.com的内容,A就去取回来,然后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。

结论就是,正向代理是一个位于客户端原始服务器(origin server)之间的服务器。为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。

目前代理软件很多,浏览器上的代理就更多了。什么自由门啊,红杏等。

反向代理

ok,说完正向代理,再来说啥是反向代理

举个例子,比如我想访问 http://www.test.com/readme,但www.test.com上并不存在readme页面,于是他是偷偷从另外一台服务器上取回来,然后作为自己的内容返回用户,但用户并不知情。这里所提到的 www.test.com 这个域名对应的服务器就设置了反向代理功能

结论就是,反向代理正好相反,对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样。

嗯。正向代理和反向代理就基本清楚了,那我们就来用nginx来配置一个反向代理。

nginx 使用反向代理,主要是使用location模块下的proxy_pass选项。

我们直接实战吧!

来个最简单的。当我访问 mac 上的nginx 的 centos.iyangyi.com 的内容时候, 就反向代理到虚拟机centos上的 apache 192.168.33.10 的index.html页面。

192.168.33.10 中的html 是很简单的一句输出:

centos apache2 index.html

在hosts里新加上这个域名。

#vi /etc/hosts 
127.0.0.1 centos.iyangyi.com

在vhost目录中新建一个conf server

 
 
  1. #centos.iyangyi.conf
  2. server {
  3. listen 80;
  4. server_name centos.iyangyi.com;
  5. access_log /usr/local/var/log/nginx/centos.iyangyi.access.log main;
  6. error_log /usr/local/var/log/nginx/centos.iyangyi.error.log error;
  7. location / {
  8. proxy_pass http://192.168.33.10;
  9. }
  10. }

重启下nginx:

sudo nginx -s reload

打开浏览器,就可以看到页面输出了:

centos apache2 index.html

当然。proxy 还有其他的参数,比如:proxy_set_header 用来设置header头部信息参数转发等,等用了可以仔细看看。

3.负载均衡

别被这个名字给吓住了,以为是什么很牛逼的东西的。其实不然。也很简单。

先简单说下负载均衡是干嘛的?举个例子:我们的小网站,刚开始就一台nginx服务器,后来,随着业务量增大,用户增多,一台服务器已经不够用了,我们就又多加了几台服务器。那么这几台服务器如何调度?如何均匀的提供访问?这就是负载均衡。

负载均衡的好处是可以集群多台机器一起工作,并且对外的IP 和 域名是一样的,外界看起来就好像一台机器一样。

nginx 也刚好提供了强大而又简单的负载均衡功能。

在第一节中,我详细讲了nginx的负载均衡模块upstream,负载均衡呢,主要是用这个模块。

我们先用vagrant搭建一个centos虚拟机集群(附vagrantfile文件)

 
 
  1. Vagrant.configure(2) do |config|
  2. config.vm.define :web1 do |web1|
  3. web1.vm.provider "virtualbox" do |v|
  4. v.customize ["modifyvm", :id, "--name", "web1", "--memory", "128"]
  5. end
  6. web1.vm.box = "centos65"
  7. web1.vm.hostname = "web1"
  8. web1.vm.network :private_network, ip: "192.168.33.11"
  9. end
  10. config.vm.define :web2 do |web2|
  11. web2.vm.provider "virtualbox" do |v|
  12. v.customize ["modifyvm", :id, "--name", "web2", "--memory", "128"]
  13. end
  14. web2.vm.box = "centos65"
  15. web2.vm.hostname = "web2"
  16. web2.vm.network :private_network, ip: "192.168.33.12"
  17. end
  18. config.vm.define :web3 do |web3|
  19. web3.vm.provider "virtualbox" do |v|
  20. v.customize ["modifyvm", :id, "--name", "web3", "--memory", "128"]
  21. end
  22. web3.vm.box = "centos65"
  23. web3.vm.hostname = "web3"
  24. web3.vm.network :private_network, ip: "192.168.33.13"
  25. end
  26. end

分别配置静态ip并且取名字:

web1 192.168.33.11
web2 192.168.33.12
web3 192.168.33.13

然后,我们分别启动vagrant ssh web1,web2,web3,并且分别用yum简单安装好apache。并在www目录里面新建index.html,分别输出一句简单的web1web2web3

好,这个时候,我们在浏览器里输入对应的IP就会显示对应的web*名字了。

ok,我们再来配置mac下的nginx,前面说过,主要是用nginx的upstream,我接下来要完成的需求就是当我访问upstram.iyangyi.com时,会自动的负载均衡到这3个服务器上去。

先在hosts里加上

127.0.0.1 upstream.iyangyi.com

好,按照惯例,新建一个upstream.iyangyi.conf的server配置文件。

基于 weight 权重的负载

先来一个最简单的,weight权重的:

 
 
  1. upstream webservers{
  2. server 192.168.33.11 weight=10;
  3. server 192.168.33.12 weight=10;
  4. server 192.168.33.13 weight=10;
  5. }
  6. server {
  7. listen 80;
  8. server_name upstream.iyangyi.com;
  9. access_log /usr/local/var/log/nginx/upstream.iyangyi.access.log main;
  10. error_log /usr/local/var/log/nginx/upstream.iyangyi.error.log error;
  11. location / {
  12. proxy_pass http://webservers;
  13. proxy_set_header X-Real-IP $remote_addr;
  14. }
  15. }

重启nginx nginx -s reload,打开浏览器输入upstream.iyangyi.com,不断刷新下,就能看到变化显示web1,web2,web3。说明我们的负载均衡起作用了。

我们再打开web[1-3]的apache的访问日志:

sudo vi /var/log/httpd/access_log

192.168.33.1 - - [12/May/2015:10:47:02 +0000] "GET / HTTP/1.0" 200 5 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36"

上面也显示出了ip为这台mac的地址。说明负载均衡已经生效。

我们再来继续看几个参数 : max_failsfail_timeout

max_fails : 允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。

fail_timeout : 在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用,进行健康状态检查。

server 192.168.33.11 weight=1 max_fails=2 fail_timeout=30s;

所以这2个一起搭配使用,表示:当失败2次的时候,就停止使30秒

好,我们来继续做实验,将web1的httpd服务停掉,然后我们加上max_fails可以和fail_timeout。

 
 
  1. sudo /usr/sbin/apachectl stop
 
 
  1. upstream webservers{
  2. server 192.168.33.11 weight=10 max_fails=2 fail_timeout=30s;
  3. server 192.168.33.12 weight=10 max_fails=2 fail_timeout=30s;
  4. server 192.168.33.13 weight=10 max_fails=2 fail_timeout=30s;
  5. }

重启nginx,然后刷新upstream.iyangyi.com,就能看到变化显示,只有web2,web3web1没有了。

看下日志,显示web1 挂了:

2015/05/14 15:15:56 [error] 2381#0: *93 kevent() reported that connect() failed (61: Connection refused) while connecting to upstream, client: 127.0.0.1, server: upstream.iyangyi.com, request: "GET / HTTP/1.1", upstream: "http://192.168.33.11:80/", host: "upstream.iyangyi.com"

我们再来继续看剩下几个参数 : downbackup

down 表示这台机器暂时不参与负载均衡。相当于注释掉了。

backup 表示这台机器是备用机器,是其他的机器不能用的时候,这台机器才会被使用,俗称备胎 O__O "…

我们继续来做实验,改一下,先把web1改成down,然后将web3改成backup:

 
 
  1. upstream webservers{
  2. server 192.168.33.11 down;
  3. server 192.168.33.12 weight=10 max_fails=2 fail_timeout=30s;
  4. server 192.168.33.13 backup;
  5. }

重启下nginx,然后刷新下,不管怎么刷新,都显示是web2

接下来,我们将web2 的服务停掉:

 
 
  1. sudo /usr/sbin/apachectl stop

然后,我们再刷新下网页,看下备胎web3是不是被启用了:果然,页面上输出了web3

基于 ip_hash 的负载

这种分配方式,每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。

动手看怎么操作:

 
 
  1. upstream webservers{
  2. ip_hash;
  3. server 192.168.33.11 weight=1 max_fails=2 fail_timeout=30s;
  4. server 192.168.33.12 weight=1 max_fails=2 fail_timeout=30s;
  5. server 192.168.33.13 down;
  6. }

重启nginx,我们刷新,发现,再怎么刷,都是web1, 是固定的了。

我们讲web2的权重该大一点:

 
 
  1. upstream webservers{
  2. ip_hash;
  3. server 192.168.33.11 weight=1 max_fails=2 fail_timeout=30s;
  4. server 192.168.33.12 weight=2 max_fails=2 fail_timeout=30s;
  5. server 192.168.33.13 down;
  6. }

这样就会永远是web2了。

我们试着把web2服务关掉,再刷新,就会输出web1了,已经切换过来了。

注意
ip_hash 模式下,最好不要设置weight参数,因为你设置了,就相当于手动设置了,将会导致很多的流量分配不均匀。

ip_hash模式下, backup参数不可用,加了会报错,为啥呢?因为,本身我们的访问就是固定的了,其实,备用已经不管什么作用了。

4.页面缓存

页面缓存也是日常web 开发中很重要的一个环节,对于一些页面,我们可以将其静态化,保存起来,下次请求时候,直接走缓存,而不用去请求反相代理服务器甚至数据库服务了。从而减轻服务器压力。

nginx 也提供了简单而强大的下重定向反向代理的缓存功能,只需要简单配置下,就能将指定的一个页面缓存起来。它的原理也很简单,就是匹配当前访问的url, hash加密后,去指定的缓存目录找,看有没有,有的话就说明匹配到缓存了。

好。现在开始学习!

我们先来看一下一个简单的页面缓存的配置:

 
 
  1. http {
  2. proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=cache_zone:10m inactive=1d max_size=100m;
  3. upstream myproject {
  4. .....
  5. }
  6. server {
  7. ....
  8. location ~* \.php$ {
  9. proxy_cache cache_zone; #keys_zone的名字
  10. proxy_cache_key $host$uri$is_args$args; #缓存规则
  11. proxy_cache_valid any 1d;
  12. proxy_pass http://127.0.0.1:8080;
  13. }
  14. }
  15. ....
  16. }

下面我们来一步一步说。用到的配置参数,主要是proxy_*前缀的很多配置。

首先需要在http中加入proxy_cache_path 它用来制定缓存的目录以及缓存目录深度制定等。它的格式如下:

 
 
  1. proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time] [max_size=size];

1. path是用来指定 缓存在磁盘的路径地址。比如:/data/nginx/cache。那以后生存的缓存文件就会存在这个目录下。

2. levels用来指定缓存文件夹的级数,可以是:levels=1, levels=1:1,levels=1:2, levels=1:2:3 可以使用任意的1位或2位数字作为目录结构分割符,如 X, X:X,或 X:X:X 例如: 2, 2:2,1:1:2,但是最多只能是三级目录。

那这个里面的数字是什么意思呢。表示取hash值的个数。比如:现在根据请求地址localhost/index.php?a=4 用md5进行哈希,得到e0bd86606797639426a92306b1b98ad9

levels=1:2 表示建立2级目录,把hash最后1位(9)拿出建一个目录,然后再把9前面的2位(ad)拿来建一个目录, 那么缓存文件的路径就是/data/nginx/cache/9/d/e0bd86606797639426a92306b1b98ad9

以此类推:levels=1:1:2表示建立3级目录,把hash最后1位(9)拿出建一个目录,然后再把9前面的1位(d)建一个目录, 最后把d前面的2位(8a)拿出来建一个目录 那么缓存文件的路径就是/data/nginx/cache/9/d/8a/e0bd86606797639426a92306b1b98ad9

3. keys_zone 所有活动的key和元数据存储在共享的内存池中,这个区域用keys_zone参数指定。one指的是共享池的名称,10m指的是共享池的大小。

注意每一个定义的内存池必须是不重复的路径,例如:

 
 
  1. proxy_cache_path /data/nginx/cache/one levels=1 keys_zone=one:10m;
  2. proxy_cache_path /data/nginx/cache/two levels=2:2 keys_zone=two:100m;
  3. proxy_cache_path /data/nginx/cache/three levels=1:1:2 keys_zone=three:1000m;

4. inactive 表示指定的时间内缓存的数据没有被请求则被删除,默认inactive为10分钟。inactive=1d 1小时。inactive=30m30分钟。

5. max_size 表示单个文件最大不超过的大小。它被用来删除不活动的缓存和控制缓存大小,当目前缓存的值超出max_size指定的值之后,超过其大小后最少使用数据(LRU替换算法)将被删除。max_size=10g表示当缓存池超过10g就会清除不常用的缓存文件。

6. clean_time 表示每间隔自动清除的时间。clean_time=1m 1分钟清除一次缓存

好。说完了这个很重要的参数。我们再来说在server模块里的几个配置参数:

proxy_cache 用来指定用哪个keys_zone的名字,也就是用哪个目录下的缓存。上面我们指定了三个one, two,three 。比如,我现在想用one 这个缓存目录 :proxy_cache one

proxy_cache_key 这个其实蛮重要的,它用来指定生成hash的url地址的格式。他会根据这个key映射成一个hash值,然后存入到本地文件。
proxy_cache_key $host$uri表示无论后面跟的什么参数,都会访问一个文件,不会再生成新的文件。
而如果proxy_cache_key $is_args$args,那么传入的参数 localhost/index.php?a=4 与localhost/index.php?a=44将映射成两个不同hash值的文件。

proxy_cache_key 默认是 "$scheme$host$request_uri"。但是一般我们会把它设置成:$host$uri$is_args$args 一个完整的url路径。

proxy_cache_valid 它是用来为不同的http响应状态码设置不同的缓存时间,

 
 
  1. proxy_cache_valid 200 302 10m;
  2. proxy_cache_valid 404 1m;

表示为http status code 为200和302的设置缓存时间为10分钟,404代码缓存1分钟。
如果只定义时间:

 
 
  1. proxy_cache_valid 5m;

那么只对代码为200, 301和302的code进行缓存。
同样可以使用any参数任何相响应:

 
 
  1. proxy_cache_valid 200 302 10m;
  2. proxy_cache_valid 301 1h;
  3. proxy_cache_valid any 1m; #所有的状态都缓存1小时

好。缓存的基本一些配置讲完了。也大致知道了怎么使用这些参数。

现在开始实战!我们启动一台vagrant linux 机器 web1 (192.168.33.11) 用作远程代理机器,就不搞复杂的负载均衡了。

先在Mac本地加一个域名cache.iyangyi.com, 然后按照上面的配置在vhost 下新建一个proxy_cache.iyangyi.conf 文件:

 
 
  1. proxy_cache_path /usr/local/var/cache levels=1:2 keys_zone=cache_zone:10m inactive=1d max_size=100m;
  2. server {
  3. listen 80;
  4. server_name cache.iyangyi.com;
  5. access_log /usr/local/var/log/nginx/cache.iyangyi.access.log main;
  6. error_log /usr/local/var/log/nginx/cache.iyangyi.error.log error;
  7. add_header X-Via $server_addr;
  8. add_header X-Cache $upstream_cache_status;
  9. location / {
  10. proxy_set_header X-Real-IP $remote_addr;
  11. proxy_cache cache_zone;
  12. proxy_cache_key $host$uri$is_args$args;
  13. proxy_cache_valid 200 304 1m;
  14. proxy_pass http://192.168.33.11;
  15. }
  16. }

当然缓存文件夹 /usr/local/var/cache得提前新建好。然后重启nginx。

192.168.33.11 是apache服务器,在index.html页面就写了一个web1

我们打开浏览器访问 cache.iyangyi.com 。就能看到web1了。

打开审核元素或者firebug。看network网络请求选项,我们可以看到,Response Headers,在这里我们可以看到:

X-Cache:MISS
X-Via:127.0.0.1

X-cache 为 MISS 表示未命中,请求被传送到后端。y因为是第一次访问,没有缓存,所以肯定是未命中。我们再刷新下,就发现其变成了HIT, 表示命中。它还有其他几种状态:

MISS 未命中,请求被传送到后端
HIT 缓存命中
EXPIRED 缓存已经过期请求被传送到后端
UPDATING 正在更新缓存,将使用旧的应答
STALE 后端将得到过期的应答
BYPASS 缓存被绕过了

我们再去看看缓存文件夹 /usr/local/var/cache里面是否有了文件:

 
 
  1. cache git:(master) cd a/13
  2. 13 git:(master) ls
  3. 5bd1af99bcb0db45c8bd601d9ee9e13a
  4. 13 git:(master) pwd
  5. /usr/local/var/cache/a/13

已经生成了缓存文件。

我们在url 后面随便加一个什么参数,看会不会新生成一个缓存文件夹及文件: http://cache.iyangyi.com/?w=ww55。因为我们使用的生成规则是全部url转换(proxy_cache_key $host$uri$is_args$args;)

查看 X-cache 为 MISS,再刷新 ,变成HIT。再去看一下缓存文件夹 /usr/local/var/cache

  ~cache git:(master) ls
  4 a

果然又生成了一个4文件夹。

参考资料:http://freeloda.blog.51cto.com/2033581/1288553




猜你喜欢

转载自blog.csdn.net/shanzhizi/article/details/78924613