nginx_技术研究报告
nginx_技术研究报告
明泽妈妈 发表于4年前
nginx_技术研究报告
  • 发表于 4年前
  • 阅读 264
  • 收藏 22
  • 点赞 1
  • 评论 0

腾讯云 学生专属云服务套餐 10元起购>>>   

摘要: nginx监控、负载均衡策略、nginx会话亲和、多应用配置、访问控制等

                                                    Nginx   技术研究

1. Nginx安装

1.1. 准备的软件

Ø  nginx-1.4.1.tar.gz

下载地址:http://nginx.org/en/download.html其中包含开发版和稳定版,到目前为止稳定版本最高版本号为1.4.1

Ø  nginx-sticky-module-1.1.tar.gz

下载地址:http://code.google.com/p/nginx-sticky-module/downloads/list

1.2. 安装nginx-1.4.1.tar.gz

Ø  解压nginx-1.4.1.tar.gz

[root@c-admin Nginx]#cd ..

[root@c-admin Nginx]#tar zxvf nginx-1.4.1.tar.gz

Ø  解压nginx-sticky-module-1.1.tar.gz

[root@c-admin Nginx]#tar zxvf nginx-sticky-module-1.1.tar.gz

Ø  检查安装环境并配置

[root@c-admin Nginx]#cd nginx-1.4.1

[root@c-admin Nginx]#./configure --add-module= /root/nginx-sticky-module-1.1

Ø  安装

[root@c-admin Nginx]#make && make install

Ø  启动nginx

进入Nginx 默认安装目录/usr/local/nginx/sbin目录.

[root@c-admin sbin]#./nginx

1.3. 可能的错误

1.      错误1:                                       

解决:

32为操作系统执行:ln -s /usr/local/lib/libpcre.so.1  /lib

64为操作系统执行:ln -s /usr/local/lib/libpcre.so.1  /lib64

2.      错误2

提示在头文件中已经定义了NGX_SENDFILE_LIMIT。且在文件nginx-1.4.1/src/unix/ngx_linux_sendfile_chain.c中重新定义,重定义错误。

              解决:

修改文件nginx-1.4.1/src/unix/ngx_linux_sendfile_chain.c 27行代码#define NGX_SENDFILE_LIMIT  2147483647L修改为#define NGX_SENDFILE_LIMIT  0x80000000

Ø  验证安装是否成功

在浏览器地输入 http://127.0.0.1 如果出现以下类似页面代表安装成功

2. Nginx启动方式

在不考虑nginx单进程工作的情况下,这个过程包含三种方式:

  1. 默认启动方式,启动新的nginx,命令: windowslinux下,./nginx

  2. 指定配置文件的启动方式,nginx –c conf/nginx.conf

  3. 指定安装目录的启动方式,nginx –p /usr/local/nginx

  4. 配置,命令: nginx –s reload

  5. 热替换nginx代码

  6. Location

  7. 表示执行一个正则匹配,区分大小写

  8. 表示执行一个正则匹配,不区分大小写

  9. 表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录

  10. 进行普通字符精确匹配

  11. 定义一个命名的 location,使用在内部定向时,例如 error_page, try_files

  12. 通用匹配,任何请求都会匹配到。

  13. 精确匹配会第一个被处理。如果发现精确匹配,nginx停止搜索其他匹配。

  14. 普通字符匹配,正则表达式规则和长的块规则将被优先和查询匹配,也就是说如果该项匹配还需去看有没有正则表达式匹配和更长的匹配。

  15. 则只匹配该规则,nginx停止搜索其他匹配,否则nginx会继续处理其他location指令。

  16. 最后匹配理带有"~""~*"的指令,如果找到相应的匹配,则nginx停止搜索其他匹配;当没有正则表达式或者没有正则表达式被匹配的情况下,那么匹配程度最高的逐字匹配指令会被使用。

  17. (网上验证)

  18. Server

nginx以名字查找虚拟主机时,如果名字可以匹配多于一个主机名定义,比如同时匹配了通配符的名字和正则表达式的名字,那么nginx按照下面的优先级别进行查找,并选中第一个匹配的虚拟主机:

  1. 确切的名字;

  2. 最长的以星号起始的通配符名字:*.example.org

  3. 最长的以星号结束的通配符名字:mail.*

  4. 第一个匹配的正则表达式名字(按在配置文件中出现的顺序)。

2. Nginx监控

通过查看Nginx的并发连接,我们可以更清除的知道网站的负载情况。Nginx并发查看有两种方法(之所以这么说,是因为笔者只知道两种),一种是通过web界面,一种是通过命令,web查看要比命令查看显示的结果精确一些。下面介绍这两种查看方法

通过web界面查看时Nginx需要开启status模块,也就是安装Nginx时加上–with-http_stub_status_module   然后配置Nginx.conf,在server点里面加入如下内容

location /nginx_status {

stub_status on;

access_log off;

allow 192.168.1.100;  访问IP

deny all;

}

配置完后重新启动Nginx后我们可以通过浏览器访问http://localhost/status 查看,如下图

解析:

Active connections    //当前 Nginx 正处理的活动连接数。

server accepts handledrequests //总共处理了8 个连接 , 成功创建 8 次握手,总共处理了500个请求。

Reading //nginx 读取到客户端的 Header 信息数。

Writing //nginx 返回给客户端的 Header 信息数。

Waiting //开启 keep-alive 的情况下,这个值等于 active – (reading + writing),意思就是 Nginx 已经处理完正在等候下一次请求指令的驻留连接

  1. 通过命令查看

#netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

TIME_WAIT 17

ESTABLISHED 3254

LAST_ACK 236

FIN_WAIT_1 648

FIN_WAIT_2 581

CLOSING 7

CLOSE_WAIT 4916

解析:

CLOSED  //无连接是活动的或正在进行

LISTEN  //服务器在等待进入呼叫

SYN_RECV  //一个连接请求已经到达,等待确认

SYN_SENT  //应用已经开始,打开一个连接

ESTABLISHED  //正常数据传输状态/当前并发连接数

FIN_WAIT1  //应用说它已经完成

FIN_WAIT2  //另一边已同意释放

ITMED_WAIT  //等待所有分组死掉

CLOSING  //两边同时尝试关闭

TIME_WAIT  //另一边已初始化一个释放

LAST_ACK  //等待所有分组死掉

3. Nginx访问控制

考虑到很多企业及个人的网站大都使用各种CMS,而攻击者在进行攻击之前,都会根据一些细节判断对方使用的系统,再进行针对性的攻击。很多CMS发行后,在一些目录或多或少都留下了部分.txt等文本信息(黑客已此判断此CMS版本等),您可以删除这些文件,也可以使用本文的方法将其屏蔽。

  1. 禁止访问文件类型

如,Nginx下禁止访问*.txt,doc文件,配置方法如下:

方法1(不准浏览器get命令访问,使用迅雷是可以将文件下来的,防止手工判断)

location ~* \.(txt|doc)$ {

if (-f $request_filename) {

root /data/www/wwwroot/linuxtone/test;

break;

   }

 }

方法2: (什么都不准访问,可能影响爬虫robots.txt以及一些txt调用)

location ~* \.(txt|doc)${

root /data/www/wwwroot/linuxtone/test;

deny all;

  }

  1. 禁止访问某个目录

location ~ ^/(WEB-INF)/ {

deny all;

  } 

  1. 禁止某个IP或网段访问使用ngx_http_access_module限制ip访问

location / {

deny    192.168.1.1;

allow   192.168.1.0/24;

allow   10.1.1.0/16;

deny    all;

  }

规则按顺序检测,至道第一个匹配的规则出现。在这个例子中,只允许IPV410.1.1.0/16192.168.1.0/24中除去192.168.1.1来访问,其他的客户端ip访问都是不允许的。
为了预防有太多的规则,使用模块ngx_http_geo_module是更可取的

语法:allow address | CIDR | all;
默认:

所属指令:
http, server, location, limit_except
指定的IP地址己网段都可以访问。

语法:deny address | CIDR | all;

默认:
所属指令:
http, server, location, limit_except
指定的IP地址及网段都不可以访问

  1. 限制下载链接

http{}里面,加上这句:

limit_zone one $binary_remote_addr 10m;

然后,在server{}里面加上下面这段:

location / {
        limit_conn one 1;
        limit_rate 100k;
}

这里limit_conn one 1是指一个IP只能用一个线程下载。limit_rate 100k是指最大只能下载100k

  1. 限速

nginx可以通过HTTPLimitZoneModuleHTTPCoreModule两个组件来对目录进行限速。

http {

  limit_zone   one  $binary_remote_addr  10m; 

  server {

location /download/ {

      limit_conn   one  1;

      limit_rate 300k;
           }

  }

}

limit_zone: 是针对每个IP定义一个存储session状态的容器.这个示例中定义了一个10m的容器,按照32bytes/session 可以处理320000session

limit_conn one 1:限制每个IP只能发起一个并发连接。

limit_rate 300k 对每个连接限速300k. 注意,这里是对连接限速,而不是对IP限速。如果一个IP允许两个并发连接,那么这个IP就是限速limit_rate×2

注意:limit_zone只能定义在http作用域,limit_connlimit_rate可以定义在http server location作用域。

  1. 限制某一时间段内同一ip连接数

http{

    #定义一个名为allipslimit_req_zone用来存储session,大小是10M内存,

  #$binary_remote_addr key,限制平均每秒的请求为20个,

 #1M能存储16000个状态,rete的值必须为整数,如果限制两秒钟一个请求,可以设置成30r/m

     limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;

   }

  1. 文件上传大小限制

配置文件里加入如下,具体大小根据你自己的业务做调整。

client_max_body_size 10m;    

4. 一个nginx存在多个应用的情况

Nginx.conf配置如下:

#gzip  on;

    upstream myserver{

        server 192.168.51.50:8080;

    }

    upstream mytest{

        server 192.168.51.106:8080;

    }

    server {

        listen       81;

        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {

            root   html;

            proxy_pass  http://myserver; 

            proxy_set_header  X-Real-IP  $remote_addr; 

            client_max_body_size  100m;

          #  index  index.html index.htm;

        }

        location /jspds {

            root   html;

            proxy_pass  http://myserver/jspDS; 

            proxy_set_header  X-Real-IP  $remote_addr; 

            client_max_body_size  100m;

          #  index  index.html index.htm;

        }

        location /helloworld {

            root   html;

            proxy_pass  http://mytest/helloWorld; 

            proxy_set_header  X-Real-IP  $remote_addr; 

            client_max_body_size  100m;

          #  index  index.html index.htm;

        }

5. Nginx负载均衡策略

5.1. 第一种:轮询

upstream test{

server 192.168.0.1:3000;

server192.168.0.1:3001;

}

5.2. 第二种:权重

upstream test{

server 192.168.0.1 weight=2;

server 192.168.0.2 weight=3;

}

这种模式可解决服务器性能不等的情况下轮询比率的调配

5.3. 第三种:ip_hash

upstream test{

    ip_hash;

server 192.168.0.1;

server 192.168.0.2;

}

这种模式会根据来源IP和后端配置来做hash分配,确保固定IP只访问一个后端

5.4. 第四种:fair

需要安装Upstream Fair Balancer Module

upstream test{

server 192.168.0.1;

server 192.168.0.2;

fair;

}

这种模式会根据后端服务的响应时间来分配,响应时间短的后端优先分配

5.5. 第五种:自定义hash

需要安装Upstream Hash Module

upstream test{

server 192.168.0.1;

server 192.168.0.2;

hash $request_uri;

}

这种模式可以根据给定的字符串进行Hash分配

具体应用:

server{

listen 80;

    server_name .test.com;

charset utf-8;

location / {

        proxy_pass http://test/;

    }

}

此外upstream每个后端的可设置参数为:

1.down: 表示此台server暂时不参与负载。

2.weight: 默认为1weight越大,负载的权重就越大。

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

4.fail_timeout: max_fails次失败后,暂停的时间。

5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器,应急措施。

默认负载均衡策略

Nginx 提供轮询(round robin)、用户 IP 哈希(client IP)和指定权重 3 种方式。

默认情况下,Nginx 会为你提供轮询作为负载均衡策略。但是这并不一定能够让你满意。比如,某一时段内的一连串访问都是由同一个用户 Michael 发起的,那么第一次 Michael 的请求可能是 backend2,而下一次是 backend3,然后是 backend1backend2backend3……在大多数应用场景中,这样并不高效。当然,也正因如此,Nginx 为你提供了一个按照 MichaelJasonDavid 等等这些乱七八糟的用户的 IP hash 的方式,这样每个 client 的访问请求都会被甩给同一个后端服务器。具体的使用方式如下:

upstream backend {

    ip_hash;

server backend1.example.com;

server backend2.example.com;

    server.backend3.example.com;

}

这种策略中,用于进行 hash 运算的 key,是 client C IP 地址(C IP 地址就是范围在 192.0.0.0 223.255.255.255 之间,前三段号码表示子网,第四段号码为本地主机的 IP 地址类别)。这样的方式保证一个 client 每次请求都将到达同一个 backend。当然,如果所 hash 到的 backend 当前不可用,则请求会被转移到其他 backend

再介绍一个和 ip_hash 配合使用的关键字:down。当某个一个 server 暂时性的宕机(down)时,你可以使用“down”来标示出来,并且这样被标示的 server 就不会接受请求去处理。具体如下:

upstream backend {

server blog.csdn.net/poechant down;

server 145.223.156.89:8090;

server unix:/tmp/backend3;

}

还可以使用指定权重(weight)的方式,如下:

upstream backend {

server backend1.example.com;

server 123.321.123.321:456 weight=4;

}

默认情况下 weight 1,对于上面的例子,第一个 server 的权重取默认值 1,第二个是 4,所以相当于第一个 server 接收 20% 的请求,第二接收 80% 的。要注意的是 weight ip_hash 是不能同时使用的,原因很简单,他们是不同且彼此冲突的策略。

重试策略

可以为每个 backend 指定最大的重试次数,和重试时间间隔。所使用的关键字是 max_fails fail_timeout。如下所示:

upstream backend {

server backend1.example.com weight=5;

server 54.244.56.3:8081 max_fails=3 fail_timeout=30s;

}

在上例中,最大失败次数为 3,也就是最多进行 3 次尝试,且超时时间为 30秒。max_fails 的默认值为 1fail_timeout 的默认值是 10s。传输失败的情形,由 proxy_next_upstream fastcgi_next_upstream 指定。而且可以使用 proxy_connect_timeout proxy_read_timeout 控制 upstream 响应时间。

有一种情况需要注意,就是 upstream 中只有一个 server 时,max_fails fail_timeout 参数可能不会起作用。导致的问题就是 nginx 只会尝试一次 upstream 请求,如果失败这个请求就被抛弃了 : ( ……解决的方法,比较取巧,就是在 upstream 中将你这个可怜的唯一 server 多写几次,如下:

upstream backend {

server backend.example.com max_fails fail_timeout=30s;

server backend.example.com max_fails fail_timeout=30s;

server backend.example.com max_fails fail_timeout=30s;

}

5.6. 备机策略

Nginx 0.6.7 版本开始,可以使用“backup”关键字。当所有的非备机(non-backup)都宕机(down)或者繁忙(busy)的时候,就只使用由 backup 标注的备机。必须要注意的是,backup 不能和 ip_hash 关键字一起使用。举例如下:

upstream backend {

server backend1.example.com;

server backend2.example.com backup;

server backend3.example.com;

}

6. Nginx会话亲和

6.1. session sticky方式

1. 下载 Session Stickywget https://nginx-sticky-module.googlecode.com/files/nginx-sticky-module-1.1.tar.gz

2. 安装模块

如果 Nginx 之前已经安装了,可以通过 nginx -V 命令查看当时编译的参数。在参数后面追加安装 Session Sticky 模块的参数,避免影响之前 Nginx 已有模块。

进入 nginx 源码目录,执行命令:

./configure …  --add-module=/usr/local/src/nginx-sticky-module-1.1

Make

make install

3. 激活模块:在 upstream块中添加 sticky; 即可激活Session Sticky模块。

upstream {

sticky;

server 127.0.0.1:9000;

server 127.0.0.1:9001;

server 127.0.0.1:9002;

}

4. 可用选项:

sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h] [hash=index|md5|sha1] [no_fallback];

name: 可以为任何的string字符,默认是route

domain:哪些域名下可以使用这个cookie

path:哪些路径对启用sticky,例如path/test,那么只有test这个目录才会使用sticky做负载均衡

expirescookie过期时间,默认浏览器关闭就过期,也就是会话方式。

no_fallbackup:如果设置了这个,cookie对应的服务器宕机了,那么将会返回502bad gateway 或者 proxy error),建议不启用。

nginx sticky使用注意事项:nginx sticky模块不能与ip_hash同时使用

5. ngix sticky模块工作流程图:

首先根据轮询RR随机到某台后端,然后在响应的Set-Cookie上加上route=md5(upstream)字段,第二次请求再处理的时候,发现有route字段,直接导向原来的那个节点。

6. 测试nginx sticky

我后端是两台tomcat服务器,每台服务器的JESSIONED值都有特殊的标志。比如209这台是s209,225这台是s225.打开页面,不管怎么刷新JESSIONED值都是不变.但是如果开启了sticky,可以看到JESSIONED值不会发生变化.死死的粘滞在其中一台服务器上.测试图如下:

使用sticky的情况下,不管怎么刷新都是下面图

6.2. ip_hash模式(不推荐使用)

nginx中的ip_hash技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的sessionip_hash是在upstream配置中定义的:

upstream backend {  

server 127.0.0.1:8080 ;  

    server 127.0.0.1:9090 ;  

ip_hash;  

        }  

不推荐使用的原因如下:

1.nginx不是最前端的服务器。

   ip_hash要求nginx一定是最前端的服务器,否则nginx得不到正确ip,就不能根据iphash。譬如使用的是squid为最前端,那么nginxip时只能得到squid的服务器ip地址,用这个地址来作分流是肯定错乱的。

2. nginx的后端还有其它方式的负载均衡。

假如nginx后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一台session应用服务器上。

3.多个外网出口。

很多公司上网有多个出口,多个ip地址,用户访问互联网时候自动切换ip。而且这种情况不在少数。使用 ip_hash 的话对这种情况的用户无效,无法将某个用户绑定在固定的tomcat上。

6.3. nginx_upstream_jvm_route(nginx扩展,推荐使用)

nginx_upstream_jvm_route 是一个nginx的扩展模块,用来实现基于 Cookie Session Sticky 的功能。

简单来说,它是基于cookie中的JSESSIONID来决定将请求发送给后端的哪个servernginx_upstream_jvm_route会在用户第一次请求后端server时,将响应的server标识绑定到cookie中的JSESSIONID中,从而当用户发起下一次请求时,nginx会根据JSESSIONID来决定由哪个后端server来处理。

1nginx_upstream_jvm_route安装

下载地址(svn)http://nginx-upstream-jvm-route.googlecode.com/svn/trunk/

假设nginx_upstream_jvm_route下载后的路径为/usr/local/nginx_upstream_jvm_route

(1)进入nginx源码路径

patch -p0 < /usr/local/nginx_upstream_jvm_route/jvm_route.patch

(2)./configure  --with-http_stub_status_module --with-http_ssl_module --prefix=/usr/local/nginx --with-pcre=/usr/local/pcre-8.33 --add-module=/usr/local/nginx_upstream_jvm_route

(3)make& make install

关于nginx的下载与安装参考:http://hanqunfeng.iteye.com/blog/697696

2nginx配置:

upstream  tomcats_jvm_route 

{

server   192.168.33.10:8090 srun_id= instance1;  

server   192.168.33.11:8090 srun_id= instance2; 

    jvm_route $cookie_JSESSIONID|sessionid reverse; 

 } 

 3 应用服务器配置

loong服务器上增加jvmRoute参数如下:

在集群上创建jvm参数

1. asadmin create-jvm-options --target cluster1 "-DjvmRoute=\${INSTANCE_NAME}"

2. asadmin create-system-properties --target INSTANCE_NAME=instance1

3. asadmin create-system-properties --target instance2 INSTANCE_NAME=instance2

共有 人打赏支持
粉丝 2
博文 2
码字总数 12193
×
明泽妈妈
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: