当前位置: > Linux服务器 > nginx >

搭建nginx反向代理用做内网域名转发

时间:2017-03-06 01:47来源:linux.it.net.cn 作者:IT

基于域名的7层转发的实现(NAT+反向代理)

 

在实际办公网中,因为出口IP只有一个,要实现对外提供服务的话就必须得做端口映射,如果有多个服务要对外开放的话,这只能通过映射不同端口来区分,这在实际使用过程中非常的痛苦(记忆困难、一一对应关系也没有规律、访问的时候还得加端口),这个痛苦的问题用表格的形式来形象的描述如下:

 

 

 

Public IP

Public Port Number

Internal IP

Internal Port Number

Note

1.1.1.1

80

192.168.1.10

80

service A

1.1.1.1

81

192.168.1.11

80

service B

1.1.1.1

8080

192.168.1.25

80

service C

1.1.1.1

443

192.168.1.26

443

service D

1.1.1.1

444

192.168.1.35

443

service E


在需要对外开放的服务很多的情况下,NAT的方式虽然难用、难记,但至少还是能够满足需求的(可用端口要小于65535个),但如果A、B、C服务都想(或者必须)使用默认的80、443端口的话,在只有一个公网IP的情况下是没法满足的,如果能有一种如下的实现方式,那就完美了:

 

Domain Name

Public IP

Public Port Number

Internal IP

Internal Port Number

Note

A.example.com

1.1.1.1

80

192.168.1.10

80

service A

B.example.com

1.1.1.1

80

192.168.1.11

80

service B

C.example.com

1.1.1.1

80

192.168.1.25

80

service C

D.example.com

1.1.1.1

443

192.168.1.26

443

service D

E.example.com

1.1.1.1

443

192.168.1.35

443

service E

首先来分析一下,传统NAT的话肯定是实现不了,因为NAT是3层ip加4层端口的方式做映射,而域名(如http header中)都属于7层的内容,要实现的话只能借助支持7层http协议解析的工具实现,经过一番研究发现反向代理可以实现,那太好了,反响代理的工具一大堆:squid、apache、nginx、haproxy、MySQL proxy等等,本文仅讲基于http、https协议的实现,其他协议暂不讨论。

有了工具的支持,接下来就得考虑考虑如何部署的问题:

(1)域名解析到路由器的公网ip-->在路由器(pfsense)上安装squid-->配置反向代理(开启http、https反向代理、主机映射、域名正则匹配转发)-->成功实现(需要路由器支持);

(2)域名解析到路由器的公网ip-->在路由器上做传统NAT,将80、443端口分别指向反向代理服务器-->配置反向代理服务器的-->成功实现(通用方法);

 

WINDOWS 2008Server 配置nginx 反向代理服务器

 

本案例有用过可行
0、先要在域名官网上面配置域名对应的IP地址,然后要在自己路由器上面将80端口映射到要装nginx服务器的IP地址。
1、从官网上面下载nginx1.6.2   WINDOWS版本的。访问地址http://nginx.org/en/download.html
2、解压缩到C盘根目录下面
3、复制C:\nginx\conf\nginx.conf,保存成一个副本
4、编辑nginx.conf,内容如下

 

[plain] view plain copy
 
  1. #工作进程数,建议设置为CPU的总核数  
  2.   
  3. worker_processes  2;  
  4.   
  5. #全局错误日志定义类型,日志等级从低到高依次为:  
  6.   
  7. #debug | info | notice | warn | error | crit  
  8.   
  9. error_log  logs/error.log  info;  
  10.   
  11. #记录主进程ID的文件  
  12.   
  13. pid        /nginx/nginx.pid;  
  14.   
  15. #一个进程能打开的文件描述符最大值,理论上该值因该是最多能打开的文件数除以进程数。  
  16.   
  17. #但是由于nginx负载并不是完全均衡的,所以这个值最好等于最多能打开的文件数。  
  18.   
  19. #LINUX系统可以执行 sysctl -a | grep fs.file 可以看到linux文件描述符。  
  20.   
  21. worker_rlimit_nofile 65535;  
  22.   
  23. #连接数上限, 单个进程允许的最大连接数  
  24.   
  25. events {     
  26.   
  27.     worker_connections  65535;  
  28.   
  29. }  
  30.   
  31. #设定http服务器,利用它的反向代理功能提供负载均衡支持  
  32.   
  33. http {  
  34.   
  35.     #文件扩展名与文件类型映射表  
  36.   
  37.     include       mime.types;  
  38.   
  39.     #默认文件类型  
  40.   
  41.     default_type  application/octet-stream;  
  42.   
  43.     #日志格式  
  44.   
  45.     log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '  
  46.   
  47.                                    '$status $body_bytes_sent "$http_referer" '  
  48.   
  49.                                    '"$http_user_agent" "$http_x_forwarded_for"';  
  50.   
  51.     #access log 记录了哪些用户,哪些页面以及用户浏览器、ip和其他的访问信息  
  52.   
  53.     access_log  logs/access.log  main;  
  54.   
  55.     #服务器名字的hash表大小  
  56.   
  57.     server_names_hash_bucket_size 128;  
  58.   
  59.     #客户端请求头缓冲大小。  
  60.   
  61.     #nginx默认会用client_header_buffer_size这个buffer来读取header值,  
  62.   
  63.     #如果header过大,它会使用large_client_header_buffers来读取。  
  64.   
  65.     #如果设置过小HTTP头/Cookie过大 会报400 错误 nginx 400 bad request  
  66.   
  67.     #如果超过buffer,就会报HTTP 414错误(URI Too Long)  
  68.   
  69.     #nginx接受最长的HTTP头部大小必须比其中一个buffer大  
  70.   
  71.     #否则就会报400的HTTP错误(Bad Request)  
  72.   
  73.     client_header_buffer_size 32k;  
  74.   
  75.     large_client_header_buffers 4 32k;  
  76.   
  77.     #客户端请求体的大小  
  78.   
  79.     client_body_buffer_size    8m;  
  80.   
  81.     #隐藏ngnix版本号  
  82.   
  83.     server_tokens off;  
  84.   
  85.     #忽略不合法的请求头  
  86.   
  87.     ignore_invalid_headers   on;  
  88.   
  89.     #指定启用除第一条error_page指令以外其他的error_page。  
  90.   
  91.     recursive_error_pages    on;  
  92.   
  93.     #让 nginx 在处理自己内部重定向时不默认使用  server_name 设置中的第一个域名  
  94.   
  95.     server_name_in_redirect off;  
  96.   
  97.     #开启文件传输,一般应用都应设置为on;若是有下载的应用,则可以设置成off来平衡网络I/O和磁盘的I/O来降低系统负载  
  98.   
  99.     sendfile  on;  
  100.   
  101.     #告诉nginx在一个数据包里发送所有头文件,而不一个接一个的发送。  
  102.   
  103.     tcp_nopush  on;  
  104.   
  105.     #告诉nginx不要缓存数据,而是一段一段的发送--当需要及时发送数据时,就应该给应用设置这个属性,  
  106.   
  107.     #这样发送一小块数据信息时就不能立即得到返回值。  
  108.   
  109.     tcp_nodelay    on;  
  110.   
  111.     #长连接超时时间,单位是秒  
  112.   
  113.     keepalive_timeout  65;  
  114.   
  115.     #gzip模块设置,使用 gzip 压缩可以降低网站带宽消耗,同时提升访问速度。  
  116.   
  117.     gzip  on;             #开启gzip  
  118.   
  119.     gzip_min_length  1k;          #最小压缩大小  
  120.   
  121.     gzip_buffers     4 16k;        #压缩缓冲区  
  122.   
  123.     gzip_http_version 1.0;       #压缩版本  
  124.   
  125.     gzip_comp_level 2;            #压缩等级  
  126.   
  127.     gzip_types   text/plain application/x-javascript text/css application/xml;           #压缩类型  
  128.   
  129.     #upstream作负载均衡,在此配置需要轮询的服务器地址和端口号,max_fails为允许请求失败的次数,默认为1.  
  130.   
  131.     #weight为轮询权重,根据不同的权重分配可以用来平衡服务器的访问率。  
  132.   
  133.     #指定要域名对应的WEB项目访问地址  
  134.   
  135.     upstream hostname {  
  136.   
  137.         server 192.168.33.129:18080 max_fails=0 weight=1;  
  138.   
  139.     }  
  140.     #主机配置  
  141.   
  142.     server {  
  143.   
  144.         #监听端口  
  145.   
  146.         listen       80;  
  147.   
  148.         #自己指定要跳转的域名  
  149.   
  150.         server_name  youjie.co;  
  151.   
  152.         #字符集  
  153.   
  154.         charset utf-8;  
  155.   
  156.         #单独的access_log文件  
  157.   
  158.         access_log  logs/192.168.33.129.access.log  main;  
  159.   
  160.         #反向代理配置,  
  161.   
  162.         #将所有请求为http://hostname的请求全部转发到upstream中定义的目标服务器中。  
  163.   
  164.         location / {  
  165.   
  166.             #此处配置的域名必须与upstream的域名一致,才能转发。  
  167.   
  168.             proxy_pass     http://hostname;  
  169.   
  170.             proxy_set_header   X-Real-IP $remote_addr;  
  171.   
  172.         }  
  173.   
  174.         #启用nginx status 监听页面  
  175.         location /nginxstatus {  
  176.   
  177.             stub_status on;  
  178.   
  179.             access_log on;  
  180.   
  181.         }  
  182.   
  183.         #错误页面  
  184.   
  185.         error_page   500 502 503 504  /50x.html;  
  186.   
  187.         location = /50x.html {  
  188.   
  189.             root   html;  
  190.   
  191.         }  
  192.     }  
  193.   
  194. upstream hostname1 {  
  195.   
  196.         server 192.168.33.129:28080 max_fails=0 weight=1;  
  197.   
  198. }  
  199.      server {  
  200.   
  201.         #监听端口  
  202.   
  203.         listen       80;  
  204.   
  205.         #自己指定要访问的域名  
  206.   
  207.         server_name  u-pai.cn;  
  208.   
  209.         #字符集  
  210.   
  211.         charset utf-8;  
  212.   
  213.         #单独的access_log文件  
  214.   
  215.         access_log  logs/192.168.33.129.access.log  main;  
  216.   
  217.         #反向代理配置,  
  218.   
  219.         #将所有请求为http://hostname1的请求全部转发到upstream中定义的目标服务器中。  
  220.   
  221.         location / {  
  222.   
  223.             #此处配置的域名必须与upstream的域名一致,才能转发。  
  224.   
  225.             proxy_pass     http://hostname1;  
  226.   
  227.             proxy_set_header   X-Real-IP $remote_addr;  
  228.   
  229.         }  
  230.         #启用nginx status 监听页面  
  231.   
  232.         location /nginxstatus {  
  233.   
  234.             stub_status on;  
  235.   
  236.             access_log on;  
  237.   
  238.         }  
  239.   
  240.         #错误页面  
  241.   
  242.         error_page   500 502 503 504  /50x.html;  
  243.   
  244.         location = /50x.html {  
  245.   
  246.             root   html;  
  247.   
  248.         }  
  249.     }  
  250. }  

到此配置完成
5、启动nginx
开始菜单-->运行-->cmd-->
cd c:\nginx\
nginx
启动完成
6、访问
现在可以在浏览器中输入u-pai,youjie.co访问到不同的网站。

 

 

搭建nginx反向代理用做内网域名转发

 

情景
由于内网有多台服务器的http服务要映射到公司外网静态IP,如果用路由的端口映射来做,就只能一台内网服务器的80端口映射到外网80端口,其他服务器的80端口只能映射到外网的非80端口。非80端口的映射在访问的时候要域名加上端口,比较麻烦。并且入口路由最多只能做20个端口映射。肯定以后不够用。
然后k兄就提议可以在内网搭建个nginx反向代理服务器,将nginx反向代理服务器的80映射到外网IP的80,这样指向到公司外网IP的域名的HTTP请求就会发送到nginx反向代理服务器,利用nginx反向代理将不同域名的请求转发给内网不同机器的端口,就起到了“根据域名自动转发到相应服务器的特定端口”的效果,而路由器的端口映射做到的只是“根据不同端口自动转发到相应服务器的特定端口”,真是喜大普奔啊。


涉及的知识:nginx编译安装,nginx反向代理基本配置,路由端口映射知识,还有网络域名等常识。

本次实验目标是做到:在浏览器中输入xxx123.tk能访问到内网机器192.168.10.38的3000端口,输入xxx456.tk能访问到内网机器192.168.10.40的80端口。

配置步骤
服务器ubuntu 12.04

###更新仓库
apt-get update -y
apt-get install wget -y

#下载nginx和相关软件包

pcre是为了编译rewrite模块,zlib是为了支持gzip功能。额,这里nginx版本有点旧,因为我还要做升级nginx的实验用。大家可以装新版本。

 

[plain] view plain copy
 
  1. cd /usr/local/src  
  2.  wget <a href="ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.33.tar.gz">ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.33.tar.gz</a>  
  3.  wget <a href="http://zlib.net/zlib-1.2.8.tar.gz">http://zlib.net/zlib-1.2.8.tar.gz</a>  
  4.  wget <a href="http://nginx.org/download/nginx-1.4.2.tar.gz">http://nginx.org/download/nginx-1.4.2.tar.gz</a>  
  5.  tar xf pcre-8.33.tar.gz  
  6.  tar xf zlib-1.2.8.tar.gz  
#安装编译环境

 

apt-get install build-essential libtool -y

#创建nginx用户  ,所谓的unprivileged user

useradd -s /bin/false -r -M -d /nonexistent www

#开始编译安装

 

[plain] view plain copy
 
  1. /configure --with-pcre=/usr/local/src/pcre-8.33 --with-zlib=/usr/local/src/zlib-1.2.8 --user=www --group=www \  
  2.  --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module  
  3.  make  
  4.  make install  
#给文件夹授权
chown -R www:www /usr/local/nginx
#修改配置文件
vim nginx.conf

 

 

[plain] view plain copy
 
  1. user www www;  
  2. worker_processes 1;  
  3. error_log logs/error.log;  
  4. pid logs/nginx.pid;  
  5. worker_rlimit_nofile 65535;  
  6. events {  
  7.     use epoll;  
  8.     worker_connections 65535;  
  9. }  
  10. http {  
  11.     include mime.types;  
  12.     default_type application/octet-stream;  
  13.     include /usr/local/nginx/conf/reverse-proxy.conf;  
  14.     sendfile on;  
  15.     keepalive_timeout 65;  
  16.     gzip on;  
  17.     client_max_body_size 50m;  
  18. #缓冲区代理缓冲用户端请求的最大字节数,可以理解为保存到本地再传给用户  
  19.     client_body_buffer_size 256k;  
  20.     client_header_timeout 3m;  
  21.     client_body_timeout 3m;  
  22.     send_timeout 3m;  
  23.     proxy_connect_timeout 300s;  
  24. #nginx跟后端服务器连接超时时间(代理连接超时)  
  25.     proxy_read_timeout 300s;  
  26. #连接成功后,后端服务器响应时间(代理接收超时)  
  27.     proxy_send_timeout 300s;  
  28.     proxy_buffer_size 64k;  
  29. #设置代理服务器(nginx)保存用户头信息的缓冲区大小  
  30.     proxy_buffers 4 32k;  
  31. #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置  
  32.     proxy_busy_buffers_size 64k;  
  33. #高负荷下缓冲大小(proxy_buffers*2)  
  34.     proxy_temp_file_write_size 64k;  
  35. #设定缓存文件夹大小,大于这个值,将从upstream服务器传递请求,而不缓冲到磁盘  
  36.     proxy_ignore_client_abort on;  
  37. #不允许代理端主动关闭连接  
  38.     server {  
  39.         listen 80;  
  40.         server_name localhost;  
  41.         location / {  
  42.             root html;  
  43.             index index.html index.htm;  
  44.         }  
  45.         error_page 500 502 503 504 /50x.html;  
  46.         location = /50x.html {  
  47.             root html;  
  48.         }  
  49.     }  
  50. }  
编辑反向代理服务器配置文件:
vim /usr/local/nginx/conf/reverse-proxy.conf
[plain] view plain copy
 
  1. server  
  2. {  
  3.     listen 80;  
  4.     server_name xxx123.tk;  
  5.     location / {  
  6.         proxy_redirect off;  
  7.         proxy_set_header Host $host;  
  8.         proxy_set_header X-Real-IP $remote_addr;  
  9.         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
  10.         proxy_pass http://192.168.10.38:3000;  
  11.     }  
  12.     access_log logs/xxx123.tk_access.log;  
  13. }  
  14.    
  15. server  
  16. {  
  17.     listen 80;  
  18.     server_name xxx456.tk;  
  19.     location / {  
  20.         proxy_redirect off;  
  21.         proxy_set_header Host $host;  
  22.         proxy_set_header X-Real-IP $remote_addr;  
  23.         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
  24.         proxy_pass http://192.168.10.40:80;  
  25.     }  
  26.     access_log logs/xxx456.tk_access.log;  
  27. }  
然后重新加载nginx配置文件,使之修改生效,再把xxx123.tk域名指向公司静态IP,这样就成功的做到了在浏览器中输入xxx123.tk的时候访问的内网服务器192.168.10.38的3000端口,输入xxx456.tk访问192.168.10.40的80端口的作用。
如果想对后端机器做负载均衡,像下面这配置就可以把对nagios.xxx123.tk的请求分发给内网的131和132这两台机器做负载均衡了。
[plain] view plain copy
 
  1. upstream monitor_server {  
  2.     server 192.168.0.131:80;  
  3.         server 192.168.0.132:80;  
  4. }  
  5.    
  6. server  
  7. {  
  8.     listen 80;  
  9.     server_name nagios.xxx123.tk;  
  10.     location / {  
  11.         proxy_redirect off;  
  12.         proxy_set_header Host $host;  
  13.         proxy_set_header X-Real-IP $remote_addr;  
  14.         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
  15.         proxy_pass http://monitor_server;  
  16.     }  
  17.     access_log logs/nagios.xxx123.tk_access.log;  
  18. }  
额,关于负载均衡和缓存就不多说了,这里只是要起到一个简单的“域名转发”功能。
另外,由于http请求最后都是由反向代理服务器传递给后段的机器,所以后端的机器原来的访问日志记录的访问IP都是反向代理服务器的IP。
要想能记录真实IP,需要修改后端机器的日志格式,这里假设后端也是一台nginx:
在后端配置文件里面加入这一段即可:

 

 

[plain] view plain copy
 
  1. log_format access '$HTTP_X_REAL_IP - $remote_user [$time_local] "$request" '  
  2. '$status $body_bytes_sent "$http_referer" '  
  3. '"$http_user_agent" $HTTP_X_Forwarded_For';  
  4.    
  5. access_log logs/access.log access;  
再看看原来日志的格式长什么样:  

 

 

[plain] view plain copy
 
  1. #log_format main '$remote_addr - $remote_user [$time_local] "$request" '  
  2. # '$status $body_bytes_sent "$http_referer" '  
  3. # '"$http_user_agent" "$http_x_forwarded_for"';  
  4.    
  5. #access_log logs/access.log main;  
看出区别了吧  

 

遇到的问题
之前没配置下面这段,访问时候偶尔会出现504 gateway timeout,由于偶尔出现,所以不太好排查

[plain] view plain copy
 
  1. proxy_connect_timeout 300s;  
  2. proxy_read_timeout 300s;  
  3. proxy_send_timeout 300s;  
  4. proxy_buffer_size 64k;  
  5. proxy_buffers 4 32k;  
  6. proxy_busy_buffers_size 64k;  
  7. proxy_temp_file_write_size 64k;  
  8. proxy_ignore_client_abort on;  
报错日志:

 

 

[plain] view plain copy
 
  1. ...upstream timed out (110: Connection timed out) while reading response header from upstream, client: ...(后面的省略)  
从日志看来是连接超时了,网上一通乱查之后估计可能是后端服务器响应超时了,本着大胆假设,小心求证的原则,既然假设了错误原因就要做实验重现错误:那就调整代理超时参数,反过来把代理超时阀值设小(比如1ms)看会不会次次出现504。后来发现把proxy_read_timeout 这个参数设置成1ms的时候,每次访问都出现504。于是把这个参数调大,加入上面那段配置,解决问题了。

 

Nginx搭建反向代理服务器过程详解

 

【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器(—周旭龙)

 

一、反向代理:Web服务器的“经纪人”

1.1 反向代理初印象

 

  反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。

lbs

  从上图可以看出:反向代理服务器位于网站机房,代理网站Web服务器接收Http请求,对请求进行转发。

1.2 反向代理的作用

  ①保护网站安全:任何来自Internet的请求都必须先经过代理服务器;

  ②通过配置缓存功能加速Web请求:可以缓存真实Web服务器上的某些静态资源,减轻真实Web服务器的负载压力;

  ③实现负载均衡:充当负载均衡服务器均衡地分发请求,平衡集群中各个服务器的负载压力;

lb

二、初识Nginx:简单却不平凡

2.1 Nginx是神马?

  Nginx是一款轻量级的网页服务器、反向代理器以及电子邮件代理服务器。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。

Source:Nginx(发音同engine x),它是由俄罗斯程序员Igor Sysoev所开发的。起初是供俄国大型的门户网站及搜索引擎Rambler(俄语:Рамблер)使用。此软件BSD-like协议下发行,可以在UNIX、GNU/Linux、BSD、Mac OS X、Solaris,以及Microsoft Windows等操作系统中运行。

  说到Web服务器,Apache服务器和IIS服务器是两大巨头;但是运行速度更快、更灵活的对手:Nginx 正在迎头赶上。

2.2 Nginx的应用现状

  Nginx 已经在俄罗斯最大的门户网站── Rambler Media(www.rambler.ru)上运行了3年时间,同时俄罗斯超过20%的虚拟主机平台采用Nginx作为反向代理服务器。

  在国内,已经有 淘宝、新浪博客、新浪播客、网易新闻、六间房、56.com、Discuz!、水木社区、豆瓣、YUPOO、海内、迅雷在线 等多家网站使用 Nginx 作为Web服务器或反向代理服务器。

2.3 Nginx的核心特点

  (1)跨平台:Nginx 可以在大多数 Unix like OS编译运行,而且也有Windows的移植版本;

  (2)配置异常简单:非常容易上手。配置风格跟程序开发一样,神一般的配置;

  (3)非阻塞、高并发连接:数据复制时,磁盘I/O的第一阶段是非阻塞的。官方测试能够支撑5万并发连接,在实际生产环境中跑到2~3万并发连接数。(这得益于Nginx使用了最新的epoll模型);

PS:对于一个Web服务器来说,首先看一个请求的基本过程:建立连接---接收数据---发送数据,在系统底层看来 :上述过程(建立连接---接收数据---发送数据)在系统底层就是读写事件。

①如果采用阻塞调用的方式,当读写事件没有准备好时,必然不能够进行读写事件,那么久只好等待,等事件准备好了,才能进行读写事件,那么请求就会被耽搁 。

②既然没有准备好阻塞调用不行,那么采用非阻塞调用方式。非阻塞就是:事件马上返回,告诉你事件还没准备好呢,你慌什么,过会再来吧。好吧,你过一会,再来检查一下事件,直到事件准备好了为止,在这期间,你就可以先去做其它事情,然后再来看看事件好了没。虽然不阻塞了,但你得不时地过来检查一下事件的状态,你可以做更多的事情了,但带来的开销也是不小的。

  (4)事件驱动:通信机制采用epoll模型,支持更大的并发连接。

①非阻塞通过不断检查事件的状态来判断是否进行读写操作,这样带来的开销很大,因此就有了异步非阻塞的事件处理机制。这种机制让你可以同时监控多个事件,调用他们是阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好了,就返回。这种机制解决了上面阻塞调用与非阻塞调用的两个问题。

②以epoll模型为例:当事件没有准备好时,就放入epoll(队列)里面。如果有事件准备好了,那么就去处理;如果事件返回的是EAGAIN,那么继续将其放入epoll里面。从而,只要有事件准备好了,我们就去处理它,只有当所有事件都没有准备好时,才在epoll里面等着。这样,我们就可以并发处理大量的并发了,当然,这里的并发请求,是指未处理完的请求,线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件,事实上就是这样的。

③与多线程方式相比,这种事件处理方式是有很大的优势的,不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级,并发数再多也不会导致无谓的资源浪费(上下文切换)。对于IIS服务器,每个请求会独占一个工作线程,当并发数上到几千时,就同时有几千的线程在处理请求了。这对操作系统来说,是个不小的挑战:因为线程带来的内存占用非常大,线程的上下文切换带来的cpu开销很大,自然性能就上不去,从而导致在高并发场景下性能下降严重。

总结:通过异步非阻塞的事件处理机制,Nginx实现由进程循环处理多个准备好的事件,从而实现高并发和轻量级。 

  (5)Master/Worker结构:一个master进程,生成一个或多个worker进程。

PS:Master-Worker设计模式核心思想是将原来串行的逻辑并行化,并将逻辑拆分成很多独立模块并行执行。其中主要包含两个主要组件Master和Worker,Master主要将逻辑进行拆分,拆分为互相独立的部分,同时维护了Worker队列,将每个独立部分下发到多个Worker并行执行,Worker主要进行实际逻辑计算,并将结果返回给Master。

问:nginx采用这种进程模型有什么好处?

答:采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,Master进程则很快重新启动新的Worker进程。当然,Worker进程的异常退出,肯定是程序有bug了,异常退出,会导致当前Worker上的所有请求失败,不过不会影响到所有请求,所以降低了风险。

  (6)内存消耗小:处理大并发的请求内存消耗非常小。在3万并发连接下,开启的10个Nginx 进程才消耗150M内存(15M*10=150M)。

  (7)内置的健康检查功能:如果 Nginx 代理的后端的某台 Web 服务器宕机了,不会影响前端访问。

  (8)节省带宽:支持 GZIP 压缩,可以添加浏览器本地缓存的 Header 头。

  (9)稳定性高:用于反向代理,宕机的概率微乎其微。

三、构建实战:Nginx+IIS构筑Web服务器集群的负载均衡

  这里我们主要在Windows环境下,通过将同一个Web网站部署到不同服务器的IIS上,再通过一个统一的Nginx反响代理服务器对外提供统一访问接入,实现一个最简化的反向代理和负载均衡服务。但是,受限于实验条件,我们这里主要在一台计算机上进行反向代理、IIS集群的模拟,具体的实验环境如下图所示:我们将nginx服务和web网站都部署在一台计算机上,nginx监听http80端口,而web网站分别以不同的端口号(这里是8050及8060)部署在同一个IIS服务器上,用户访问localhost时,nginx作为反向代理将请求均衡地转发给两个IIS中不同端口的Web应用程序进行处理。虽然实验环境很简单而且有限,但是对于一个简单的负载均衡效果而言,本文是可以达到并且展示的。

3.1 准备一个ASP.NET网站部署到IIS服务器集群中

  (1)在VS中新建一个ASP.NET Web应用程序,但是为了在一台计算机上展示效果,我们将这个Web程序复制一份,并修改两个Web程序的Default.aspx,让其的首页显示不同的一点信息。这里Web1展示的是“The First Web:”,而Web2展示的则是“The Second Web”。

  (2)调试运行,看看两个网站的效果如何?

  ①Web1的展示效果:

  ②Web2的展示效果:

  ③部署到IIS中,分配不同的端口号:这里我选择了Web1:8050,Web2:8060

  (3)总结:在真实环境中,构建Web应用服务器集群的实现是将同一个Web应用程序部署到Web服务器集群中的多个Web服务器上。

3.2 下载Nginx并部署到服务器中作为自启动的Windows服务

  (1)到Nginx官网下载Nginx的Windows版本:http://nginx.org/en/download.html(这里我们使用nginx/Windows-1.4.7版本进行实验,本文底部有下载地址)

  (2)解压到磁盘任意目录,例如这里我解压到了:D:\Servers\nginx-1.4.7

  (3)启动、停止和重新加载服务:通过cmd以守护进程方式启动nginx.exe:start nginx.exe,停止服务:nginx -s stop,重新加载配置:nginx -s  reload;

  (4)每次以cmd方式启动Nginx服务不符合实际要求,于是我们想到将其注册为Windows服务,并设置为自动启动模式。这里,我们使用一个不错的小程序:“Windows Service Wrapper”,将nginx.exe注册为Windows服务,具体的步凑如下:

  ①下载最新版的 Windows Service Wrapper 程序,比如我下载的名称是 "winsw-1.8-bin.exe"(本文底部有下载地址),然后把它命名成你想要的名字(比如: "nginx-service.exe",当然,你也可以不改名)

  ②将重命名后的 nginx-service.exe 复制到 nginx 的安装目录(比如,我这里是 "D:\Servers\nginx-1.4.7")

  ③在同一个目录下创建一个Windows Service Wrapper 的XML配置文件,名称必须与第一步重命名时使用的名称一致(比如我这里是 "nginx-service.xml",  如果,你没有重命名,则应该是 "winsw-1.8-bin.xml"),这个XML的内容如下:

复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<service>
<id>nginx</id>
<name>Nginx Service</name>
<description>High Performance Nginx Service</description>
<executable>D:\Servers\nginx-1.4.7\nginx.exe</executable>
<logpath>D:\Servers\nginx-1.4.7\</logpath>
<logmode>roll</logmode>
<depend></depend>
<startargument>-p D:\Servers\nginx-1.4.7</startargument>
<stopargument>-p D:\Servers\nginx-1.4.7 -s stop</stopargument>
</service>
复制代码

  ④在命令行下执行以下命令,以便将其注册成Windows服务:nginx-service.exe install

  ⑤接下来就可以在Windows服务列表看到Nginx服务了,这里我们可以将其设置为自动启动了:

  (5)总结:在Windows环境中,要对外提供的Windows服务一般都要将其启动类型设置为自动。

3.3 修改Nginx核心配置文件nginx.conf

  (1)进程数与每个进程的最大连接数:

    •nginx进程数,建议设置为等于CPU总核心数
    
    •单个进程最大连接数,那么该服务器的最大连接数=连接数*进程数

  (2)Nginx的基本配置:

    •监听端口一般都为http端口:80;
    •域名可以有多个,用空格隔开:例如 server_name www.ha97.com ha97.com;

  (3)负载均衡列表基本配置:

    •location / {}:对aspx后缀的进行负载均衡请求,假如我们要对所有的aspx后缀的文件进行负载均衡时,可以这样写:location ~ .*\.aspx$ {}

    •proxy_pass:请求转向自定义的服务器列表,这里我们将请求都转向标识为http://cuitccol.com的负载均衡服务器列表;

    •在负载均衡服务器列表的配置中,weight是权重,可以根据机器配置定义权重(如果某台服务器的硬件配置十分好,可以处理更多的请求,那么可以为其设置一个比较高的weight;而有一台的服务器的硬件配置比较差,那么可以将前一台的weight配置为weight=2,后一台差的配置为weight=1)。weigth参数表示权值,权值越高被分配到的几率越大;

  (4)总结:最基本的Nginx配置差不多就是上面这些内容,当然仅仅是最基础的配置。(详细的配置内容请下载底部的nginx-1.4.7详细查看)

3.4 添加Nginx对于静态文件的缓存配置

  为了提高响应速度,减轻真实服务器的负载,对于静态资源我们可以在反向代理服务器中进行缓存,这也是反向代理服务器的一个重要的作用。

  (1)缓存静态资源之图片文件

  root /nginx-1.4.7/staticresources/image:对于配置中提到的jpg/png等文件均定为到/nginx-1.4.7/staticresources/image文件夹中进行寻找匹配并将文件返回;

  expires 7d:过期时效为7天,静态文件不怎么更新,过期时效可以设大一点,如果频繁更新,则可以设置得小一点;

  TIPS:下面的样式、脚本缓存配置同这里一样,只是定位的文件夹不一样而已,不再赘述。

  (2)缓存静态资源之样式文件

  (3)缓存静态资源之脚本文件

  (4)在nginx服务文件夹中创建静态资源文件夹,并要缓存的静态文件拷贝进去:这里我主要将Web程序中用到的image、css以及js文件拷贝了进去;

  (5)总结:通过配置静态文件的缓存设置,对于这些静态文件的请求可以直接从反向代理服务器中直接返回,而无需再将这些静态资源请求转发到具体的Web服务器进行处理了,可以提高响应速度,减轻真实Web服务器的负载压力。

3.5 简单测试Nginx反向代理实现负载均衡效果

  (1)第一次访问http://localhost/Default.aspx时从127.0.0.1:8050处理响应返回结果

  (2)第二次访问http://localhost/Default.aspx时从127.0.0.1:8060处理响应返回结果

  (3)多次访问http://localhost/Default.aspx时的截屏:

学习小结

  在本文中,借助了Nginx这个神器简单地在Windows环境下搭建了一个反向代理服务,并模拟了一个IIS服务器集群的负载均衡效果。从这个DEMO中,我们可以简单地感受到反向代理为我们所做的事情,并体会负载均衡是怎么一回事。但是,在目前大多数的应用中,都会将Nginx部署在Linux服务器中,并且会做一些针对负载均衡的优化配置,这里我们所做的仅仅就是一个小小的使用而已(just修改一下配置文件)。不过,万丈高楼平地起,前期的小小体会,也会帮助我们向后期的深入学习奠定一点点的基础。

  突然在QQ空间里看到了朋友送的礼物,猛然发现今天居然是我的阳历生日,好吧,我祝我自己生日快乐,希望自己在未来的日子中能够做更多的实践,分享更多的内容。当然,如果你觉得本文还可以,那也麻烦点个赞,不要吝啬你的鼠标左键哟。

参考资料

(1)丁胖胖,《图解正向代理、反向代理与透明代理》:http://z00w00.blog.51cto.com/515114/1031287

(2)特种兵-AK47,《正向代理与反向代理的区别》:http://blog.csdn.net/m13666368773/article/details/8060481

(3)百度百科,Nginx:http://baike.baidu.com/view/926025.htm?fr=aladdin

(4)51CTO,《Nginx安装配置与服务搭建专题》:http://os.51cto.com/art/201111/304611.htm

(5)红黑联盟,《Nginx配置文件nginx.conf中文详解总结》:http://www.2cto.com/os/201212/176520.html

(6)360doc,《Linux下同步模式、异步模式、阻塞调用与非阻塞调用总结》:http://www.360doc.com/content/13/0117/12/5073814_260691714.shtml (好文一篇,值得阅读)

(7)e路相扶,《同步、异步、阻塞与非阻塞》:http://www.cnblogs.com/zhangjun516/archive/2013/04/17/3025902.html

(8)feitianxuxue,《处理大并发之对异步非阻塞的理解》:http://blog.csdn.net/feitianxuxue/article/details/8936802

附件下载

(1)nginx-1.4.7:http://pan.baidu.com/s/1dD2C2zB

(2)winsw-1.8-bin.exe:http://pan.baidu.com/s/1kTihzk7

(3)SimpleNginxDemo:http://pan.baidu.com/s/1bnq5oYz




(责任编辑:IT)
------分隔线----------------------------
栏目列表
推荐内容