工作,学习,生活,这里将会有一些记录. 备用域名:http://meisw.wdlinux.cn 注册 | 登陆
浏览模式: 标准 | 列表分类:nginx

Nginx 并发连接数控制 Limit Zone Limit simultaneous connections

ngx_http_limit_zone_module

Limit Zone Limit simultaneous connections from a client.

本模块可以针对条件,进行会话的并发连接数控制。(例如:限制每个IP的并发连接数。)

__配置示例__

http { : limit_zone   one  $binary_remote_addr  10m;  : ...  : server {  : ...  : location /download/ { : limit_conn   one  1; : }

指令

  • [#limit_zone limit_zone]
  • [#limit_conn limit_conn]

 

limit_zone

语法: limit_zone zone_name $variable the_size

默认值: no

作用域: http

本指令定义了一个数据区,里面记录会话状态信息。
$variable 定义判断会话的变量;the_size 定义记录区的总容量。

例子:

limit_zone   one  $binary_remote_addr  10m;

定义一个叫“one”的记录区,总容量为 10M,以变量 $binary_remote_addr 作为会话的判断基准(即一个地址一个会话)。


您可以注意到了,在这里使用的是 $binary_remote_addr 而不是 $remote_addr。

$remote_addr 的长度为 7 至 15 bytes,会话信息的长度为 32 或 64 bytes。而 $binary_remote_addr 的长度为 4 bytes,会话信息的长度为 32 bytes。

当区的大小为 1M 的时候,大约可以记录 32000 个会话信息(一个会话占用 32 bytes)。


 

limit_conn

语法: limit_conn zone_name the_size

默认值: no

作用域: http, server, location

指定一个会话最大的并发连接数。当超过指定的最发并发连接数时,服务器将返回 "Service unavailable" (503)。

例子:

limit_zone   one  $binary_remote_addr  10m;  : server { : location /download/ { : limit_conn   one  1; : }

定义一个叫“one”的记录区,总容量为 10M,以变量 $binary_remote_addr 作为会话的判断基准(即一个地址一个会话)。限制 /download/ 目录下,一个会话只能进行一个连接。简单点,就是限制 /download/ 目录下,一个IP只能发起一个连接,多过一个,一律503。

原文:http://wiki.nginx.org/ChsHttpLimitZoneModule

substitutions4nginx

server
{ 
listen 205.105.100.110:80;
server_name www.baidu.net baidu.net;
sub_filter  'baidu.com'  'baidu.net';
sub_filter_once on;


location / { 
subs_filter_types text/html text/css text/xml text/javascript;
subs_filter baidu.com baidu.net;
proxy_set_header X-Real-IP $remote_addr; 
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
proxy_set_header Referer http://www.baidu.com[/url]; #强制定义Referer,程序验证判断会用到 
proxy_set_header Host www.baidu.com; #定义主机头,如果目标站点绑定的域名个server_name项的吻合则使用$host 
proxy_pass http://www.baidu.com; #指定目标,建议使用IP或者nginx自定义池 
proxy_redirect http://www.baidu.com [url]http://www.baidu.net; 
proxy_set_header Accept-Encoding ""; #清除编码 
} 
}

nginx 301 302跳转配置方法

首先看一个完整代码示例,关于nginx 301 302跳转的。 301跳转设置: server { listen 80; server_name 123.com; rewrite ^/(.*) http://456.com/$1 permanent; access_log off; } 302跳转设置: server { listen 80; server_name 123.com; rewrite ^/(.*) http://456.com/$1 redirect; access_log off; } 在看下关于nginx 301 302跳转的详细说明文档 server { server_name test.com; rewrite ^/(.*) http://www.test1.com/$1 permanent; } last – 基本上都用这个Flag。 break – 中止Rewirte,不在继续匹配 redirect – 返回临时重定向的HTTP状态302 permanent – 返回永久重定向的HTTP状态301 Nginx的重定向用到了Nginx的HttpRewriteModule,下面简单解释以下如何使用的方法: rewrite命令 nginx的rewrite相当于apache的rewriterule(大多数情况下可以把原有apache的rewrite规则加上引号就可以直接使用),它可以用在server,location 和IF条件判断块中,命令格式如下: rewrite 正则表达式 替换目标 flag标记 flag标记可以用以下几种格式: last – 基本上都用这个Flag。 break – 中止Rewirte,不在继续匹配 redirect – 返回临时重定向的HTTP状态302 permanent – 返回永久重定向的HTTP状态301 例如下面这段设定nginx将某个目录下面的文件重定向到另一个目录,$2对应第二个括号(.*)中对应的字符串: location /download/ { rewrite ^(/download/.*)/m/(.*)\..*$ $1/nginx-rewrite/$2.gz break; } nginx重定向的IF条件判断 在server和location两种情况下可以使用nginx的IF条件判断,条件可以为以下几种: 正则表达式 如: 匹配判断 ~ 为区分大小写匹配; !~为区分大小写不匹配 ~* 为不区分大小写匹配;!~为不区分大小写不匹配 例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下: if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; } 文件和目录判断 -f和!-f判断是否存在文件 -d和!-d判断是否存在目录 -e和!-e判断是否存在文件或目录 -x和!-x判断文件是否可执行 例如下面设定nginx在文件和目录不存在的时候重定向: if (!-e $request_filename) { proxy_pass http://127.0.0.1; } return 返回http代码,例如设置nginx防盗链: location ~* \.(gif|jpg|png|swf|flv)$ { valid_referers none blocked www.test.com www.test1.com; if ($invalid_referer) { return 404; } }

3种Nginx防盗链的方法

一般的防盗链如下:

location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.51099.com 51099.com ;
if ($invalid_referer) {
rewrite ^/ http://www.51099.com/retrun.html;
#return 403;
}
}

第一行:gif|jpg|png|swf|flv
表示对gif、jpg、png、swf、flv后缀的文件实行防盗链
第二行: 表示对51099.com www.51099.com这2个来路进行判断
if{}里面内容的意思是,如果来路不是指定来路就跳转到http://www.51099.com/retrun.html页面,当然直接返回403也是可以的。

二:针对图片目录防止盗链

location /images/ {
alias /data/images/;
valid_referers none blocked server_names *.xok.la xok.la ;
if ($invalid_referer) {return 403;}
}

三:使用第三方模块ngx_http_accesskey_module实现Nginx防盗链
实现方法如下:

实现方法如下:
1. 下载NginxHttpAccessKeyModule模块文件:Nginx-accesskey-2.0.3.tar.gz
2. 解压此文件后,找到nginx-accesskey-2.0.3下的config文件。编辑此文件:替换其中的”$HTTP_ACCESSKEY_MODULE”为”ngx_http_accesskey_module”;
3. 用一下参数重新编译nginx:
./configure --add-module=path/to/nginx-accesskey
4. 修改nginx的conf文件,添加以下几行:
location /download {
  accesskey             on;
  accesskey_hashmethod  md5;
  accesskey_arg         "key";
  accesskey_signature   "mypass$remote_addr";
}
其中:
accesskey为模块开关;
accesskey_hashmethod为加密方式MD5或者SHA-1;
accesskey_arg为url中的关键字参数;
accesskey_signature为加密值,此处为mypass和访问IP构成的字符串。

访问测试脚本download.php:
<?
$ipkey= md5("mypass".$_SERVER['REMOTE_ADDR']);
$output_add_key="<a href=http://www.51099.com/download/G3200507120520LM.rar?key=".$ipkey.">download_add_key</a><br />";
$output_org_url="<a href=http://www.51099.com/download/G3200507120520LM.rar>download_org_path</a><br />";
echo $output_add_key;
echo $output_org_url;
?>
访问第一个download_add_key链接可以正常下载,第二个链接download_org_path会返回403 Forbidden错误。

参考:
NginxHttpAccessKeyModule

nginx限速及连接数限制

在nginx.conf的http{}添加
limit_zone one $binary_remote_addr 10m;

然后在 虚拟机里写
location / {
limit_conn one 1; 线程
limit_rate 100k; 速度
表示限速100K 每个客户端只允许一个线程

最终速度=rate * conn

-----------------------------------------------------------------

limit_zone one $binary_remote_addr 32k;
server {
listen       80;
server_name  192.168.1.222;
location / {
root   /var/www/html;
index  index.html index.htm index.php;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
limit_conn one 2;
limit_rate 10k;
}


说明:

limit_zone,针对每个IP定义一个存储session状态的容器。要求大于等于32K。

limit_conn,限制每个IP发起的连接数,比如本实例设了2个,当我用IE进行单线程下载的时候还可以打开该站点的一个网页。而用迅雷下载时,迅雷会启用2个线程下载,所以当再去打开网页的时候,服务器端会返回错误请求。该值建议设置得高一些,比如15左右。

limit_rate,限制每个连接速度为10K,此限制是针对单个线程,比如这个例子,我用IE下载是10K,当用迅雷时它会占用2个线程,所以迅雷下载速度为20K,此实例也很好的解释了迅雷下载速度快的原因。

 

nginx 虚拟目录的配置

nginx貌似没有虚拟目录的说法,因为它本来就是完完全全根据目录来设计并工作的。

如果非要给nginx安上一个虚拟目录的说法,那就只有alias标签比较“像”,干脆来说说alias标签和root标签的区别吧。

最基本的区别:alias指定的目录是准确的,root是指定目录的上级目录,并且该上级目录要含有location指定名称的同名目录。另外,根据前文所述,使用alias标签的目录块中不能使用rewrite的break。

说不明白,看下配置:

location /abc/ {
alias /home/html/abc/;
}

在这段配置下,http://test/abc/a.html就指定的是/home/html/abc/a.html。这段配置亦可改成

location /abc/ {
root /home/html/;
}

这样,nginx就会去找/home/html/目录下的abc目录了,得到的结果是相同的。

但是,如果我把alias的配置改成:

location /abc/ {
alias /home/html/def/;
}

那么nginx将会从/home/html/def/取数据,这段配置还不能直接使用root配置,如果非要配置,只有在/home/html/下建立一个 def->abc的软link(快捷方式)了。

一般情况下,在location /中配置root,在location /other中配置alias是一个好习惯。

至于alias和root的区别,我估计还没有说完全,如果在配置时发现奇异问题,不妨把这两者换换试试。

将不同的HTTP User Agent请求转发到特定的后端服务器

假设我这里有大量图像、CSS、javascript等静态文件,分别放在后端服务器  192.168.1.5 和 192.168.1.6上,那么我如何利用nginx的反向代理功能将不同的 http_user_agent 请求发送到指定的服务器上呢?如 "Mozilla" 转发到 192.168.1.5 ,MSIE  转发到 192.168.1.6 。

Nginx web 服务器支持if条件表达式,由此来跳转或者使用不同的配置变量。在本文中需要使用 $http_user_agent 变量,它标记了用户浏览器的类别,版本以及操作系统的一些信息,语法如下:

if ( condition ){
  do_something
}
if ( $http_user_agent = "wget" ){
   do_something
}
if ( $http_user_agent ~ MSIE ){
   return 403;
}

if指令会就检查后面表达式的值是否为真(true),如果为真,则执行后面大括号中的内容。以下是一些条件表达式的比较方法:
1、变量的完整比较可以使用=或!=操作符
2、 部分匹配可以使用正则表达式来表示,~或~*
3、~表示区分大小写
4、~*表示不区分大小写(firefox与FireFox是一样的)
5、!~与!~* 是取反操作,也就是不匹配的意思
6、检查文件是否存在使用 -f 或 !-f 操作符
7、检查目录是否存在使用-d或!-d操作符
8、检查文件,目录或符号连接是否存在使用-e或!-e操作符
9、检查文件是否可执行使用-x或!-x操作符
10、正则表达式的部分匹配可以使用括号,匹配的部分在后面可以用$1~$9变量代替,这些和apache一致。

例子:

编辑 /usr/local/nginx/conf/nginx.conf 文件
#vi /usr/local/nginx/conf/nginx.conf
设置upstream服务器:

upstream myproxybackend  {
       server 192.168.1.1;
       server 192.168.1.2;
       server 192.168.1.3;
       server 192.168.1.4;
}
 
upstream msiebackend  {
       server 192.168.1.6;
}
 
upstream mozillabackend  {
       server 192.168.1.5;
}

更新虚拟主机配置文件

server {
      access_log  logs/access.log;
      error_log   logs/error.log;
      index       index.html;
      listen      202.54.1.5:80 default;
      root        /usr/local/nginx/html;
      server_name example.com www.example.com 0.example.com;
 
     ## PROXY - Web
      location / {
        proxy_pass  http://myproxybackend;
        if ($http_user_agent ~ MSIE ) {
              proxy_pass  http://msiebackend;
        }
        if ($http_user_agent ~ Mozilla ) {
              proxy_pass  http://mozillabackend;
        }
 
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
# many more...
# many more...
}

最后重启/重新载入nginx
#/usr/local/nginx/sbin/nginx -s reload

nginx单一端口域名转发

对于后端是同一端口多域名转发的nginx proxy。在nginx中的默认proxy是只能对后面real server做端口转发的,而不能做域名转发。
这个是因为默认

 
1 proxy_set_header Host $proxy_host;

这样就等于前端输入域名后到nginx这里直接转换成IP进行转发了。
于是我们需要修改proxy_set_header的参数

 
1 proxy_set_header Host $http_host;

例如下面一个举例。下面这个例子中backend1权重为5,其他默认为1,最大失效次数3次,如果30秒内没有响应就认为是失效了。

 
01 upstream lb  {
02 server backend1.test.com weight=5;
03 server backend2.test.com:8080 max_fails=3  fail_timeout=30s;
04 server unix:/tmp/test3;
05 }
06 server {
07         listen 80;
08         server_name  lb.test.com;
09         location  /     {
10         proxy_store off;
11         proxy_redirect  off;
12         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
13         proxy_set_header X-Real-IP $remote_addr;
14         proxy_set_header Host $http_host;
15         proxy_pass http://lb;
16         }
17 }
Records:301234