Loading
0

Nginx反向代理、缓存、负载均衡服务器构建

proxy_cache_path:设置缓存目录,目录里的文件名是cache_key的MD5值。levels=1:2 keys_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_headers Set-Cookie;
proxy_hide_header Set-Cookie;
proxy_cache:引用前面定义的缓存区my-cache
proxy_cache_key:定义如何生成缓存的键,设置web缓存的key值,nginx根据key值md5哈希存储缓存
proxy_cache_valid:为不同的响应状态码设置不同的缓存时间,比如200、302等正常结果可以缓存的时间长点,而404、500等缓存时间设置短一些,这个时间到了文件就会过期,而不论是否刚被访问过。
add_header指令来设置response header,语法: add_headername value;
$upstream_cache_status这个变量来显示缓存的状态,我们可以在配置中添加一个http头来显示这一状态,
$upstream_cache_status包含以下几种状态: ·MISS 未命中,请求被传送到后端 ·HIT 缓存命中 ·EXPIRED 缓存已经过期请求被传送到后端 ·UPDATING 正在更新缓存,将使用旧的应答 ·STALE 后端将得到过期的应答
expires :在响应头里设置Expires:或Cache-Control:max-age,返回给客户端的浏览器缓存失效时间。
下面的nginx.conf实现nginx在前端做反向代理服务器的完整配置文件的例子,处理js、png?www.8090-sec.com等静态文件,jsp/php等动态请求转发到其它服务器tomcat/apache

user  www www;
worker_processes 2;
worker_cpu_affinity 01 10;
error_log logs/error.log;
#error_log logs/error.log  notice;
#error_log logs/error.log  info;
worker_rlimit_nofile 10240;
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_tokens off;
sendfile       on;
   #tcp_nopush     on;
   #keepalive_timeout  0;
keepalive_timeout 65;
    #CompressionSettings
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/css text/javascriptapplication/json application/javascript application/x-javascriptapplication/xml;
gzip_vary on;
    #end gzip
    # http_proxySettings
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_cachelevels=1:2 keys_zone=my-cache:100m max_size=1000m inactive=600m max_size=2g;
    #loadbalance Settings
upstream backend {
sticky;
server 192.168.31.141:80 weight=1 max_fails=2fail_timeout=10s;
server 192.168.31.250:80 weight=1 max_fails=2fail_timeout=10s;
    }
    #virtualhost Settings
server {
listen       80;
server_name localhost;
charset utf-8;
location  ~/purge(/.*) {
allow 127.0.0.1;
allow 192.168.31.0/24;
deny all;
proxy_cache_purge my-cache $host$1$is_args$args;
        }
location / {
index  index.phpindex.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 timeout invalid_headerhttp_500 http_502 http_503 http_504;
        }
location ~.*\.(gif|jpg?www.myhack58.com|png?www.myhack58.com|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 timeout invalid_headerhttp_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.31.0/24;
deny all;
        }
    }
}

常用指令说明:
main全局配置:
woker_processes4在配置文件的顶级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_affinity 0001 0010 0100 1000; (四核)。
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进行压缩等。
sendfileon开启高效文件传输模式。
keepalive_timeout 65 : 长连接超时时间,单位是秒,长连接请求大量小文件的时候,可以减少重建连接的开销,如果设置时间过长,用户又多,长时间保持连接会占用大量资源。
client_max_body_size10m允许客户端请求的最大单文件字节数。如果有上传较大文件,请设置它的限制值
client_body_buffer_size128k缓冲区代理缓冲用户端请求的最大字节数
server_tokens off;
隐藏nginx的版本号
模块http_proxy:
这个模块实现的是nginx作为反向代理服务器的功能,包括缓存功能
proxy_connect_timeout 60
nginx跟后端服务器连接超时时间(代理连接超时)
proxy_read_timeout 60
定义从后端服务器读取响应的超时。此超时是指相邻两次读操作之间的最长时间间隔,而不是整个响应传输完成的最长时间。如果后端服务器在超时时间段内没有传输任何数据,连接将被关闭。
proxy_send_timeout  75
定义向后端服务器传输请求的超时。此超时是指相邻两次写操作之间的最长时间间隔,而不是整个请求传输完成的最长时间。如果后端服务器在超时时间段内没有接收到任何数据,连接将被关闭。
proxy_buffer_size 4k
设置缓冲区的大小为size。nginx从被代理的服务器读取响应时,使用该缓冲区保存响应的开始部分。这部分通常包含着一个小小的响应头。该缓冲区大小默认等于proxy_buffers指令设置的一块缓冲区的大小,但它也可以被设置得更小。
proxy_buffers 84k
语法: proxy_buffersthe_numberis_size;
为每个连接设置缓冲区的数量为number,每块缓冲区的大小为size。这些缓冲区用于保存从被代理的服务器读取的响应。每块缓冲区默认等于一个内存页的大小。这个值是4K还是8K,取决于平台。
附:查看Linux内存页大小
[root@hexiaoshuai ~]# getconf PAGESIZE
4096

[root@hexiaoshuai ~]# getconf PAGE_SIZE
4096
proxy_busy_buffers_size64k高负荷下缓冲大小(默认大小是proxy_buffers指令设置单块缓冲大小的2倍)
proxy_max_temp_file_size
当proxy_buffers放不下后端服务器的响应内容时,会将一部分保存到硬盘的临时文件中,这个值用来设置最大临时文件大小,默认1024M。
proxy_temp_file_write_size64k
当缓存被代理的服务器响应到临时文件时,这个选项限制每次写临时文件的大小。
模块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:port options; 方式组织在 {} 中。如果后端被代理的只有一台,也可以直接写在proxy_pass。
Location:
root /var/www/html
定义服务器的默认网站根目录位置。如果locationURL匹配的是子目录或文件,root没什么作用,一般放在server指令里面或/下。
indexindex.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_redirect http://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_headerX-Forwarded-For $proxy_add_x_forwarded_for;
后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
X_Forward_For字段表示该条http请求是有谁发起的?如果反向代理服务器不重写该请求头的话,那么后端真实服务器在处理时会认为所有的请求都来自反向代理服务器,如果后端有防攻击策略的话,那么机器就被封掉了。因此,在配置用作反向代理的nginx中一般会增加两条配置,修改http的请求头:proxy_set_header Host $host;proxy_set_header X-Forward-For $remote_addr;
proxy_next_upstreamerror timeoutinvalid_header http_500 http_502 http_503 http_504;
增加故障转移,如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。
proxy_set_headerX-Real-IP $remote_addr;
web服务器端获得用户的真实ip但是,实际上要获得用户的真实ip,也可以通过X-Forward-For
7、验证:nginx反向代理的缓存功能、负载均衡及健康检查
1)下面我们来测试一下缓存功能
如果在缓存时间之内需要更新被缓存的静态文件怎么办呢,这时候就需要手动来清除缓存了。
ngx_cache_pure清除缓存模块使用说明
用谷歌浏览器测试的时候,可以按F12调用开发工具,选择Network选项,我们可以看到,Response Headers,在这里我们可以看到,我们请求的是否是缓存

从图中我们可以看到,我们访问的服务器是192.168.31.83,缓存命中。
也可以查看缓存目录或nginx的访问日志

[root@hexiaoshuai ~]# tail -f /usr/local/nginx1.10/logs/access.log 
192.168.31.10 - - [19/Mar/2017:23:13:33 +0800] "GET /11.gif HTTP/1.1" 200 3694 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36" "-""MISS"
192.168.31.10 - - [19/Mar/2017:23:13:37 +0800] "GET /11.gif HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36" "-""HIT"
分页阅读: 1 2 3 4 5 6
【声明】:8090安全小组门户(http://www.8090-sec.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们:邮箱hack@ddos.kim,我们会在最短的时间内进行处理。