6、nginx的proxy缓存使用:

缓存也就是将js、css、p_w_picpath等静态文件从后端服务器缓存到nginx指定的缓存目录下,既可以减轻后端服务器负担,也可以加快访问速度,但这样缓存及时清理成为了一个问题,所以需要 ngx_cache_purge 这个模块来在过期时间未到之前,手动清理缓存。

proxy模块中常用的指令时proxy_pass和proxy_cache.

nginx的web缓存功能的主要是由proxy_cache、fastcgi_cache指令集和相关指令集完成,proxy_cache指令负责反向代理缓存后端服务器的静态内容,fastcgi_cache主要用来处理FastCGI动态进程缓存。

wKioL1kSZAHiW6z0AAKyQeFNtY4961.jpg

wKiom1kSZAOBreL1AAN4swlxnA0932.jpg

相关选项说明:

proxy_buffering on代理的时候,开启或关闭缓冲后端服务器的响应。

当开启缓冲时,nginx尽可能快地从被代理的服务器接收响应,再将它存入缓冲区中。

proxy_temp_path : 缓存临时目录。后端的响应并不直接返回客户端,而是先写到一个临时文件中,然后被rename一下当做缓存放在 proxy_cache_path 。0.8.9版本以后允许temp和cache两个目录在不同文件系统上(分区),然而为了减少性能损失还是建议把它们设成一个文件系统上。

proxy_cache_path: 设置缓存目录,目录里的文件名是 cache_key 的MD5值。

levels=1:2keys_zone=my-cache:100m表示采用2级目录结构,第一层目录只有一个字符,是由levels=1:2设置,总共二层目录,子目录名字由二个字符组成。Web缓存区名称为my-cache,内存缓存空间大小为100MB,这个缓冲zone可以被多次使用。文件系统上看到的缓存文件名类似于

/usr/local/nginx1.10/proxy_cache/c/29/b7f54b2df7773722d382f4809d65029c

inactive=600 max_size=2g表示600分钟没有被访问的内容自动清除,硬盘最大缓存空间为2GB,超过这个大小将清除最近最少使用的数据。

需要在默认情况,nginx不缓存从后端响应的http头中带有Set-Cookie的对象。如果客户端发送的请求带有Cookie header,varnish将忽略缓存,直接将请求传递到后端。nginx中通过proxy_ignore_headers设置忽略它们,设置方法如下:

解决办法: 

proxy_ignore_headersSet-Cookie;

proxy_hide_headerSet-Cookie;

proxy_cache : 引用前面定义的缓存区 my-cache

proxy_cache_key:定义如何生成缓存的键,设置web缓存的key值,nginx根据key值md5哈希存储缓存

proxy_cache_valid : 为不同的响应状态码设置不同的缓存时间,比如200、302等正常结果可以缓存的时间长点,而404、500等缓存时间设置短一些,这个时间到了文件就会过期,而不论是否刚被访问过。

add_header指令来设置responseheader, 语法: add_header name value;

$upstream_cache_status这个变量来显示缓存的状态,我们可以在配置中添加一个http头来显示这一状态,

$upstream_cache_status包含以下几种状态

·MISS 未命中,请求被传送到后端

·HIT 缓存命中

·EXPIRED 缓存已经过期请求被传送到后端

·UPDATING 正在更新缓存,将使用旧的应答

·STALE 后端将得到过期的应答

expires : 在响应头里设置Expires:或Cache-Control:max-age,返回给客户端的浏览器缓存失效时间。

 

下面是nginx.conf实现nginx在前端做反向代理服务器的完整配置文件的例子,处理js、png等静态文件,jsp/php等动态请求转发到其它服务器tomcat/apache。

user  www www;

worker_processes  4;

worker_cpu_affinity0001 0010 0100 1000;

error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;

worker_rlimit_nofile10240;

pid        logs/nginx.pid;

events{

    use epoll;

    worker_connections  4096;

}

http{

    include       mime.types;

    default_type  application/octet-stream;

   log_format  main  '$remote_addr - $remote_user [$time_local]"$request" '

                      '$status $body_bytes_sent"$http_referer" '

                     '"$http_user_agent" "$http_x_forwarded_for"'

                     '"$upstream_cache_status"';

access_log  logs/access.log  main;

server_tokensoff;

    sendfile        on;

    #tcp_nopush     on;

    #keepalive_timeout  0;

    keepalive_timeout  65;

    #Compression Settings

    gzip on;

    gzip_comp_level 6;

    gzip_http_version 1.1;

    gzip_proxied any;

    gzip_min_length 1k;

    gzip_buffers 16 8k;

    gzip_types text/plain text/csstext/javascript application/json application/javascriptapplication/x-javascript application/xml;

    gzip_vary on;

    #end gzip

    # http_proxy Settings

    client_max_body_size   10m;

    client_body_buffer_size   128k;

    proxy_connect_timeout   75;

    proxy_send_timeout   75;

    proxy_read_timeout   75;

    proxy_buffer_size   4k;

    proxy_buffers   4 32k;

    proxy_busy_buffers_size   64k;

    proxy_temp_file_write_size  64k;

    proxy_buffering on;

    proxy_temp_path/usr/local/nginx1.10/proxy_temp;

    proxy_cache_path/usr/local/nginx1.10/proxy_cache levels=1:2 keys_zone=my-cache:100mmax_size=1000m inactive=600m max_size=2g;

    #load balance Settings

    upstream backend {

        sticky;

        server 192.168.1.7:80 weight=1max_fails=2 fail_timeout=10s;

        server 192.168.1.8:80 weight=1max_fails=2 fail_timeout=10s;

    }

    #virtual host Settings

    server {

        listen      80;

        server_name  localhost;

        charset utf-8;

        location  ~/purge(/.*) {

           allow 127.0.0.1;

           allow 192.168.1.0/24;

           deny all;

           proxy_cache_purge my-cache$host$1$is_args$args;

        }

        location / {

            index  index.php index.html index.htm;

            proxy_pass        http://backend;

            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;

            proxy_ignore_headers Set-Cookie;

           proxy_hide_header Set-Cookie;

            proxy_next_upstream error timeoutinvalid_header http_500 http_502 http_503 http_504;

        }

        location ~.*\.(gif|jpg|png|html|htm|css|js|ico|swf|pdf)(.*) {

           proxy_pass  http://backend;

           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;

           proxy_next_upstream error timeoutinvalid_header http_500 http_502 http_503 http_504;

           proxy_cache my-cache;

           add_header Nginx-Cache$upstream_cache_status;

           proxy_cache_valid 200 304 301 302 8h;

           proxy_cache_valid 404 1m;

           proxy_cache_valid any 1d;

           proxy_cache_key$host$uri$is_args$args;

           expires 30d;

        }

        location /nginx_status {

            stub_status on;

            access_log off;

            allow 192.168.1.0/24;

            deny all;

        }

    }

}

:nginx代理服务器这里server_name  localhost;而后台web服务器上每个服务器上都必须是ServerName www.benet.com

常用指令说明:

main全局配置:

woker_processes 4

在配置文件的顶级main部分,worker角色的工作进程的个数,master进程是接收并分配请求给worker处理。这个数值简单一点可以设置为cpu的核数grep ^processor /proc/cpuinfo | wc -l,也是 auto 值,如果开启了ssl和gzip更应该设置成与逻辑CPU数量一样甚至为2倍,可以减少I/O操作。如果nginx服务器还有其它服务,可以考虑适当减少。

worker_cpu_affinity

也是写在main部分。在高并发情况下,通过设置cpu粘性来降低由于多CPU核切换造成的寄存器等现场重建带来的性能损耗。如worker_cpu_affinity0001 0010 0100 1000; (四核)。

附:

CPU工作状况:(输入 top 后,按1 查看)

wKiom1kSZASzbcZSAADz2ARukHU951.jpg

上面的配置表示:4核CPU,开启4个进程。0001表示开启第一个cpu内核, 0010表示开启第二个cpu内核,依次类推;有多少个核,就有几位数,1表示该内核开启,0表示该内核关闭。

例如:

1、2核CPU,开启2个进程

worker_processes  2;

worker_cpu_affinity01 10;

2、2核CPU,开启4进程

worker_processes4;

worker_cpu_affinity01 10 01 10;

3、2核CPU,开启8进程

worker_processes  8;

worker_cpu_affinity01 10 01 10 01 10 01 10;

4、8核CPU,开启2进程

worker_processes  2;

worker_cpu_affinity10101010  01010101;

说明:10101010表示开启了第2,4,6,8内核,01010101表示开始了1,3,5,7内核http

通过 apache 的ab测试查看nginx对CPU的使用状况:

wKioL1kSZATBB-G2AAD1sr-YmcY185.jpg

如果多个CPU内核的利用率都相差不多,证明nginx己经成功的利用了多核CPU。

测试结束后,CPU内核的负载应该都同时降低。

worker_connections 4096

写在events部分。每一个worker进程能并发处理(发起)的最大连接数(包含与客户端或后端被代理服务器间等所有连接数)。

worker_rlimit_nofile 10240

写在main部分。worker进程的最大打开文件数限制。默认是没有设置,如果没设置的话,这个值为操作系统的限制(ulimit -n)。可以限制为操作系统最大的限制65535。把这个值设高,这样nginx就不会有“too many open files”问题了。

use epoll

写在events部分。在Linux操作系统下,nginx默认使用epoll事件模型,得益于此,nginx在Linux操作系统下效率相当高。同时Nginx在OpenBSD或FreeBSD操作系统上采用类似于epoll的高效事件模型kqueue。

http服务器:

与提供http服务相关的一些配置参数。例如:是否使用keepalive啊,是否使用gzip进行压缩等。

sendfile on

开启高效文件传输模式。

keepalive_timeout 65 :长连接超时时间,单位是秒,长连接请求大量小文件的时候,可以减少重建连接的开销,如果设置时间过长,用户又多,长时间保持连接会占用大量资源。

client_max_body_size 10m

允许客户端请求的最大单文件字节数。如果有上传较大文件,请设置它的限制值

client_body_buffer_size 128k

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

server_tokens off;

隐藏nginx的版本号

模块http_proxy:

这个模块实现的是nginx作为反向代理服务器的功能,包括缓存功能

proxy_connect_timeout

nginx跟后端服务器连接超时时间(代理连接超时)

proxy_read_timeout

定义从后端服务器读取响应的超时。此超时是指相邻两次读操作之间的最长时间间隔,而不是整个响应传输完成的最长时间。如果后端服务器在超时时间段内没有传输任何数据,连接将被关闭。

proxy_send_timeout

定义向后端服务器传输请求的超时。此超时是指相邻两次写操作之间的最长时间间隔,而不是整个请求传输完成的最长时间。如果后端服务器在超时时间段内没有接收到任何数据,连接将被关闭。

proxy_buffer_size 4k

设置缓冲区的大小为size。nginx从被代理的服务器读取响应时,使用该缓冲区保存响应的开始部分。这部分通常包含着一个小小的响应头。该缓冲区大小默认等于proxy_buffers指令设置的一块缓冲区的大小,但它也可以被设置得更小。

proxy_buffers 8 4k

语法: proxy_buffers the_number is_size;

为每个连接设置缓冲区的数量为number,每块缓冲区的大小为size。这些缓冲区用于保存从被代理的服务器读取的响应。每块缓冲区默认等于一个内存页的大小。这个值是4K还是8K,取决于平台。

附:查看Linux内存页大小

[root@www~]# getconf PAGESIZE

4096

[root@www~]# getconf PAGE_SIZE

4096

proxy_busy_buffers_size 64k

高负荷下缓冲大小(默认大小是proxy_buffers指令设置单块缓冲大小的2倍)

proxy_max_temp_file_size

当 proxy_buffers 放不下后端服务器的响应内容时,会将一部分保存到硬盘的临时文件中,这个值用来设置最大临时文件大小,默认1024M。

proxy_temp_file_write_size 64k

当缓存被代理的服务器响应到临时文件时,这个选项限制每次写临时文件的大小。

模块http_gzip:

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

gzip_min_length 1k : 设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。建议设置成大于1k的字节数,小于1k可能会越压越大。

gzip_buffers 4 16k: 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。4 16k代表以16k为单位,按照原始数据大小以16k为单位的4倍申请内存。如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果

gzip_http_version 1.1 : 用于识别 http 协议的版本,早期的浏览器不支持 Gzip 压缩,用户就会看到乱码,所以为了支持前期版本加上了这个选项,如果你用了Nginx 的反向代理并期望也启用 Gzip 压缩的话,由于末端通信是 http/1.1,故请设置为 1.1。

gzip_comp_level 6  gzip压缩比,1压缩比最小处理速度最快,9压缩比最大但处理速度最慢(传输快但比较消耗cpu)

gzip_types :匹配mime类型进行压缩,无论是否指定”text/html”类型总是会被压缩的。

默认值: gzip_types text/html (默认不对js/css文件进行压缩)

#压缩类型,匹配MIME类型进行压缩

#不能用通配符 text/*

#(无论是否指定)text/html默认已经压缩

#设置哪压缩种文本文件可参考 conf/mime.types

gzip_proxied any: Nginx作为反向代理的时候启用,根据某些请求和应答来决定是否在对代理请求的应答启用gzip压缩,是否压缩取决于请求头中的“Via”字段,指令中可以同时指定多个不同的参数,意义如下:

off– 关闭所有的代理结果数据的压缩

expired– 启用压缩,如果header头中包含 “Expires” 头信息

no-cache– 启用压缩,如果header头中包含 “Cache-Control:no-cache” 头信息

no-store– 启用压缩,如果header头中包含 “Cache-Control:no-store” 头信息

private– 启用压缩,如果header头中包含 “Cache-Control:private” 头信息

no_last_modified– 启用压缩,如果header头中不包含“Last-Modified” 头信息

no_etag– 启用压缩 ,如果header头中不包含“ETag” 头信息

auth– 启用压缩 , 如果header头中包含“Authorization” 头信息

any– 无条件启用压缩

gzip_vary on :和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩。

模块http_stream:

这个模块通过一个简单的调度算法来实现客户端IP到后端服务器的负载均衡,upstream后接负载均衡器的名字,后端realserver以 host:portoptions;方式组织在 {} 中。如果后端被代理的只有一台,也可以直接写在 proxy_pass 。

Location:

root /var/www/html

定义服务器的默认网站根目录位置。如果locationURL匹配的是子目录或文件,root没什么作用,一般放在server指令里面或/下。

 

index index.jsp index.html index.htm

定义路径下默认访问的文件名,一般跟着root放

 

proxy_pass http:/backend

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

 

proxy_redirect off;

指定是否修改被代理服务器返回的响应头中的location头域跟refresh头域数值

例如:

设置后端服务器“Location”响应头和“Refresh”响应头的替换文本。 假设后端服务器返回的响应头是 “Location: http://localhost:8000/two/some/uri/”,那么指令

proxy_redirecthttp://localhost:8000/two/ http://frontend/one/;

将把字符串改写为

“Location:http://frontend/one/some/uri/”

proxy_set_header Host $host;

允许重新定义或者添加发往后端服务器的请求头。

Host的含义是表明请求的主机名,nginx反向代理服务器会向后端真实服务器发送请求,并且请求头中的host字段重写为proxy_pass指令设置的服务器。因为nginx作为反向代理使用,而如果后端真实的服务器设置有类似防盗链或者根据http请求头中的host字段来进行路由或判断功能的话,如果反向代理层的nginx不重写请求头中的host字段,将会导致请求失败。

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

后端的Web服务器可以通过X-Forwarded-For获取用户真实IP

X_Forward_For字段表示该条http请求是有谁发起的?如果反向代理服务器不重写该请求头的话,那么后端真实服务器在处理时会认为所有的请求都来自反向代理服务器,如果后端有防***策略的话,那么机器就被封掉了。因此,在配置用作反向代理的nginx中一般会增加两条配置,修改http的请求头:

proxy_set_headerHost $host;

proxy_set_headerX-Forward-For $remote_addr;

 

proxy_next_upstreamerror timeout invalid_header http_500 http_502 http_503 http_504;

增加故障转移,如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。

 

proxy_set_header X-Real-IP $remote_addr;

web服务器端获得用户的真实ip但是,实际上要获得用户的真实ip,也可以通过X-Forward-For

7、验证:nginx反向代理的缓存功能、负载均衡及健康检查

说明:

1)下面我们来测试一下缓存功能

如果在缓存时间之内需要更新被缓存的静态文件怎么办呢,这时候就需要手动来清除缓存了。

ngx_cache_pure清除缓存模块使用说明

用谷歌浏览器测试的时候,可以按F12调用开发工具,选择Network选项,我们可以看到,Response Headers,在这里我们可以看到,我们请求的是否是缓存。

wKiom1kSZAWie1mBAAEJRc0M0yc627.jpg

说明:第一次访问是MISS,刷新一下这个页面就是HIT命中了。

从图中我们可以看到,我们访问的服务器是192.168.1.6,缓存命中。

也可以查看缓存目录或nginx的访问日志。

wKioL1kSZAXR0toYAACbeeBR6gg146.jpg

wKioL1kSZAbBQCO9AAH9_AsUKtE934.jpg

清除缓存:

上述配置的proxy_cache_purge指令用于方便的清除缓存,但必须按照第三方的ngx_cache_purge 模块才能使用

使用 ngx_cache_purge 模块清除缓存(直接删除缓存目录下的文件也算一种办法):

GET方式请求URL

即使用配置文件中的location ~ /purge(/.*)

浏览器访问http://192.168.1.6/purge/your/may/path来清除缓存。

wKiom1kSZAbB-MaoAACg6cFrg08274.jpg

缓存清除成功。

备注

      (1)purge是ngx_cache_pure 模块指令

      (2)your/may/path是要清除的缓存文件URL路径

 

2)若只有一台客户端要验证负载均衡和健康检查可以先关掉缓存功能和保持session会话。

wKiom1kSZAeCuQB3AABA0huDdpA569.jpg

wKioL1kSZAeQn3CHAAAfP909vag881.jpg

wKiom1kSZAeyMKlcAADNfKK5ATQ809.jpg

测试:

wKioL1kSZAjjo82WAACpx9FZCAM740.jpg

wKiom1kSZAjCwN_oAAC14tAIaGg309.jpg

验证健康检查:

首先关闭一台后端的web服务器的web服务:

wKioL1kSZAiBdalEAADl4yYtA1Y956.jpg

开始验证:

wKiom1kSZAmw5WguAABzdnEyHDQ077.jpg

中间不卡顿,一直访问的是apache2的网页。

重新启动宕机的apache1的web服务:

wKiom1kSZB_xYPvNAADha67HOkY152.jpg

再次验证:

wKioL1kSZB_gsb8RAAB71VzKyfg502.jpg

wKiom1kSZB-i3-VOAABuK8L6Kxc135.jpg

又可以来回切换的正常访问了。

在后端服务器上查看访问日志:

wKioL1kSZCDCmfhwAAEM-y3qFQM982.jpg

可以看见,访问日志记录的访问者是nginx反向代理服务器的IP,那怎么让它记录的是客户机的真是IP,而不是nginx代理服务器的呢?

解决办法如下:

wKiom1kSZCDDqGo0AADic2bnYTU094.jpg

wKiom1kSZCDRaTyQAACQKHXDjew466.jpg

wKioL1kSZCHhdNJpAACkW5Jlqa4861.jpg

再次查看:

wKioL1kSZCHRU1mOAAC0X5X32a0535.jpg

注:192.168.1.4是我客户机的IP。