Nginx学习笔记

83 阅读8分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

Nginx-反向代理

正向代理:平时我们访问一些国外的网站,不能直接访问,这个时候,就需要一个国外的代理服务器,我们通过代理服务器去访问这个国外的网站就可以访问得到。这就是正向代理,正向代理,指的是,客户端知道服务器的具体访问地址,而服务器不知道真实客户端的地址。 \

反向代理:国内一些大型的互联网公司,现在都会做一些分布式系统来应对一些高并发的场景,也就是一个应用部署在多台机器上。我们通过域名去访问一个网站,发起的请求,首先会到达网站的代理服务器,再由代理服务器转发到具体的服务器上。这种客户端不知道具体服务器的代理方式,称为反向代理。

\

反向代理的配置在nginx.conf文件中

一个http下有多个server,server中会有多个路由location的匹配规则,location中指向配置好的负载均衡模块upstream,upstream中配置了对应的负载均衡策略的信息


location路由匹配规则,先精确匹配,如果有匹配中的话就马上返回。然后是普通匹配,这个先后没关系,因为会取匹配中路径最长的那个。最后才是正则匹配,这个是有顺序的,一旦一个匹配中了,就会马上返回。

\

http -> server->location->proxy->指向 upstream

upstream mysvr { 
    server 192.168.10.121:3333;
    server 192.168.10.122:3333;
}
server {
    ....
    location  ~*^.+$ {         
        proxy_pass  http://mysvr;  #请求转向mysvr 定义的服务器列表         
    }
}

Nginx-负载均衡

Nginx 负载均衡策略

负载均衡用于从“upstream”模块定义的后端服务器列表中选取一台服务器接受用户的请求。一个最基本的upstream模块是这样的,模块内的server是服务器列表:

#动态服务器组

upstream dynamic_zuoyu {

  server localhost:8080; #tomcat 7.0

  server localhost:8081; #tomcat 8.0

  server localhost:8082; #tomcat 8.5

  server localhost:8083; #tomcat 9.0

}

在upstream模块配置完成后,要让指定的访问反向代理到服务器列表:

#其他页面反向代理到tomcat容器

location ~ .*$ {

  index index.jsp index.html;

  proxy_pass http://dynamic_zuoyu;

}

这就是最基本的负载均衡实例,但这不足以满足实际需求;目前Nginx服务器的upstream模块支持6种方式的分配:

负载均衡策略

轮询默认方式
weight权重方式
ip_hash依据ip分配方式
least_conn最少连接方式
fair(第三方)响应时间方式
url_hash(第三方)依据URL分配方式

在这里,只详细说明Nginx自带的负载均衡策略,第三方不多描述。

1 、轮询

最基本的配置方法,上面的例子就是轮询的方式,它是upstream模块默认的负载均衡默认策略。每个请求会按时间顺序逐一分配到不同的后端服务器。

有如下参数:

fail_timeout与max_fails结合使用。
max_fails设置在fail_timeout参数设置的时间内最大失败次数,如果在这个时间内,所有针对该服务器的请求都失败了,那么认为该服务器会被认为是停机了,
fail_time服务器会被认为停机的时间长度,默认为10s。
backup标记该服务器为备用服务器。当主服务器停止时,请求会被发送到它这里。
down标记服务器永久停机了。

注意:

  • 在轮询中,如果服务器down掉了,会自动剔除该服务器。
  • 缺省配置就是轮询策略。
  • 此策略适合服务器配置相当,无状态且短平快的服务使用。

2 weight

权重方式,在轮询策略的基础上指定轮询的几率。例子如下:

#动态服务器组

upstream dynamic_zuoyu {

  server localhost:8080  weight=2; #tomcat 7.0

  server localhost:8081; #tomcat 8.0

  server localhost:8082  backup; #tomcat 8.5

  server localhost:8083  max_fails=3 fail_timeout=20s; #tomcat 9.0

}

在该例子中,weight参数用于指定轮询几率,weight的默认值为1,;weight的数值与访问比率成正比,比如Tomcat 7.0被访问的几率为其他服务器的两倍。

注意:

  • 权重越高分配到需要处理的请求越多。
  • 此策略可以与least_conn和ip_hash结合使用。
  • 此策略比较适合服务器的硬件配置差别比较大的情况。

3 ip_hash

指定负载均衡器按照基于客户端IP的分配方式,这个方法确保了相同的客户端的请求一直发送到相同的服务器,以保证session会话。这样每个访客都固定访问一个后端服务器,可以解决session不能跨服务器的问题。

#动态服务器组

  upstream dynamic_zuoyu {

    ip_hash;  #保证每个访客固定访问一个后端服务器

    server localhost:8080  weight=2; #tomcat 7.0

    server localhost:8081; #tomcat 8.0

    server localhost:8082; #tomcat 8.5

    server localhost:8083  max_fails=3 fail_timeout=20s; #tomcat 9.0

  }

注意:

  • 在nginx版本1.3.1之前,不能在ip_hash中使用权重(weight)。
  • ip_hash不能与backup同时使用。
  • 此策略适合有状态服务,比如session。
  • 当有服务器需要剔除,必须手动down掉。

4 least_conn

把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

#动态服务器组

upstream dynamic_zuoyu {

  least_conn;  #把请求转发给连接数较少的后端服务器

  server localhost:8080  weight=2; #tomcat 7.0

  server localhost:8081; #tomcat 8.0

  server localhost:8082 backup; #tomcat 8.5

  server localhost:8083  max_fails=3 fail_timeout=20s; #tomcat 9.0

}

注意:

  • 此负载均衡策略适合请求处理时间长短不一造成服务器过载的情况。

5 、第三方策略

第三方的负载均衡策略的实现需要安装第三方插件。

fair

按照服务器端的响应时间来分配请求,响应时间短的优先分配。

#动态服务器组

upstream dynamic_zuoyu {

  server localhost:8080; #tomcat 7.0

  server localhost:8081; #tomcat 8.0

  server localhost:8082; #tomcat 8.5

  server localhost:8083; #tomcat 9.0

  fair;  #实现响应时间短的优先分配

}

url_hash

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。 

#动态服务器组

upstream dynamic_zuoyu {

  hash $request_uri;  #实现每个url定向到同一个后端服务器

  server localhost:8080; #tomcat 7.0

  server localhost:8081; #tomcat 8.0

  server localhost:8082; #tomcat 8.5

  server localhost:8083; #tomcat 9.0

}

nginx-灰度发布

灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。

灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

灰度发布常见一般有三种方式:

  • Nginx+LUA方式(不是很理解)
  • 根据Cookie实现灰度发布
  • 根据来路IP实现灰度发布

Nginx根据Cookie实现灰度发布

\

根据Cookie查询Cookie键为version的值,如果该Cookie值为V1则转发到hilinux_01,为V2则转发到hilinux_02。Cookie值都不匹配的情况下默认走hilinux_01所对应的服务器。

两台服务器分别定义为:

hilinux_01  192.168.1.100:8080
hilinux_02  192.168.1.200:8080
  • 用if指令实现
upstream hilinux_01 {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream hilinux_02 {
    server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
}
upstream default {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
server {
  listen 80;
  server_name  www.hi-linux.com;
  access_log  logs/www.hi-linux.com.log  main;
  #match cookie
  set $group "default";
    if ($http_cookie ~* "version=V1"){
        set $group hilinux_01;
    }
    if ($http_cookie ~* "version=V2"){
        set $group hilinux_02;
    }
  location / {                       
    proxy_pass http://$group;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    index  index.html index.htm;
  }
 }
  • 用map指令实现

在Nginx里面配置一个映射,$COOKIE_version可以解析出Cookie里面的version字段。$group是一个变量,{}里面是映射规则。

如果一个version为V1的用户来访问,$group就等于hilinux_01。在server里面使用就会代理到http://hilinux_01上。version为V2的用户来访问,$group就等于hilinux_02。在server里面使用就会代理到http://hilinux_02上。Cookie值都不匹配的情况下默认走hilinux_01所对应的服务器。

upstream hilinux_01 {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream hilinux_02 {
    server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
}
upstream default {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
map $COOKIE_version $group {
~*V1$ hilinux_01;
~*V2$ hilinux_02;
default default;
}
server {
  listen 80;
  server_name  www.hi-linux.com;
  access_log  logs/www.hi-linux.com.log  main;
  location / {                       
    proxy_pass http://$group;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    index  index.html index.htm;
  }
 }

\

Nginx根据来路IP实现灰度发布

如果是内部IP,则反向代理到hilinux_02(预发布环境);如果不是则反向代理到hilinux_01(生产环境)。

upstream hilinux_01 {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
upstream hilinux_02 {
    server 192.168.1.200:8080 max_fails=1 fail_timeout=60;
}
upstream default {
    server 192.168.1.100:8080 max_fails=1 fail_timeout=60;
}
server {
  listen 80;
  server_name  www.hi-linux.com;
  access_log  logs/www.hi-linux.com.log  main;
  set $group default;
  if ($remote_addr ~ "211.118.119.11") {
      set $group hilinux_02;
  }
location / {                       
    proxy_pass http://$group;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    index  index.html index.htm;
  }
}

如果你只有单台服务器,可以根据不同的IP设置不同的网站根目录来达到相同的目的。

server {
  listen 80;
  server_name  www.hi-linux.com;
  access_log  logs/www.hi-linux.com.log  main;
  set $rootdir "/var/www/html";
    if ($remote_addr ~ "211.118.119.11") {
       set $rootdir "/var/www/test";
    }
    location / {
      root $rootdir;
    }
}

到此最基本的实现灰度发布方法就讲解完了,如果要做更细粒度灰度发布可参考ABTestingGateway项目。

\

nginx-无损发布

\

1、何为无损发布?

无损发布就是在应用进行发布升级的时候,不会影响到正在使用系统的用户,比如用户正在进行资料更新,如果这个时候进行升级,系统升级往往需要重启,重启会导致用户的资料更新失败。如何做到升级不影响用户的使用,就是今天我们讨论的无损发布。不会因为系统重启导致系统数据的丢失。

2、如何做到无损发布?

2.1、首先我们来看看web应用的无损发布,也即Nginx+Tomcat的架构模式,如下图:

2.2、无损发布的基本思路:

2.2.1、首先Nginx 动态修改 upstream,请求不再路由到Tomcat1

2.2.2、等待Tomcat1上面的请求处理完毕

2.2.3、对Tomcat1进行升级

2.2.4、检查Tomcat1是否升级成功

2.2.5、再修改Nginx 的upstream,把请求路由到Tomcat1上面

2.2.6、循环上面的步骤,直到所有的Tomcat都升级完毕

2.3、需要解决的技术问题:

2.3.1、Nginx 动态修改 upstream:

2.3.1.1、ngx_http_dyups_module模块能动态修改upstream

或者

2.3.1.2、通过lua动态更改upstream

(修改之后,路由到被踢掉的Tomcat上面的请求是否还能继续处理,待验证?)

2.3.2、识别Tomcat上面的请求处理完毕(只有等到Tomcat上面的请求处理完毕以后,才能对Tomcat进行进行重启,这样才能做到无损发布,否则还是会有部分请求会失败):

2.3.2.1、通过监控Tomcat的处理请求的线程的状态,来判断现在是否还有请求没有处理完毕