Nginx 技术研究html
1. Nginx安装
1.1. 准备的软件
Ø nginx-1.4.1.tar.gz前端
下载地址:http://nginx.org/en/download.html其中包含开发版和稳定版,到目前为止稳定版本最高版本号为1.4.1linux
Ø nginx-sticky-module-1.1.tar.gznginx
下载地址:http://code.google.com/p/nginx-sticky-module/downloads/listweb
1.2. 安装nginx-1.4.1.tar.gz
Ø 解压nginx-1.4.1.tar.gz正则表达式
[root@c-admin Nginx]#cd ..windows
[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.gztomcat
Ø 检查安装环境并配置
[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单进程工做的状况下,这个过程包含三种方式:
默认启动方式,启动新的nginx,命令: windows或linux下,./nginx
指定配置文件的启动方式,nginx –c conf/nginx.conf
指定安装目录的启动方式,nginx –p /usr/local/nginx
配置,命令: nginx –s reload
热替换nginx代码
Location
表示执行一个正则匹配,区分大小写
表示执行一个正则匹配,不区分大小写
表示普通字符匹配,若是该选项匹配,只匹配该选项,不匹配别的选项,通常用来匹配目录
进行普通字符精确匹配
定义一个命名的 location,使用在内部定向时,例如 error_page, try_files
通用匹配,任何请求都会匹配到。
精确匹配会第一个被处理。若是发现精确匹配,nginx中止搜索其余匹配。
普通字符匹配,正则表达式规则和长的块规则将被优先和查询匹配,也就是说若是该项匹配还需去看有没有正则表达式匹配和更长的匹配。
则只匹配该规则,nginx中止搜索其余匹配,不然nginx会继续处理其余location指令。
最后匹配理带有"~"和"~*"的指令,若是找到相应的匹配,则nginx中止搜索其余匹配;当没有正则表达式或者没有正则表达式被匹配的状况下,那么匹配程度最高的逐字匹配指令会被使用。
(网上验证)
Server
nginx以名字查找虚拟主机时,若是名字能够匹配多于一个主机名定义,好比同时匹配了通配符的名字和正则表达式的名字,那么nginx按照下面的优先级别进行查找,并选中第一个匹配的虚拟主机:
确切的名字;
最长的以星号起始的通配符名字:*.example.org;
最长的以星号结束的通配符名字:mail.*;
第一个匹配的正则表达式名字(按在配置文件中出现的顺序)。
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 已经处理完正在等候下一次请求指令的驻留链接
经过命令查看
#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版本等),您能够删除这些文件,也可使用本文的方法将其屏蔽。
禁止访问文件类型
如,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;
}
禁止访问某个目录
location ~ ^/(WEB-INF)/ {
deny all;
}
禁止某个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;
}
规则按顺序检测,至道第一个匹配的规则出现。在这个例子中,只容许IPV4的10.1.1.0/16和192.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地址及网段都不能够访问
限制下载连接
在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。
限速
nginx能够经过HTTPLimitZoneModule和HTTPCoreModule两个组件来对目录进行限速。
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, 能够处理320000个session。
limit_conn one 1:限制每一个IP只能发起一个并发链接。
limit_rate 300k: 对每一个链接限速300k. 注意,这里是对链接限速,而不是对IP限速。若是一个IP容许两个并发链接,那么这个IP就是限速limit_rate×2。
注意:limit_zone只能定义在http做用域,limit_conn和limit_rate能够定义在http server location做用域。
限制某一时间段内同一ip链接数
http{
#定义一个名为allips的limit_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;
}
文件上传大小限制
配置文件里加入以下,具体大小根据你本身的业务作调整。
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: 默认为1,weight越大,负载的权重就越大。
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,而后是 backend1、backend2、backend3……在大多数应用场景中,这样并不高效。固然,也正因如此,Nginx 为你提供了一个按照 Michael、Jason、David 等等这些乱七八糟的用户的 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 的默认值为 1,fail_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 Sticky:wget 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作负载均衡
expires:cookie过时时间,默认浏览器关闭就过时,也就是会话方式。
no_fallbackup:若是设置了这个,cookie对应的服务器宕机了,那么将会返回502(bad 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下的某个客户端和某个后端就能创建起稳固的session,ip_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,就不能根据ip做hash。譬如使用的是squid为最前端,那么nginx取ip时只能获得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来决定将请求发送给后端的哪一个server,nginx_upstream_jvm_route会在用户第一次请求后端server时,将响应的server标识绑定到cookie中的JSESSIONID中,从而当用户发起下一次请求时,nginx会根据JSESSIONID来决定由哪一个后端server来处理。
1.nginx_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
2.nginx配置:
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