2016年-01-26:nginx稳定版本为nginx-1.8.1,核心版本为nginx-1.9.10+,1.9+版本修复了诸多nginx的bug,新增了很多新功能,本文介绍nginx反向代理方面


nginx反向代理实现方式很简单:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

http {

    upstream myapp1 {

        server srv1.example.com;

        server srv2.example.com;

        server srv3.example.com;

    }

 

    server {

        listen 80;

 

        location / {

            proxy_pass http://myapp1;

        }

    }

}

nginx常用调度算法:

  • round-robin:轮询,加权轮询,这是默认的调度算法

  • least-connected :最小连接调度

  • ip-hash:基于ip的哈希

  • hash:基于url的哈希


问题解析:

1

2

3

4

5

upstream myapp1 {

        server srv1.example.com;

        server srv2.example.com;

        server srv3.example.com;

    }

这里默认采用的就是加权轮询,默认三台server的权重值都为1

nginx默认开启被动健康检测功能默认:

server srv1.example.com max_fails=1 fail_timeount=10

意思是:

某nginx进程里的一个线程读取upstream模块,发包给srv1,失败一次在10秒内就会认为这个server不可用

线程共享这个nginx进程的内存空间,所以,该进程里所有线程都会知道这个server死掉了,在10秒的周期内都不会发请求给它了

问题是:

进程直接内存空间是独立的,这样说来,一个进程里面的某个线程检测到的结果也只有该进程内有效,

而其余进程是不会知道这台server死掉的信息。

那么如果nginx同时开启4个进程,第一个进程里的某个线程检测到死了一台server,第二,三,四进程都需要重新检测,这样健康检测就显得比较鸡肋了。

大家应该会很容易想到,可以拿出一块共享的内存(进程直接内存共享),专门存放检测数据,这样所有进程就不会出现重复检测的问题,对,这就是1.9版本新增功能zone(定义shared memory)


解决方案:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

Syntax:zone name [size];

 

Default:—    

Context:upstream

 

This directive appeared in version 1.9.0.

Defines the name and size of the shared

memory zone that keeps the group’s configuration and run-time state that are

shared between worker processes.

Several groups may share the same zone.

In this case, it is enough to specify the size only once.

Additionally,

as part of our commercial subscription,

such groups allow changing the group membership

or modifying the settings of a particular server

without the need of restarting nginx.

The configuration is accessible via a special location

handled byupstream_conf.


实现方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

http {

    upstream myapp1 {

        zone myapp1 64k;        #64k可以支持几十台机器的规模,128k可以支持到上百台

        server srv1.example.com;

        server srv2.example.com;

        server srv3.example.com;

    }

 

    server {

        listen 80;

 

        location / {

            proxy_pass http://myapp1;

        }

    }

}


补充一:nginx做反向代理的时候,经常会报502,503错误,很明显不是nginx的错误,而是后端代理的服务器出问题了或者说检测不到代理的后端服务器了


情况:

如果upstream模块里server定义的主机引用的是主机名,那么一旦这台被代理的主机ip发生变化,nginx是不会主动检测的,就会报502错误


解决方案:

1

2

3

4

5

6

resolve

monitors changes of the IP addresses

that correspond to a domain name of the server,

and automatically modifies the upstream configuration

without the need of restarting nginx (1.5.12).

The server group must reside in the shared memory.


实现方法

1

2

3

4

5

6

7

8

9

http {

    resolver 8.8.8.8 valid=30s; #定义主动解析upstream模块定义的主机域名的dns服务器,valid为生存周期,会替换dns的TTL

 

    upstream u {

        zone u 64k;

        ...

        server example.com resolve; #后面一定要加resolve

    }

}


补充二:slow_start=time定义慢启动周期

问题解析:

大并发情况下宕机的某台机器修复好重新上线工作后,如果立马遇到大并发任务会再次宕机

解决方案:慢启动

1

2

3

4

5

6

7

8

9

10

11

12

13

14

http {

upstream dynamic {

    server www1.example.com      weight=5 slow_start=30s; #在30s内会逐步提升www1主机的权重值

    server www2.example.com      weight=3;

    server www3.example.com      weight=2;

}

 

server {

    location / {

        proxy_pass http://dynamic;

        health_check;

    }

}

}


补充三:如果upstream里只定义一台server,那么nginx认为这台server永远可用,健康检测选项(max_fails=3 fail_timeout=10)都无效

问题:

你只有你要机器直接proxy_pass 

你只有一台机器被代理,如果还健康检测,那么检测它死掉了,nginx在fail_timeout定义的周期内都认为这台机器死掉不给它发包,你觉得合理吗???所以嘛,只一台被代理的机器,健康检测默认失效。