跳转至

Nginx

Nginx工作模式?

Nginx采用master-worker模式,nginx启动成功后,会有一个master进程和至少一个worker进程;master进程负责处理系统信号、加载配置、管理worker进程;worker进程负责处理具体的业务逻辑。

nginx采用了异步非阻塞的工作方式,epoll模型:当有i/o事件产生时,epoll就会告诉进程哪个连接由i/o事件产生,然后进程就会处理这个事件。nginx配置use epoll后,以异步非阻塞的方式工作,能够处理百万计的并发连接。

master-worker模式的优缺点:

  • 稳定性高

    一个worker进程挂掉后master进程会立即启动一个新的worker进程,保证worker进程数量不变,降低服务中断的概率

  • 高性能

    Nginx 启动 N 个 worker, 并将 worker 和 cpu 进行绑定,每个 worker 有自己的 epoll 和 定时器,由于没有进程、线程切换开销,性能非常好。配合Linux的cpu亲和性的匹配中,可以充分利用多核cpu的优势,提升性能

  • 支持平滑重启

    处理信号、配置重新加载等可以做到尽可能不中断服务

Nginx Location 路径匹配规则是怎么样的?

对于请求: http://example.com/static/img/logo.jpg

  1. 如果命中精确匹配,例如:
location = /static/img/logo.jpg {

}

则优先精确匹配,并终止匹配。

  1. 如果命中多个前缀匹配,例如:
location /static/ {

}

location /static/img/ {

}

则记住最长的前缀匹配,即上例中的 /static/img/,并继续匹配

  1. 如果最长的前缀匹配是优先前缀匹配,即:
location /static/ {

}

location ^~ /static/img/ {

}
  1. 否则,如果命中多个正则匹配,即:
location /static/ {

}

location /static/img/ {

}

location ~* /static/ {

}

location ~* /static/img/ {

}

则忘记上述 2 中的最长前缀匹配,使用第一个命中的正则匹配,即上例中的 location ~* /static/ ,并终止匹配(命中多个正则匹配,优先使用配置文件中出现次序的第一个)

  1. 否则,命中上述 2 中记住的最长前缀匹配

Nginx的负载均衡策略有哪些?

负载均衡策略 说明
轮询(rr) 负载均衡默认策略
weight 权重方式,权重越高分配到需要处理的请求越多,此策略比较适合服务器的硬件配置差别比较大的情况。此策略可以与least_conn和ip_hash结合使用。
ip_hash 依据ip分配方式,基于客户端IP的分配方式,确保了相同的客户端的请求一直发送到相同的服务器,实现会话粘滞目的
least_conn 最少连接方式,把请求转发给连接数较少的后端服务器,可以达到更好的负载均衡效果
fair(第三方) 响应时间方式
url_hash(第三方) 依据URL分配方式

nginx基于权重轮询平滑算法是怎么实现的?

常规的基于权重的轮询调度算,假定a, b, c三台机器的负载能力分别是4:2:1,则可以给它们分配的权限为4, 2, 1。 这样轮询完一次后,a被调用4次,b被调用2次,c被调用1次。

对于普通的基于权重的轮询算法,可能会产生以下的调度顺序{a, a, a, a, b, b, c}。这样的调度顺序其实并不友好,它会一下子把大压力压到同一台机器上,这样会产生一个机器一下子很忙的情况。 于是乎,就有了平滑的基于权重的轮询算法。

所谓平滑就是调度不会集中压在同一台权重比较高的机器上。这样对所有机器都更加公平。 比如,对于{a:5, b:1, c:1},产生{a, a, b, a, c, a, a}的调度序列就比{c, b, a, a, a, a, a} 更加平滑。

算法逻辑:

算法执行2步,选择出1个当前节点。

  1. 用上次选择后的权重加上每个节点配置的权重,作为节点当前权重值,第一选择的时候,上次选择后的权重都是0
  2. 选择当前权重值最大的节点为选中节点,并把它的当前值减去所有节点的权重总和,作为选择后的权重值

例如{a:5, b:1, c:1}三个节点。一开始我们初始化三个节点的当前值为{0, 0, 0}。 选择过程如下表:

轮数 当前权重 选择节点 选择后的权重
0 - - {0, 0, 0}
1 {5, 1, 1} a {-2, 1, 1}
2 {3, 2, 2} a {-4, 2, 2}
3 {1, 3, 3} b {1, -4, 3}
4 {6, -3, 4} a {-1, -3, 4}
5 {4, -2, 5} c {4, -2, -2}
6 {9, -1, -1} a {2, -1, -1}
7 {7, 0, 0} a {0, 0, 0}

我们可以发现,a, b, c选择的次数符合5:1:1,而且权重大的不会被连接选择。7轮选择后, 当前值又回到{0, 0, 0},以上操作可以一直循环,一样符合平滑和基于权重。

nginx四层、七层负载均衡的有什么区别?

四层就是基于IP+端口的负载均衡,通过虚拟IP+端口接收请求,然后再分配到真实的服务器;nginx修改数据包里面的目标和源IP和端口,然后把数据包发向目标服务器,服务器处理完成后,nginx再做一次修改,返回给请求的客户端。

七层通过虚拟的URL或主机名接收请求,然后再分配到真实的服务器。七层就是基于URL等应用层信息的负载均衡。Nginx需要读取并解析http请求内容,然后根据具体内容(url,参数,cookie,请求头)然后转发到相应的服务器,转发的过程是:建立和目标机器的连接,然后转发请求,收到响应数据在转发给请求客户端。

七层负载均衡是:

# cat /etc/nginx/conf.d/test.conf
upstream phpserver {
    server192.168.2.3;
    server192.168.2.4;
}
upstream htmlserver {
    server192.168.2.1;
    server192.168.2.2;
}

# /etc/nginx/nginx.conf
location / {
    root  /usr/share/nginx/html;
    index  index.html index.htm;
    if ($request_uri ~*\.html$){
            proxy_pass http://htmlserver;
    }
    if ($request_uri~* \.php$){
            proxy_pass http://phpserver;
    }
}

四层负载均衡:

# vim nginx.conf
worker_processes  1;
events {
    worker_connections  1024;
}
stream {  # 类似于7层的http段
    upstream ssh_proxy {
        hash $remote_addr consistent;
        server 192.168.56.2:22;
        server 192.168.56.3:22;
    }
    server {
        listen 2222;
        proxy_connect_timeout 1s;
        proxy_timeout 3s;
        proxy_pass ssh_proxy;
    }
}