nginx一个轻量级的web服务器,同时可以作为反向代理服务器,将web请求分发至后端的realserver。作为webserver 和proxy-server nginx本身来说有什么优点呢?
1、作为web服务器
并发量高,在30000的并发量下,在nginx+PHP(fastcgi)架构下,开启10个nginx进程会消耗10*15=150M内存,开启64个CGI进程会消耗64*20=1280M内存。在内存、cpu的消耗量不是很大的情况下,实现了高并发量。
nginx选用的是epoll网络I/O模型,而apace则采用的是select,所以nginx的处理速度更快。
在10000个非活动连接的长连接的情况下。只需要消耗2.5M内存。
在启动nginx后,主进程master会生成相应数量的worker进程。worker进程用来接收client的请求。如果我们的服务器配置发生了改变。原来已经生成的并且正在为client提供请求的进程继续使用原来的配置。当服务结束之后,master进程将老配置的worker进程终止,在重新生成新的进程。
2、作为proxy服务器
比较流行的反向代理服务器有nginx,haproxy,lvs等,三种反向代理服务器有各自的优缺点:
lvs是基于四层实现的负载均衡,所谓的四层基于的是socket实现反向代理,比如说把A的80请求全部代理到B的80上去。lvs工作四层之上,仅做分发之用,不会产生额外的开销,这就决定的了lvs的性能超强,其对内存和cpu的开销都是很小的。
lvs在代理的过程中,DR单纯的把请求分发到后面的realserver,realserver直接对client端进行响应。所以lvs的分发性能是其他的反向代理服务器不能比较的。
lvs请求图示(DR模型)
nginx对于lvs而言,首先nginx是工作在七层之上的反向代理服务器。所谓的七层表示nginx可以针对某个目录,某个url来进行反向代理。比如说把A服务器的 /app01/这个目录代理到B服务器的/app01/目录。这样就实现了基于应用的反向代理。同时nginx可以实现对后端服务器的健康检查,当分发的请求发生错误之后,会将请求重新分发到另外的realserver,同样nginx可以承受大并发请求,且采用异步请求处理,减轻了后端服务器的压力。
haproxy本身作为作为反向代理服务器,会比nginx具有更好的处理速度,而且可以解决nginx出现的session共享问题。(nginx可以采用ip_hash的调度方法解决)。haproxy同样可以对后端服务器进行健康检查。但是haproxy的配置相对于nginx来说略微复杂(个人意见仅供参考)。
nginx反向代理图示
How nginx
nginx无论作为web服务器还是反向代理服务器,location和正则表达式的灵活应用都是他的一大优势,可以任意的匹配我们想进行操作的url,并对相应的url做rewrite和proxy_pass处理。对于nginx的location匹配我有话说。
1
location分类:正则location和普通的location
正则location:以”~”和”~*”开头,其中*好表示后面的正则表达式忽略大小写
普通location:“=”,“^~ ”和“@ ”和无任何前缀的都属于普通location 。
2
如果nginx配置中两种location都存在,先匹配那个呢,另外location的匹配和书写的顺序有关系吗?
在正则location和普通location都存在的时候,location的匹配规则是先匹配普通的location,在匹配普通location的过程中,遵循的是最长匹配原则。然后再匹配正则的location,但后边匹配到的正则location会覆盖掉先前的普通的location,除非普通的location是完全匹配的。
下面用几个简单的例子加以说明:
1、location =/ {
}
2、location / {
}
3、location ^~ /image/ {
}
4、 location ~* \.(gif|jpg|jpeg)${
}
请求:
/ ----->匹配第一个url
/documents/docment.html ----->匹配第二个url
/images/boc.gif ----->匹配第三个url
/documents/boc.jpg ----->匹配第四个url
解析
1:如果location中明确标注了=号,那么此location只能精确的匹配根/这个location,因为此时是精确匹配,所以不再进行正则的匹配。
2:/documents/docment.html只有/这个location会匹配。虽然前缀不是那么长,但是在这四个location中算是最长的匹配。
3:/images/boc.gif,这个url首先会匹配到/这个普通的location和/image/这两个,但是/image/的匹配前缀更长,所以选择后面的进行匹配。~^表示的是在匹配的过程中,匹配完普通location之后不在进行正则的匹配。
4:/documents/boc.jpg 首先会匹配到/,然后进行正则的匹配,会匹配到最后的~* \.(gif|jpg|jpeg)$,匹配到之后,正则的会把普通的覆盖掉。
location匹配进阶
server {
listen 80;
server_name www.mingpaixinxi.com.cn;
location /boc/test.html {
allow all;
}
location ^~ / {
root html;
index index.html index.htm;
deny all;
}
location ~ \.html$ {
allow all;
}
}
分别访问 curl -I http://www.mingpaixinxi.com.cn/,http://www.mingpaixinxi.com.cn/a.html,http://www.mingpaixinxi.com.cn/boc/test.html,http://www.mingpaixinxi.com.cn/test.html。
总结:为什么除了/boc/test.html之外,其余根开始匹配的全部都返回的是403呢,因为在匹配的过程中,匹配到根路径之后,前面^~说明就不在进行正则的匹配。所以直接执行了里面的deny all请求,所以返回了403。
如果我们把前面的^~符号去掉会发生什么呢?
server {
listen 80;
server_name www.mingpaixinxi.com.cn;
location /boc/test.html {
allow all;
}
location / {
root html;
index index.html index.htm;
deny all;
}
location ~ \.html$ {
allow all;
}
}
总结:除了根的匹配之外,其余的全部是404的返回值,为什么呢,因为location /之后还会进行正则的匹配,结果匹配到了 ~ \.html$ 就会把最开始的进行覆盖,执行里面的allow all(虽然是allow all,但是没有文件,返回是404,404表明请求已经到达了服务器,但是服务器不存在客户端请求的文件,而403表示的是请求根本没有到达服务器直接被拒绝掉,这两个存在本质的区别)就返回了404状态吗。
location的匹配规则你懂了吗?
总结
普通location会先于正则location进行匹配。
如果匹配到普通之后,想结束不再匹配正则的location,那么可以在普通的location前面加上 ^~这两个符号。
如果继续匹配正则location,正则匹配到的结果会覆盖普通匹配到的结果。
匹配正则的过程中,和正则的为上下位置有关系,因为正则location是匹配到一个随即停止匹配。并不存在普通location的最大前缀匹配原则。
3
nginx rewrite规则
在nginx中rewrite可以使我们将url进行灵活的转换,但是nginx在转换的过程中会有许多的坑,下面的这些坑你踩过吗?
rewrite既可以写在server中又可以写在location中,但是写在这两个中有什么区别呢,会有什么先后的顺序吗?
答案是肯定的,如果两者同时出现的话,首先会匹配的是server中的rewrite规则,然后进行匹配的是location中的rewrite规则,那server中location匹配完了之后会在继续匹配location中的rewrite规则吗?如果想解决这个问题,需要简要的说下rewrite的4个flag位。
1、last:匹配完当前的uri之后不在进行匹配。
2、break:匹配完当前的uri之后不在进行匹配。
3、permanent:永久重定向,http请求返回码301。
4、redirect:临时重定向,http请求返回码302。
没看错吧,为什么last和break的定义一样呢?解析的是从官方翻译过来的,下面看几个例子。
server {
listen 80;
server_name www.mingpaixinxi.com.cn ;
root html;
rewrite_log on; # 打开 URL 重写模块的日志开关,以便写入 error_log
location /aaa.html {
rewrite "^/aaa\.html$" /bbb.html;
rewrite "^/bbb\.html$" /ddd.html;
}
location /bbb.html {
rewrite "^/bbb\.html$" /ccc.html;
}
}
请求:
curl http://www.mingpaixinxi.com.cn/aaa.html
返回bbb.html,这个应该不难理解,先是匹配自己location中的uri规则,之后生成的新的uri也会继续匹配,直到匹配完成。
server {
listen 80;
server_name www.mingpaixinxi.com.cn ;
root html;
rewrite_log on; # 打开 URL 重写模块的日志开关,以便写入 error_log
location /aaa.html {
rewrite "^/aaa\.html$" /bbb.html last;
rewrite "^/bbb\.html$" /ddd.html;
}
location /bbb.html {
rewrite "^/bbb\.html$" /ccc.html;
}
}
curl http://www.mingpaixinxi.com.cn/aaa.html
返回ccc.html
为什么会返回的是ccc.html呢,因为rewrite "^/aaa\.html$" /bbb.html last;后面的flag位last,这表明停止当前location中的uri的继续的匹配,但是重新生成的uri不会停止匹配,会继续匹配其他的location,所以匹配到了 /bbb.html,所以返回的是ccc.html。
erver {
listen 80;
server_name www.mingpaixinxi.com.cn ;
root html;
rewrite_log on; # 打开 URL 重写模块的日志开关,以便写入 error_log
location /aaa.html {
rewrite "^/aaa\.html$" /bbb.html break;
rewrite "^/bbb\.html$" /ddd.html;
}
location /bbb.html {
rewrite "^/bbb\.html$" /ccc.html;
}
}
请求:
curl http://www.mingpaixinxi.com.cn/aaa.html
返回bbb.html,当遇到break之后,停止一切的匹配。从此处结束。所以说break比last的力度会更大些。就好像是程序里面的循环一样,遇到break之后,结束所有的循环。
同样,如果rewrite规则同时在server和location中出现,server的总是先于location的匹配,直到匹配结束。
nginx的rewrite规则你了解了吗?
Use nginx
核心配置
upstream boc {
server 192.168.1.1 weight=1 max_fails=2 fail_timeout=2;
server 192.168.1.2 weight=1 max_fails=2 fail_timeout=2;
}
server
{
listen 80;
server_name www.mingpaixinxi.com;
location / {
proxy_pass http://boc;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log off;
}
在这里,定义了一个web的集群,包含两台realserver,并定义了健康检查的规则。当client访问www.mingpaixinxi.com.cn这个域名的时候,前方的nginx就会把请求发送到192.168.1.1和192.168.1.2这两台服务器,默认的分配规则是roundrobin。
上面简单的对nginx作为反向代理服务器和其他的几款反向代理软件简单的做了些比较,也介绍了些nginx中的location和反向代理集群的配置。无论是nginx还是haproxy亦或是lvs。都有自己的优势和不足的地方。没有那个好那个坏的区分。在应用中,选择自己合适的才是最好的。正所谓无论白猫还是黑猫,能抓到老鼠的都是好猫。
1、作为web服务器
并发量高,在30000的并发量下,在nginx+PHP(fastcgi)架构下,开启10个nginx进程会消耗10*15=150M内存,开启64个CGI进程会消耗64*20=1280M内存。在内存、cpu的消耗量不是很大的情况下,实现了高并发量。
nginx选用的是epoll网络I/O模型,而apace则采用的是select,所以nginx的处理速度更快。
在10000个非活动连接的长连接的情况下。只需要消耗2.5M内存。
在启动nginx后,主进程master会生成相应数量的worker进程。worker进程用来接收client的请求。如果我们的服务器配置发生了改变。原来已经生成的并且正在为client提供请求的进程继续使用原来的配置。当服务结束之后,master进程将老配置的worker进程终止,在重新生成新的进程。
2、作为proxy服务器
比较流行的反向代理服务器有nginx,haproxy,lvs等,三种反向代理服务器有各自的优缺点:
lvs是基于四层实现的负载均衡,所谓的四层基于的是socket实现反向代理,比如说把A的80请求全部代理到B的80上去。lvs工作四层之上,仅做分发之用,不会产生额外的开销,这就决定的了lvs的性能超强,其对内存和cpu的开销都是很小的。
lvs在代理的过程中,DR单纯的把请求分发到后面的realserver,realserver直接对client端进行响应。所以lvs的分发性能是其他的反向代理服务器不能比较的。
lvs请求图示(DR模型)
nginx对于lvs而言,首先nginx是工作在七层之上的反向代理服务器。所谓的七层表示nginx可以针对某个目录,某个url来进行反向代理。比如说把A服务器的 /app01/这个目录代理到B服务器的/app01/目录。这样就实现了基于应用的反向代理。同时nginx可以实现对后端服务器的健康检查,当分发的请求发生错误之后,会将请求重新分发到另外的realserver,同样nginx可以承受大并发请求,且采用异步请求处理,减轻了后端服务器的压力。
haproxy本身作为作为反向代理服务器,会比nginx具有更好的处理速度,而且可以解决nginx出现的session共享问题。(nginx可以采用ip_hash的调度方法解决)。haproxy同样可以对后端服务器进行健康检查。但是haproxy的配置相对于nginx来说略微复杂(个人意见仅供参考)。
nginx反向代理图示
How nginx
nginx无论作为web服务器还是反向代理服务器,location和正则表达式的灵活应用都是他的一大优势,可以任意的匹配我们想进行操作的url,并对相应的url做rewrite和proxy_pass处理。对于nginx的location匹配我有话说。
1
location分类:正则location和普通的location
正则location:以”~”和”~*”开头,其中*好表示后面的正则表达式忽略大小写
普通location:“=”,“^~ ”和“@ ”和无任何前缀的都属于普通location 。
2
如果nginx配置中两种location都存在,先匹配那个呢,另外location的匹配和书写的顺序有关系吗?
在正则location和普通location都存在的时候,location的匹配规则是先匹配普通的location,在匹配普通location的过程中,遵循的是最长匹配原则。然后再匹配正则的location,但后边匹配到的正则location会覆盖掉先前的普通的location,除非普通的location是完全匹配的。
下面用几个简单的例子加以说明:
1、location =/ {
}
2、location / {
}
3、location ^~ /image/ {
}
4、 location ~* \.(gif|jpg|jpeg)${
}
请求:
/ ----->匹配第一个url
/documents/docment.html ----->匹配第二个url
/images/boc.gif ----->匹配第三个url
/documents/boc.jpg ----->匹配第四个url
解析
1:如果location中明确标注了=号,那么此location只能精确的匹配根/这个location,因为此时是精确匹配,所以不再进行正则的匹配。
2:/documents/docment.html只有/这个location会匹配。虽然前缀不是那么长,但是在这四个location中算是最长的匹配。
3:/images/boc.gif,这个url首先会匹配到/这个普通的location和/image/这两个,但是/image/的匹配前缀更长,所以选择后面的进行匹配。~^表示的是在匹配的过程中,匹配完普通location之后不在进行正则的匹配。
4:/documents/boc.jpg 首先会匹配到/,然后进行正则的匹配,会匹配到最后的~* \.(gif|jpg|jpeg)$,匹配到之后,正则的会把普通的覆盖掉。
location匹配进阶
server {
listen 80;
server_name www.mingpaixinxi.com.cn;
location /boc/test.html {
allow all;
}
location ^~ / {
root html;
index index.html index.htm;
deny all;
}
location ~ \.html$ {
allow all;
}
}
分别访问 curl -I http://www.mingpaixinxi.com.cn/,http://www.mingpaixinxi.com.cn/a.html,http://www.mingpaixinxi.com.cn/boc/test.html,http://www.mingpaixinxi.com.cn/test.html。
总结:为什么除了/boc/test.html之外,其余根开始匹配的全部都返回的是403呢,因为在匹配的过程中,匹配到根路径之后,前面^~说明就不在进行正则的匹配。所以直接执行了里面的deny all请求,所以返回了403。
如果我们把前面的^~符号去掉会发生什么呢?
server {
listen 80;
server_name www.mingpaixinxi.com.cn;
location /boc/test.html {
allow all;
}
location / {
root html;
index index.html index.htm;
deny all;
}
location ~ \.html$ {
allow all;
}
}
总结:除了根的匹配之外,其余的全部是404的返回值,为什么呢,因为location /之后还会进行正则的匹配,结果匹配到了 ~ \.html$ 就会把最开始的进行覆盖,执行里面的allow all(虽然是allow all,但是没有文件,返回是404,404表明请求已经到达了服务器,但是服务器不存在客户端请求的文件,而403表示的是请求根本没有到达服务器直接被拒绝掉,这两个存在本质的区别)就返回了404状态吗。
location的匹配规则你懂了吗?
总结
普通location会先于正则location进行匹配。
如果匹配到普通之后,想结束不再匹配正则的location,那么可以在普通的location前面加上 ^~这两个符号。
如果继续匹配正则location,正则匹配到的结果会覆盖普通匹配到的结果。
匹配正则的过程中,和正则的为上下位置有关系,因为正则location是匹配到一个随即停止匹配。并不存在普通location的最大前缀匹配原则。
3
nginx rewrite规则
在nginx中rewrite可以使我们将url进行灵活的转换,但是nginx在转换的过程中会有许多的坑,下面的这些坑你踩过吗?
rewrite既可以写在server中又可以写在location中,但是写在这两个中有什么区别呢,会有什么先后的顺序吗?
答案是肯定的,如果两者同时出现的话,首先会匹配的是server中的rewrite规则,然后进行匹配的是location中的rewrite规则,那server中location匹配完了之后会在继续匹配location中的rewrite规则吗?如果想解决这个问题,需要简要的说下rewrite的4个flag位。
1、last:匹配完当前的uri之后不在进行匹配。
2、break:匹配完当前的uri之后不在进行匹配。
3、permanent:永久重定向,http请求返回码301。
4、redirect:临时重定向,http请求返回码302。
没看错吧,为什么last和break的定义一样呢?解析的是从官方翻译过来的,下面看几个例子。
server {
listen 80;
server_name www.mingpaixinxi.com.cn ;
root html;
rewrite_log on; # 打开 URL 重写模块的日志开关,以便写入 error_log
location /aaa.html {
rewrite "^/aaa\.html$" /bbb.html;
rewrite "^/bbb\.html$" /ddd.html;
}
location /bbb.html {
rewrite "^/bbb\.html$" /ccc.html;
}
}
请求:
curl http://www.mingpaixinxi.com.cn/aaa.html
返回bbb.html,这个应该不难理解,先是匹配自己location中的uri规则,之后生成的新的uri也会继续匹配,直到匹配完成。
server {
listen 80;
server_name www.mingpaixinxi.com.cn ;
root html;
rewrite_log on; # 打开 URL 重写模块的日志开关,以便写入 error_log
location /aaa.html {
rewrite "^/aaa\.html$" /bbb.html last;
rewrite "^/bbb\.html$" /ddd.html;
}
location /bbb.html {
rewrite "^/bbb\.html$" /ccc.html;
}
}
curl http://www.mingpaixinxi.com.cn/aaa.html
返回ccc.html
为什么会返回的是ccc.html呢,因为rewrite "^/aaa\.html$" /bbb.html last;后面的flag位last,这表明停止当前location中的uri的继续的匹配,但是重新生成的uri不会停止匹配,会继续匹配其他的location,所以匹配到了 /bbb.html,所以返回的是ccc.html。
erver {
listen 80;
server_name www.mingpaixinxi.com.cn ;
root html;
rewrite_log on; # 打开 URL 重写模块的日志开关,以便写入 error_log
location /aaa.html {
rewrite "^/aaa\.html$" /bbb.html break;
rewrite "^/bbb\.html$" /ddd.html;
}
location /bbb.html {
rewrite "^/bbb\.html$" /ccc.html;
}
}
请求:
curl http://www.mingpaixinxi.com.cn/aaa.html
返回bbb.html,当遇到break之后,停止一切的匹配。从此处结束。所以说break比last的力度会更大些。就好像是程序里面的循环一样,遇到break之后,结束所有的循环。
同样,如果rewrite规则同时在server和location中出现,server的总是先于location的匹配,直到匹配结束。
nginx的rewrite规则你了解了吗?
Use nginx
核心配置
upstream boc {
server 192.168.1.1 weight=1 max_fails=2 fail_timeout=2;
server 192.168.1.2 weight=1 max_fails=2 fail_timeout=2;
}
server
{
listen 80;
server_name www.mingpaixinxi.com;
location / {
proxy_pass http://boc;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
access_log off;
}
在这里,定义了一个web的集群,包含两台realserver,并定义了健康检查的规则。当client访问www.mingpaixinxi.com.cn这个域名的时候,前方的nginx就会把请求发送到192.168.1.1和192.168.1.2这两台服务器,默认的分配规则是roundrobin。
上面简单的对nginx作为反向代理服务器和其他的几款反向代理软件简单的做了些比较,也介绍了些nginx中的location和反向代理集群的配置。无论是nginx还是haproxy亦或是lvs。都有自己的优势和不足的地方。没有那个好那个坏的区分。在应用中,选择自己合适的才是最好的。正所谓无论白猫还是黑猫,能抓到老鼠的都是好猫。