设为首页 收藏本站

运维网

查看: 301|回复: 0

[经验分享] nginx学习笔记之三:nginx作为反向代理服务器

[复制链接]

尚未签到

发表于 4 天前 | 显示全部楼层 |阅读模式
  nginx不仅能作为web server,还具有反向代理、负载均衡和缓存的功能
DSC0000.png

  一、nginx的反向代理和负载均衡功能
  1、proxy模块
  nginx通过proxy模块实现将客户端的请求代理至上游服务器,此时nginx与上游服务器的连接是通过http协议进行的。nginx在实现反向代理功能时的最重要指令为 proxy_pass,它能够并能够根据URI、客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream server)。
  ⑴proxy_pass URL;
  设置后端服务器的协议和地址;这条指令可以设置的协议是“http”或者“https”,而地址既可以使用域名或者IP地址加端口(可选)的形式来定义:
  proxy_pass http://localhost:8000/uri/;
  如果解析一个域名得到多个地址,所有的地址都会以轮转的方式被使用。当然,也可以使用服务器组来定义多个地址。
  如果proxy_pass没有使用URI,传送到后端服务器的请求URI一般是客户端发起的原始URI,如果nginx改变了请求URI,则请求路径与配置中的路径的匹配部分将被替换为指令中定义的URI:
  若nginx接到的请求的uri是/name/a.html
  location /name/ {
  proxy_pass http://192.168.30.20/remote/;
  } #传送到后端服务器的URI是/remote/a.html
  location /name/ {
  proxy_pass http://192.168.30.20;
  } #传送到后端服务器的URI是/name/a.html
  location /name/ {
  proxy_pass http://192.168.30.20/;
  } #注意与上面用法的区别,这里地址末尾带有斜线,实际上被认为定义了URI,该“/”会替换“/name/",传送到后端服务器的URI是/a.html。
  如果使用正则表达式定义路径,则proxy_pass指令不应使用URI。例如:
  location ~ ^/bbs {
  proxy_pass http://www.magedu.com;
  }
  在需要代理的路径中,使用rewrite指令改变了URI,那么nginx将使用重写后的URI处理请求,而忽略proxy_pass指令设置的URI。如下面所示的例子中,传送给上游服务器的URI为/index.php?page=。
  location / {
  rewrite /(.*)$ /index.php?page=$1 break;
  proxy_pass http://localhost:8080;
  }
  ⑵proxy模块的其它指令
  ①proxy_connect_timeout time;
  与后端服务器建立连接的超时时间。一般不可能大于75秒;
  ②proxy_cookie_domain off;  #取消当前配置级别的所有proxy_cookie_domain指令
  proxy_cookie_domain domain replacement;
  设置“Set-Cookie”响应头中的domain属性的替换文本,其值可以为一个字符串、正则表达式的模式或一个引用的变量;例如:
  proxy_cookie_domain localhost example.org;
  说明:
  浏览器对 Cookie 有很多限制,如果 Cookie 的 Domain 部分与当前页面的 Domain 不匹配就无法写入。所以如果请求 A 域名,服务器 proxy_pass 到 B 域名,然后 B 服务器输出 Domian=B 的 Cookie,前端的页面依然停留在 A 域名上,于是浏览器就无法将 Cookie 写入。
  不仅是域名,浏览器对 Path 也有限制。我们经常会 proxy_pass 到目标服务器的某个 Path 下,不把这个 Path 暴露给浏览器。这时候如果目标服务器的 Cookie 写死了 Path 也会出现 Cookie 无法写入的问题。
  ③proxy_cookie_path off;
  proxy_cookie_path path replacement;
  设置“Set-Cookie”响应头中的path属性的替换文本,其值可以为一个字符串、正则表达式的模式或一个引用的变量;例如:
  proxy_cookie_path /two/ /;
  若“Set-Cookie”响应头含有属性“path=/two/some/uri/”,那么该指令会将这个属性改写为“path=/some/uri/”。
  ④proxy_hide_header field;
  nginx默认不会将“Date”、“Server”、“X-Pad”,和“X-Accel-...”响应头发送给客户端。该指令则可以设置额外隐藏的响应头,这些响应头也不会发送给客户端。相反的,如果希望允许传递某些响应头给客户端,可以使用proxy_pass_header指令。
  ⑤proxy_set_header field value;
  重新定义或者添加发往后端服务器的请求头。value可以包含文本、变量或者它们的组合。例如:
  proxy_set_header X-Real-IP $remote_addr;   #给请求头中添加客户端IP
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  默认情况下,只有两个请求头会被重新定义:
  proxy_set_header Host $proxy_host;
  proxy_set_header Connection close;
  如果某个请求头的值为空,那么这个请求头将不会传送给后端服务器:
  proxy_set_header Accept-Encoding "";
  ⑥proxy_pass_request_headers on|off;   #是否将http首部发往上游服务器
  ⑦proxy_pass_request_body on|off;  #是否将http请求报文的包体部分发往上游服务器
  ⑧proxy_redirect [default|off|redirect replacement];
  修改上游服务器传来的响应头中的"Location"和"Refresh"字段。例如:
  proxy_redirect http://localhost:8000/two/ http://frontend/one/;
  replacement字符串可以省略服务器名:
  proxy_redirect http://localhost:8000/two/ /;
  此时将使用代理服务器的主域名和端口号来替换。如果端口是80,可以不加。
  ⑨proxy_send_timeout time;
  在连接断开之前两次发送至upstream server的写操作的最大间隔时长;
  ⑩proxy_read_timeout time;
  在连接断开之前两次从接收upstream server接收读操作的最大间隔时长;
  ⑶proxy模块的内置变量
  ①$proxy_host:后端服务器的主机名和端口;
  ②$proxy_port:后端服务器的端口;
  ③$proxy_add_x_forwarded_for
  将$remote_addr变量值添加在客户端“X-Forwarded-For”请求头的后面,并以逗号分隔。 如果客户端请求未携带“X-Forwarded-For”请求头,$proxy_add_x_forwarded_for变量值将与$remote_addr变量相同
  2、upstream模块
  如果有多个上游服务器,我们可以把它们放到一个组中,并且给它们赋予不同的权重和类型,进行负载均衡等,这些功能是由upstream模块实现的。
  ⑴配置语法:
  upstream name {
  server address [parameters];
  ...
  }
  示例:
  upstream backend {
  server backend1.example.com       weight=5;
  server backend2.example.com:8080;
  server unix:/tmp/backend3;
  server backup1.example.com:8080   backup;
  }
  server {
  location / {
  proxy_pass http://backend;
  }
  }
  ⑵uptream使用注意:
  ①只能用于http上下文
  ②各server只能直接使用IP或主机名,不要加协议
  ⑶默认情况下,nginx按加权轮转的方式将请求代理到各上游服务器。与上游服务器通信的时候,如果出现错误,请求会被传给下一个服务器,直到所有可用的服务器都被尝试过。如果所有服务器都返回失败,客户端将会得到最后通信的那个服务器的(失败)响应结果。
  ⑷地址可以是域名或者IP地址,端口是可选的(默认是80),或者是指定“unix:”前缀的UNIX域套接字的路径。如果一个域名解析到多个IP,本质上是定义了多个server。
  ⑸server后可定义的参数:
  ①weight=number   #设定服务器的权重,默认是1。
  ②max_fails=number
  设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可用。在下一个fail_timeout时间段,服务器不会再被尝试。失败的尝试次数默认是1。设为0就会停止统计尝试次数,认为服务器是一直可用的。
  ③fail_timeout=time   #默认是10秒
  设定:
  统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。
  服务器被认为不可用的时间段。
  ④backup   #标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器。
  ⑤down   #标记服务器永久不可用,可以跟ip_hash指令一起使用
  ⑹upstream模块的其它负载均衡算法(用于upstream上下文):
  ①ip_hash;
  作用同lvs中的sh调度算法,将来自于同一个客户端的请求始终调度至同一台后端服务器(除了当服务器不可用的时候)
  ②least_conn;
  将请求发送到活动连接数最少的那台服务器。如果这样的服务器有多台,就尝试按加权轮循来调度
  ③sticky cookie name [expires=time] [domain=domain] [httponly] [secure] [path=path];
  session绑定,将来自于同一个客户端的请求始终调度至同一台后端服务器,从而实现客户端与后端服务器的session保持。
  ip_hash指令无法实现对内网NAT用户的均衡,而sticky指令可以做到;
  ◆sticky工作原理:
  1.浏览器首次发起请求,请求头未带cookie。nginx接收请求,发现请求头没有cookie,则以轮询方式将请求代理给后端服务器。
  2.后端服务器处理完请求,将响应头和内容返回给nginx。
  3.nginx生成cookie,返回给客户端浏览器。cookie的值与后端服务器对应,可能是明文,也可能是md5、sha1等Hash值。
  4.浏览器接收请求,并创建cookie。
  5.浏览器再次发送请求时,带上cookie。
  6.nginx接收到cookie,直接转给对应的后端服务器
  参数说明:
  domain:cookie作用的域名
  path:cookie作用的路径
  expires:cookie的过期时长
  示例:
                    upstream backend {  
                       server backend1.example.com;
  
                       server backend2.example.com;
  

  
                       sticky cookie srv_id expires=1h domain=.example.com path=/;
  
                    }
  ⑺health_check [interval=time] [fails=number] [passes=number] [uri=uri] [match=name];
  对上游服务器组进行健康状态检测,用于location中;
  参数说明:
  interval=time  #检测的间隔时长,默认为5秒
  fails=number   #连续检测失败多少次即认为上游服务器不可用,默认为1次
  passes=number  #上游服务器从不可用到可用状态时需要连续检测的次数,默认为1次
  uri=uri      #定义用于健康检测的URI,默认为“/”,即默认检测目标服务器的主页
  match=name    #指定一段配置来当作检测条件,默认当响应码为2XX或3XX时认为上游服务器是可用的
  示例:
  http {
  server {
  ...
  location / {
  proxy_pass http://backend;
  health_check uri=/.health.html match=welcome;
  }
  }
  match welcome {   #match配置段要位于http上下文
  status 200;
  header Content-Type = text/html;
  body ~ "Welcome to nginx!";
  }
  }
  3、fastcgi模块
  nginx能够通过fastcgi模块实现将客户端的动态文件请求代理至fastcgi server,此时nginx与fastcgi server的通信是通过fastcgi协议进行的
  ⑴fastcgi模块的常用指令:
  ①fastcgi_pass address;  #指定fastcgi server的地址和端口,也支持使用unix sock;
  例如:
  fastcgi_pass localhost:9000;
  fastcgi_pass 192.168.30.20:9000;
  fastcgi_pass unix:/tmp/fastcgi.socket;
  ②fastcgi_bind address | off;   #指定联系fpm服务器时使用的地址;
  ③fastcgi_param parameter value [if_not_empty];
  定义传递给fastcgi server的参数;参数值可以是文本、变量或它们的组合,if_not_empty表示不为空时才传递
  例:fastcgi_param SCRIPT_FILENAME /web/scripts$fastcgi_script_name;
  ④fastcgi_index name;   #默认主页名;就是当URI中的文件名缺省时,使用此文件名
  ⑤fastcgi_connect_timeout time;   #连接fastcgi服务器的超时时长;
  ⑥fastcgi_send_timeout time;   #向fastcgi服务传输数据的超时时长;
  ⑵通常建议nginx和fastcgi server(如php-fpm)部署在同一台服务器上,因为二者如果通过网络通信的话会造成额外的性能开销。
  ⑶配置示例:
  location ~ \.php$ {
  fastcgi_pass 127.0.0.1:9001;
  fastcgi_index index.php;
  fastcgi_param SCRIPT_FILENAME /web/scripts$fastcgi_script_name;
  include fastcgi_params;
  }
  说明:
  ①参数SCRIPT_FILENAME保存是的脚本文件的绝对路径;例如,若请求的URI是/test/status.php,那么向fastcgi server传递的脚本文件路径就是/web/scripts/test/status.php
  ②nginx有两个文件fastcgi_params和fastcgi.conf,它们存放着nginx向fastcgi server传递的参数,二者唯一的区别是后者比前者多了一行 SCRIPT_FILENAME 的定义:
  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  ⑷通过nginx查看后端php-fpm的运行状态
  vim /etc/php-fpm.d/www.conf(若php-fpm是编译安装,则为主配置文件)
  pm.status_path = fpm_status
  ping.path = fpm_ping
  vim /etc/nginx/nginx.conf
  location ~* /(fpm_status|fpm_ping) {
  root           /www/a.com;
  fastcgi_pass   127.0.0.1:9000;
  fastcgi_param  SCRIPT_FILENAME  $fastcgi_script_name;
  include      fastcgi_params;
  }
  二、nginx的缓存功能
  nginx做为反向代理时,能够将来自上游服务器的响应缓存至本地,并在后续的客户端请求同样内容时直接从本地构造响应报文。nginx使用磁盘做缓存;
  缓存将遵从上游服务器的响应报文首部中关于缓存的设定,如 "Expires"、"Cache-Control: no-cache"、 "Cache-Control: max-age=XXX"、"private"和"no-store" 等,但nginx在缓存时不会考虑响应报文的"Vary"首部。为了确保私有信息不被缓存,所有关于用户的私有信息可以在上游服务器上通过"no-cache" or "max-age=0"来实现,也可在nginx设定proxy_cache_key必须包含用户特有数据如$cookie_xxx的方式实现,但最后这种方式在公共缓存上使用可能会有风险。因此,在响应报文中含有以下首部或指定标志的报文将不会被缓存。
  Set-Cookie
  Cache-Control containing "no-cache", "no-store", "private", or a "max-age" with a non-numeric or 0 value
  Expires with a time in the past
  X-Accel-Expires: 0
  与缓存有关的指令:
  ①proxy_cache zone | off;   #定义一个用于缓存的共享内存区域,其可被多个地方调用;
  ②proxy_cache_key string;   #设定在存储及检索缓存时用于“键”的字符串,可以使用变量为$uri其值,但使用不当时有可能会为同一个内容缓存多次;另外,将用户私有信息用于键可以避免将用户的私有信息返回给其它用户;
  例如:proxy_cache_key "$host$request_uri;
  ③proxy_cache_lock on | off;   #启用此项,可在缓存未命令中阻止多个相同的请求同时发往upstream,其生效范围为worker级别;
  ④proxy_cache_lock_timeout time;   #proxy_cache_lock功能的锁定时长;
  ⑤proxy_cache_min_uses number;   #某响应报文被缓存之前至少应该被请求的次数;
  ⑥proxy_cache_path path [levels=levels] keys_zone=name:size [inactive=time] [max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time] ;
  定义一个用记保存缓存响应报文的目录,及一个保存缓存对象的键及响应元数据的共享内存区域(keys_zone=name:size),其可选参数有:
  levels:每级子目录名称的长度,有效值为1或2,每级之间使用冒号分隔,最多为3级;
  inactive:非活动缓存项从缓存中剔除之前的最大缓存时长;
  max_size:缓存空间大小的上限,当需要缓存的对象超出此空间限定时,缓存管理器将基于LRU算法对其进行清理;
  loader_files:缓存加载器的每次工作过程最多为多少个文件加载元数据;
  loader_sleep:缓存加载器的每次迭代工作之后的睡眠时长;
  loader_threashold:缓存加载器的最大睡眠时长;
  示例:
  proxy_cache_path /data/nginx/cache/one levels=1 keys_zone=one:10m;
  proxy_cache_path /data/nginx/cache/two levels=2:2 keys_zone=two:100m;          ⑦proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 |http_504 | http_403 | http_404 | off ...;
  在无法联系到upstream服务器时的哪种情形下(如error、timeout或http_500等)让nginx使用本地缓存的过期的缓存对象直接响应客户端请求;
  ⑧proxy_cache_valid [code ...] time;
  用于为不同的响应设定不同时长的有效缓存时长,例如:
  proxy_cache_valid  200 302  10m;
  ⑨proxy_cache_methods GET | HEAD | POST ...;   #为哪些请求方法启用缓存功能;
  ⑩proxy_cache_bypass string;
  设定在哪种情形下,nginx将不从缓存中取数据。例如:
  proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
  proxy_cache_bypass $http_pragma $http_authorization;
  nginx也可将后端fastcgi server的响应结果缓存:
  fastcgi_cache
  fastcgi_cache_path
  fastcgi_cache_valid
  ...
  这些指令用法同上述指令类似,不再赘述;



运维网声明 1、欢迎大家加入本站运维交流群:群①:263444886群②:197202523群③:485755530群④:201730672群⑤:202807635运维网交流群⑥:281548029
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须注明原文的出处
4、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
5、运维网 - 服务您的运维操作管理专家!
6、联系人Email:admin@yunvn.com 网址:www.iyunv.com

点击关注更多内容
您需要登录后才可以回帖 登录 | 立即注册  

本版积分规则  允许回帖邮件提醒楼主

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服 E-mail:kefu@yunvn.com

本站由青云提供云计算服务

运维网--中国最专业的运维工程师交流社区

京ICP备14039699号-1 Copyright © 2012-2018

使用手机软件扫描微信二维码

关注我们可获取更多热点资讯

Good good study day day up !


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


独家合作伙伴: 青云cloud

快速回复 返回顶部 返回列表