02 - nginx - 反向代理、限速、URL重写
一、Nginx反向代理
代理服务器,客户机在发送请求时,不会直接发送给目的主机,而是先发送给代理服务器. 代理服务接受客户机请求之后,再向主机发出,并接收目的主机返回的数据,存放在代理服务器的硬盘中,再发送给客户机。 location / { proxy_pass http://118.190.209.153:4000; } OR (优化后得) location / { index index.php index.html index.htm; #定义首页索引文件的名称 proxy_pass http://mysvr ; #请求转向mysvr 定义的服务器列表 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; #允许客户端请求的大单文件字节数 client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的大字节数, proxy_connect_timeout 90; #nginx跟后端服务器连接超时时间(代理连接超时) proxy_send_timeout 90; #后端服务器数据回传时间(代理发送超时) proxy_read_timeout 90; #连接成功后,后端服务器响应时间(代理接收 超时) proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息 的缓冲区大小 proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置 proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2) proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从 upstream服务器传 } 测试: killall nginx ../sbin/nginx 10.0.0.200
二、Nginx限速
1.限速介绍: 限流(rate limiting)是NGINX众多特性中有用的,也是经常容易被误解和错误配置的,特性之一。 该特性可以限制某个用户在一个给定时间段内能够产生的HTTP 请求数。 请求可以简单到就是一个对于主页的GET请求或者一个登陆表格的POST 请求。 限流也可以用于安全目的上,比如减慢暴力密码破解攻击。 通过限制进来的请求速率,并且(结合日志)标记出目标URLs来帮助防范DDoS攻击。 一般地说,限流是用在保护上游应用服务器不被在同一时刻的大量用户请求湮没。 2.应用场景 DDOS防御 下载场景保护IO 3.限速原理 水(请求)从上方倒入水桶,从水桶下方流出(被处理); 来不及流出的水存在水桶中(缓冲),以固定速率流出; 水桶满后水溢出(丢弃)。 这个算法的核心是:缓存请求、匀速处理、多余的请求直接丢弃。 相比漏桶算法,令牌桶算法不同之处在于它不但有一只“桶”,还有个队列, 这个桶是用来存放令牌的,队列才是用来存放请求的。 4.限速实现,实现方式: Nginx官方版本限制IP的连接和并发分别有两个模块: limit_req_zone 用来限制单位时间内的请求数,即速率限制。 limit_req_conn 用来限制同一时间连接数,即并发限制。 5.模块使用方法 limit_req_zone 参数配置 Syntax: limit_req zone=name [burst=number] [nodelay]; Default: — Context: http, server, location 6.限速案例一: #基于IP对下载速率做限制,限制每秒处理1次请求,对突发超过5个以后的请求放入缓存区。 http { limit_req_zone $binary_remote_addr zone=baism:10m rate=1r/s; server { location /abc { limit_req zone=baism burst=5 nodelay; } } } limit_req_zone $binary_remote_addr zone=baism:10m rate=1r/s; 第一个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制, “binary_”的目的是缩写内存占用量,是限制同一客户端ip地址。 第二个参数:zone=baism:10m表示生成一个大小为10M,名字为one的内存区域, 用来存储访问的频次信息。 第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒 1次,还可以有比如30r/m的。 limit_req zone=baism burst=5 nodelay; 第一个参数:zone=baism 设置使用哪个配置区域来做限制,与上面 limit_req_zone 里的name对应。 第二个参数:burst=5,重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时, 超过了访问频次限制的请求可以先放到这个缓冲区内。 第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。 7.限速案例二: #基于IP做连接限制,限制同一IP并发为1 下载速度为100K limit_conn_zone $binary_remote_addr zone=addr:10m; server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } location /abc { limit_conn addr 1; limit_rate 100k; } } 创建一个大文件: dd if=/dev/zero of=../html/abc/bigfile bs=1M count=300 # 300M一个文件 cd /tmp wget http://192.168./10.42/abc/bigfile 8.综合案例: http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; #基于IP做连接限制 限制同一IP并发为1 下载速度为100K limit_conn_zone $binary_remote_addr zone=addr:10m; #基于IP对下载速率做限制 限制每秒处理1次请求,对突发超过5个以后的请求放入缓存区 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } location /abc { limit_req zone=one burst=5 nodelay; limit_conn addr 1; limit_rate 100k; } } } 9.测试: cd /usr/local/nginx/conf vim nginx.conf ../sbin/nginx elinks http://192.168.10.52 --dump
三、URL重写
( cd /usr/local/nginx/conf netstat -ntpl killall nginx ../sbin/nginx ) rewrite模块(ngx_http_rewrite_module) 应用场景: 域名变更 (京东) 用户跳转 (从某个连接跳到另一个链接) 伪静态场景(便于cdn缓存动态页面数据) URL 模块语法: 1) set 设置变量 2) if 负责语句中的判断 3) return 返回返回值或URL 4) break 终止后续的rewrite规则 5) rewrite 重定向URL a. set指令 自定义变量 Syntax: set $variable value; Default: — Context: server, location, if 将http://www.ayitula.com 重写为 http://www.ayitula.com/baism location / { set $name baism; rewrite ^(.*)$ http://www.ayitula.com/$name; } b. if 指令 负责判断 Syntax: if (condition) { ... } Default: — Context: server, location location / { root html; index index.html index.htm; if ($http_user_agent ~* 'Chrome') { break; return 403; #return http://www.jd.com; } } #模糊匹配 ~匹配 !~不匹配 ~* 不区分大小写的匹配 #精确匹配 = != c. return 指令 定义返回数据 Syntax: return code [text]; return code URL; return URL; Default: — Context: server, location, if location / { root html; index index.html index.htm; if ($http_user_agent ~* 'Chrome') { return 403; #return http://www.jd.com; } } d. break 指令 停止执行当前虚拟主机的后续rewrite指令集 Syntax: break; Default: — Context:server, location, if location / { root html; index index.html index.htm; if ($http_user_agent ~* 'Chrome') { break; return 403; } } e. rewrite 模块 rewrite <regex> <replacement> [flag]; 关键字 正则 替代内容 flag标记 flag: last #本条规则匹配完成后,继续向下匹配新的location URI规则 break #本条规则匹配完成即终止,不再匹配后面的任何规则 redirect #返回302临时重定向,浏览器地址会显示跳转后的URL地址 permanent #返回301永久重定向,浏览器地址栏会显示跳转后的URL地址 eg: 域名跳转 www.ayitula.com 重写为 www.jd.com server { listen 80; server_name www.ayitula.com; location / { rewrite ^/$ http://www.jd.com permanent ; } } 注意: 重定向就是将网页自动转向重定向 301永久性重定向:新网址完全继承旧网址,旧网址的排名等完全清零 301重定向是网页更改地址后对搜索引擎友好的好方法,只要不是暂时搬移的情况,都建议使用301来做转址。 302临时性重定向:对旧网址没有影响,但新网址不会有排名 搜索引擎会抓取新的内容而保留旧的网址 ######################################################################### break 类似临时重定向 根据用户浏览器重写访问目录 如果是chrome浏览器 就将 http://192.168.10.42/$URI 重写为 http://http://192.168.10.42/chrome/$URI 实现步骤 1)URL重写 2)请求转给本机location location / { ..... if ($http_user_agent ~* 'chrome'){ #^ 以什么开头 ^a #$ 以什么结尾 c$ #. 除了回车以外的任意一个字符 #* 前面的字符可以出现多次或者不出现 # 更多内容看正则表达式 re rewrite ^(.*)$ /chrome/$1 last; } location /chrome { root html ; index index.html; } } url重写后,马上发起一个新的请求,再次进入server块,重试location匹配, 超过 10次匹配不到报500错误,地址栏url不变 last 一般出现在server或if中 数据包走向 client-->nginx nginx告诉客户端让服务器的新地址(真实服务器) 客户端收到后再去找服务器 client--->server 练习: # 访问 /baism00.html 的时候,页面内容重写到 /index.html 中 rewrite /baism00.html /index.html last; # 访问 /baism01.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配 rewrite /baism01.html /index.html break; # 访问 /baism02.html 的时候,页面直接302定向到 /index.html中 rewrite /baism02.html /index.html redirect; // 302 临时,redirect # 访问 /baism03.html 的时候,页面直接301定向到 /index.html中 rewrite /baism03.html /index.html permanent; // 301 永久,permanent # 把 /html/*.html => /post/*.html ,301定向 rewrite ^/html/(.+?).html$ /post/$1.html permanent; # 把 /search/key => /search.html?keyword=key rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;