JavaWeb_19_Nginx


本文介绍Ngnix入门,Nginx是一款服务器软件。

1. 概述

nginx news

Nginx是一个高性能的轻量级的HTTP反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。其特点是占有内存小,并发能力强,事实上Nginx的并发能力确实在同类型的网页服务器中表现较好。

注意,上面说了是web服务器,可以作为静态页面的web服务器,同时还支持CGI协议的动态语言,比如perl、php等。但是不支持Java。Java程序只能通过与tomcat配合完成。Nginx专为性能优化而开发,性能是其最重要的考量,实现上非常注重效率,能经受高负载的考验,有报告表明能支持高达50000个并发连接数。

Nginx是什么?Nginx介绍及Nginx的优点 - LNMP一键安装包

nginx做为HTTP服务器,有以下几项基本特性:

  • 处理静态文件,索引文件以及自动索引;打开文件描述符缓冲.
  • 无缓存的反向代理加速,简单的负载均衡和容错.
  • FastCGI,简单的负载均衡和容错.
  • 模块化的结构。包括gzipping, byte ranges, chunked responses,以及 SSI-filter等filter。如果由FastCGI或其它代理服务器处理单页中存在的多个SSI,则这项处理可以并行运行,而不需要相互等待。
  • 支持SSL 和 TLSSNI.

Nginx具有很高的稳定性。其它HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽频繁交换,失去响应,只能重启服务器。例如当前apache一旦上到200个以上进程,web响应速度就明显非常缓慢了。而Nginx采取了分阶段资源分配技术,使得它的CPU与内存占用率非常低。nginx官方表示保持10000个没有活动的连接,它只占2.5M内存,所以类似DOS这样的攻击对Nginx来说基本上是毫无用处的。就稳定性而言,Nginx比Lighthttpd更胜一筹。

Nginx支持热部署。它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行进行升级。

Nginx采用master-slave模型,能够充分利用SMP的优势,且能够减少工作进程在磁盘I/O的阻塞延迟。当采用select()/poll()调用时,还可以限制每个进程的连接数。

2. Nginx常见概念

2.1 正向代理

在介绍反向代理之前,先引入正向代理的概念。Nginx不仅可以做反向代理,实现负载均衡。还能用作正向代理来实现上网等功能。正向代理指的是:如果把局域网外的Internet想象成一个巨大的资源库,则局域网中的客户端要访问Internet,则需要通过代理服务器来访问,这种代理服务就称为正向代理。

因此,Java中的静态/动态代理其实就是正向代理,代替服务商来提供服务。(当然,既然代理,除了基础服务之外,也可附加一些功能,即切面。)回到这里,国内是无法直接访问google.com的,因此只能访问能访问google.com的计算机,来间接访问,这个能访问google.com的计算机就是代理,即代理我们来访问google.com,并将结果返回给我们,或者说,代理google.com来向我们提供服务。感觉还是第一种概念比较合适,即代替我们访问google.com,因为这是我们主动让它来代替我们访问的,并不是google来提供的。或者说,因为对于google.com来说,代理和我们普通客户是没区别的。

image-20221002141811866

2.2 反向代理

那么反向代理是什么呢?

反向代理,其实客户端对代理是无感知的,因为客户端不需要任何配置就可以访问,我们只需要将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,再返回给客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器的IP地址。

而前面的正向代理,显然,我们需要去配置代理服务器,也就是说,客户端对代理其实是有感知的。而反向代理,则无需配置,只需要将请求发送到代理服务器即可。

感觉二者并没有太大的区别emmmm,这里的正向和反向感觉分别是对客户端和服务端来说的。

一句话,正向代理需要客户端配置,反向代理需要服务器端配置。正向代理,代理的是客户端,即对于客户端来说,是代替自己访问。反向代理代理的是服务端,对服务端来说,是代替自己对外提供服务。

再通俗易懂地说,只要客户端访问官网的方式需要设置,那么就是正向代理,比如翻墙软件,需要客户端自己开启。而如果客户端不需要自己修改任何方式的话,那么就是反向代理【对于服务端来说,其实也是正向代理,对于客户端来说就是反向代理】。

还需要注意一点的是,反向代理其实就是一个服务器,客户端只需要访问该服务器即可,只不过具体的服务,则是由该服务器来负载均衡具体的后端web服务器。因此说,正向代理,似乎做不到负载均衡;而反向代理则可以负载均衡。

综上,正向代理是代理客户端端访问,而反向代理是代理服务器接收客户端的访问。正向反向指的就是请求的发送方和接收方。

image-20221002143615639

即真实的服务器和反向代理服务器对外都是统一的反向代理服务器公开的的接口。

2.3 负载均衡

首先看一下传统web应用最普通的请求响应过程:

客户端发送多个请求到服务器,服务器处理请求,有一些可能要与数据库进行交互,服务器处理完毕后,再将结果返回给客户端。

这种架构模式对于早期的系统相对单一,并发请求相对较少的情况下是比较适合的,成本也低。但是随着信息数量的不断增长,访问量和数据量的飞速增长,以及系统业务的复杂度增加,这种架构会造成服务器相应客户端的请求日益缓慢,并发量特别大的时候,还容易造成服务器直接崩溃。很明显这是由于服务器性能的瓶颈造成的问题,那么如何解决这种情况呢?

首先想到的就是升级服务器的配置,比如提高CPU执行频率,加大内存等,但是随着摩尔定律的日益失效,显然单服务器已经无法满足要求了,这时候需要集群。集群的话,则需要合理地分配处理请求分发到各个服务器上,即负载均衡。(如果单纯的单体应用集群,其实效率还是有点低的,并且性能利用率也低,因此出现了微服务,但是对于同一种微服务,也需要集群来扩容,也需要负载均衡,因此说,无论什么时候,都需要负载均衡)

image-20221002150252508

2.4 动静分离

为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度。降低原来单个服务器的压力。即静态资源和动态资源在不提供的服务器提供。

image-20221002154650132

3. Nginx安装、常用命令和配置文件

Nginx其实就是服务器软件,和Tomcat类似,因此需要安装、配置。

3.1 Nginx安装

一般情况下,服务器是Linux操作系统,因此Nginx也是安装在Linux操作系统上,需要

  1. pcre-8.37.tar.gz
  2. openssl-1.0.1t.tar.gz
  3. zlib-1.28.tar.gz
  4. nginx-1.11.1.tar.gz

由Nginx来负责调用具体的服务。但是由于之前联系的项目都是在本机上,内网无法访问,因此这里将Nginx安装到本地来简单学习一下即可。

Nginx安装教程(windows)_猪耳朵的博客-CSDN博客_nginx安装windows

默认监听80端口。

image-20221002163550425

3.2 常用命令

使用Nginx命令,需要进入到Nginx的安装目录中。

命令 描述
nginx -v 查看nginx的版本号
nginx -V 查看nginx的版本号,编译器版本和配置参数
start nginx 启动nginx
nginx -s stop 快速关闭nginx,可能不保存相关信息,并迅速终止web服务
nginx -s quit 平稳关闭nginx,保存相关信息,有安排的结束web服务
nginx -s reload 重新加载nginx(修改配置文件后需要重加载)

3.3 配置文件

在Nginx的安装目录下,有conf/nginx.conf配置文件,有如下配置信息,由三部分组成:

  1. 全局块

    从配置文件开始,到events块之间的内容,主要会设置一些影响nginx服务器整体运行的配置指令。比如:worker_processes 1;,这是Nginx服务器处理并发服务的关键配置,worker_processes值越大,可以支持的并发处理量也越多,即worker数量。但是会受到硬件、软件等设备的制约。

    1
    2
    3
    4
    5
    6
    7
    8
    #user  nobody;
    worker_processes 1;

    #error_log logs/error.log;
    #error_log logs/error.log notice;
    #error_log logs/error.log info;

    #pid logs/nginx.pid;
  2. events块

    events块涉及的指令主要影响Nginx服务器与用户的网络连接。如worker_connections 1024;表示支持的最大的连接数。

    1
    2
    3
    events {
    worker_connections 1024;
    }
  3. http块【配置最频繁的部分】

    1. http全局块

      该部分配置的指令包括文件引入、MIME-TYPE定义、日志自定义、连接超时时间、单链接请求数上限等。如下所示:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      include       mime.types;
      default_type application/octet-stream;

      #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
      # '$status $body_bytes_sent "$http_referer" '
      # '"$http_user_agent" "$http_x_forwarded_for"';

      #access_log logs/access.log main;

      sendfile on;
      #tcp_nopush on;

      #keepalive_timeout 0;
      keepalive_timeout 65;

      #gzip on;
    2. server块

      这部分和虚拟主机有密切联系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本

      每个http块可以包括多个server块,而每个server块就相当于一个虚拟主机。而每个server块也分为全局server块以及若干个location块。

      1. 全局server块

        最常见的配置是本虚拟主机的监听端口本虚拟主机的名称或IP配置

      2. location块

        一个server块可以配置多个location块。这块的主要作用是基于Nginx服务器接收到的请求字符串(如server_name/uri_string),对虚拟主机名称(或者是IP别名)之外的字符串(如前面的/uri_string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。

      server块如下所示:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      server {
      listen 80;
      server_name localhost;

      #charset koi8-r;

      #access_log logs/host.access.log main;

      location / {
      root html;
      index index.html index.htm;
      }

      #error_page 404 /404.html;

      # redirect server error pages to the static page /50x.html
      #
      error_page 500 502 503 504 /50x.html;
      location = /50x.html {
      root html;
      }

      # proxy the PHP scripts to Apache listening on 127.0.0.1:80
      #
      #location ~ \.php$ {
      # proxy_pass http://127.0.0.1;
      #}

      # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
      #
      #location ~ \.php$ {
      # root html;
      # fastcgi_pass 127.0.0.1:9000;
      # fastcgi_index index.php;
      # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
      # include fastcgi_params;
      #}

      # deny access to .htaccess files, if Apache's document root
      # concurs with nginx's one
      #
      #location ~ /\.ht {
      # deny all;
      #}
      }

整体文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

#user nobody;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;


events {
worker_connections 1024;
}


http {
include mime.types;
default_type application/octet-stream;

#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';

#access_log logs/access.log main;

sendfile on;
#tcp_nopush on;

#keepalive_timeout 0;
keepalive_timeout 65;

#gzip on;

server {
listen 80;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root html;
index index.html index.htm;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}


# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;

# location / {
# root html;
# index index.html index.htm;
# }
#}


# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;

# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;

# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;

# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

# location / {
# root html;
# index index.html index.htm;
# }
#}

}

这里简单描述了配置文件的几部分,下面的用例再具体介绍。

4. Nginx应用配置实例

4.1 实现反向代理

实现效果:

打开浏览器,在浏览器地址栏输入地址:www.123.com,跳转到本机系统tomcat欢迎主页面中。

本质上说,就是对外暴露Nginx的IP和端口,Nginx收到之后,将请求转发到对应的Tomcat服务器上。

准备工作:

  1. 本地启动tomcat,默认8080端口。【注意防火墙开放端口】

  2. 注册域名解析到Nginx服务器的公网地址【或者修改本机host文件,将该域名映射到Nginx服务器的IP地址】

    C:\Windows\System32\drivers\etc\host

  3. 配置Nginx

    1. 在http的server块中修改server_name,即设置监听的端口和对外提供的域名。

      1
      2
      3
      4
      5
      server {
      listen 80;
      server_name 192.168.31.58;
      # 省略
      }
    2. 上面是监听的URL,接下来设置转发的到的服务器地址,即Location。

      在该server块中的location块中,添加转发到的地址。即proxy_pass http://localhost:8080

      1
      2
      3
      4
      5
      6
      location / {
      root html;
      # 要转发到的服务器地址
      proxy_pass http://localhost:8080;
      index index.html index.htm;
      }
    3. 启动Nginx服务器

    4. 在浏览器中,访问Nginx监听的IP地址和端口号,可以看到直接跳转到Tomcat主页了,即转发成功,即反向代理成功。

上面的反向代理仅实现了基本的代理功能,下面是一个进阶一点的,实现效果:

  1. 访问 http://192.168.31.58:9001/edu/ 直接跳转到 http://127.0.0.1:8080
  2. 访问http://192.168.31.58:9001/vod/ 直接跳转到 http://127.0.0.1:8081

即对路径进一步明确,利用Nignx不同访问路径跳转到不同的项目上。

准备工作:

  1. 开启两个Tomcat服务器,分别监听8080、8081端口。并创建具体的页面

  2. 在Nginx的配置文件中,在某个server的全局块中设置Nginx的监听IP和端口。并在该server块中添加两个location块。

    1. 每个location块表示跳转的具体的URL,正则表达式~表示server_name中任意起始地址。

    2. location指令说明:

      1
      2
      3
      location [= | ~ | ~* | ^~] uri {

      }
    3. 正则表达式规则:

      1. =:用于不含正则表达式的uri前,要求请求字符串与uri严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求。
      2. ~:用于表示uri包含正则表达式,并且区分大小写。
      3. ~*:用于表示uri包含正则表达式,并且不区分大小写。
      4. ^~:用于不含正则表达式的uri前,要求Nginx服务器找到标识uri和请求字符串匹配度最高的location后,立即使用此location处理请求,而不再使用location块中的这条狗你这uri和请求字符串做匹配。
      5. 注意,如果uri包含正则表达式,则必须要有~或者~*标识。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    server {
    listen 9001;
    server_name 192.168.31.58;

    location ~/edu/ {
    proxy_pass http://localhost:8081;
    }

    location ~/vod/ {
    proxy_pass http://localhost:8082;
    }
    }

由本案例可知,配置文件中的http块的server块,就是负责监听本机某个端口的,其中的location块就是负责根据URL来转发到不同的服务器中,即反向代理。

4.2 实现负载均衡

负载均衡就是将请求分发到各个服务器上。实现效果如下:

浏览器地址栏输入地址:http://192.168.31.58:9001/edu/a.html,负载均衡效果,将请求平均分发到 http://127.0.0.1:8081和http://127.0.0.1:8082上面。

准备工作:

  1. 两台tomcat服务器,分别监听8081和8082端口,分别设置/edu/a.html页面。

  2. 配置Nginx服务器配置文件,在http块的全局块中,添加upstream字段,后跟名称以及{}。也就是负载均衡的服务器列表。

    1
    2
    3
    4
    5
    upstream myserver {
    # 转发的服务器IP端口
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    }
  3. 配置Nginx服务器配置文件,在http块中的server块中的全局块中,设置监听的IP和端口

    1
    2
    3
    4
    server {
    listen 9001;
    server_name 192.168.31.58;
    }
  4. 设置location,转发/edu/a.html请求到127.0.0.1:8080端口和8081端口。这里因为在上面已经有负载均衡列表了,这里直接转发即可。

    1
    2
    3
    location / {
    proxy_pass http://myserver;
    }
  5. 访问Nginx监听的接口即可,多次刷新,可以看到会跳转到不同端口的界面上【这里需要提前在不同端口的界面上写不同的内容,方便查看跳转的是哪个界面】

上面只是最基本的负载均衡方法——轮询。负载均衡其实有很多种策略

  1. 轮询(默认)

    每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器宕掉,能自动剔除。

  2. weight权重

    weight表示权重,默认为1,权重越高,被分配的请求就越多。weight和分配的请求次数成正比,适用于后端服务器性能不均的情况。使用方式就是在upstream字段中的转发IP后面添加weight=权重值即可。

    1
    2
    3
    4
    5
    upstream myserver {
    # 转发的服务器IP端口
    server 127.0.0.1:8081 weight=5;
    server 127.0.0.1:8082 weight=1;
    }
  3. ip_hash

    每个请求按访问ip的hash结果来转发,这样每个访客访问固定的一个后端服务器,可以解决session共享的问题。使用方式就是在upstream字段的里面添加ip_hash;标识即可。

    1
    2
    3
    4
    5
    6
    upstream myserver {
    ip_hash;
    # 转发的服务器IP端口
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    }
  4. fair

    按照后端服务器的响应时间来分配请求,响应时间短服务器的优先分配。使用方式就是在upstream字段的里面添加fair;字段即可。

    1
    2
    3
    4
    5
    6
    upstream myserver {
    # 转发的服务器IP端口
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    fair;
    }

4.3 动静分离

动静分离其实是为了更加高效,充分利用服务器资源。静态和动态专业化。

动静分离指的是动态资源和静态资源放在不同的服务器上,即Nginx将静态资源请求和动态资源请求转发到不同的服务器上。不能简单理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求和静态请求分开

image-20221002230603779

可以理解成使用Nginx处理静态页面,Tomcat(或其他web服务器)处理动态页面。动静分离目前从实现角度来讲大致分为两种:

  1. 一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上(比如nginx自身),动态资源存放在另一个服务器上,也是目前主流推崇的方案
  2. 一种是动态和静态文件混合在一起发布(放在一个服务器上,不同的项目),通过nginx来分开。

对于静态资源,可进一步采用缓存来优化,使用服务器本地缓存。

通过server块中的location指定不同的后缀名实现不同的请求转发。通过expires参数设置,可以设置浏览器缓存的过期时间,减少与服务器之间的请求和流量。具体Expires定义:是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。(如果经常更新的文件,不建议使用Expires来缓存),我这里设置3d,表示在这三天之内访问这个URL,发送一个请求,比对服务器该文件最后更新时间没有变化,则不会从服务器抓取,返回状态码304;如果有修改,则直接从服务器重新下载,返回状态码200。其实就是根据服务端的文件是否改变来确定是否从服务端传输文件。如果没有改变,则无需传输,直接使用缓存即可。

准备工作【采用第一种方式】:

  1. 在nginx服务器上准备静态资源【注意资源所在路径要和下面的配置对应】,在tomcat服务器上准备动态资源;

  2. 在nginx配置文件中的server块中设置监听IP和端口;

  3. 在server块中的location中设置静态资源请求,其实就是将URL中的某个路径映射到Nginx服务器的某个目录下。

    1
    2
    3
    4
    5
    6
    7
    # 设置静态资源请求,就是请求自身nginx某个路径下的静态资源文件。
    # /www/ 表示URL中的地址,即自动映射到 root + /www/目录下。即D:/www/下。
    location /www/ {
    root D:/;
    index index.html index.htm;
    autoindex on; # 表示可列出文件夹中的内容
    }
  4. 至于动态资源,和前面的tomcat类似。直接转发动态请求即可。(其实location路径匹配类似Java中的异常,从上到下来逐个匹配的,这里为了简单起见,只是写了一个非静态路径文件,即根目录,统统转发到Tomcat上)

    1
    2
    3
    4
    5
    location / {
    root html;
    proxy_pass http://localhost:8080;
    index index.html index.htm;
    }

5. Nginx配置高可用(High Availability)集群

上面的情景中存在一种问题,当Nginx服务器宕机后,那么其暴露的端口就无法提供功能,而后面的Tomcat又没有暴露给用户,因此整个系统将无法使用。

因此需要配置高可用集群,配置多个Nginx服务器,一个是主Nginx服务器(Master),一个是备份Nginx服务器(Backup)。客户端一般情况下访问主服务器,当主服务器宕掉之后,会自动切换成备份服务器(注意,为了方便,这是对用户不可见的)。这个功能实现需要keepalived的帮助。而且由于两个Nginx服务器的IP是不同的,因此,而客户端是不能改变的,因此需要对外暴露一个虚拟的IP,两台服务器均绑定这个虚拟IP,之后由keepalived来决定将请求转发到哪台Nginx服务器上,实际上keepalived起到的就是一个路由作用

image-20221003111716031

准备工作:

  1. 两台nginx服务器,绑定虚拟IP地址(对外暴露这个虚拟IP地址和端口)。

  2. 在两台服务器上安装keepalived软件。

  3. 修改两台nginx服务器上的keepalived软件的配置文件。

    切换到keepalived安装目录下的conf文件中。配置文件的内容分为三部分。

    1. global_defs区域,全局配置

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      global_defs {
      notification_email {
      acassen@firewall.loc
      failover@firewall.loc
      sysadmin@firewall.loc
      }
      notification_email_from Alexandre.Cassen@firewall.loc
      smtp_server 192.168.17.129
      smtp_connect_timeout 30

      # 关键地方,路由设置,即通过该名字访问到本主机。
      router_id LVS_DEVELBACK
      }
    2. vrrp_script区域,包括检测脚本【检测该某个Nginx服务器是否存活】、权重等参数。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      vrrp_script chk_http_port {
      # 设置检测脚本文件的路径,即通过该脚本指定检测的规则。
      script "/usr/local/src/nginx_check.sh"

      # 脚本每隔一定的间隔时间,来检测执行一次
      interval 2

      # 设置当前服务器的一个权重
      weight 2
      }

      下面是具体脚本的内容

      1
      2
      3
      4
      5
      6
      7
      8
      9
      #!/bin/bash
      A=`ps -C nginx -no-header | WC -l`
      if [ $A -eq 0 ]; then
      /usr/local/nginx/sbin/nginx
      sleep 2
      if [ `ps -C nginx --no-header | wc -l` -eq 0 ]; then
      killall keepalived
      fi
      fi
    3. vrrp_instance区域,设置本机为主服务器还是备份服务器,在某个网卡上绑定一个虚拟IP

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      vrrp_instance VI_1 {
      # 设置本机是主服务器MASTER/备份服务器BACKUP
      state MASTER

      # 将虚拟主机绑定在该网卡上,即通过该网卡监听请求
      interface ens33

      # 虚拟路由id,主、备服务器的virtual_router_id必须相同
      virtual_router_id 51

      # 优先级,主备机取不同的优先级,主机值较大,备份机值较小
      priority 100

      # 每隔一定的时间来探测是否存活,心跳机制。
      advert_int 1
      authentication {
      auth_type PASS
      auth_pass 1111
      }

      # 虚拟IP地址,即对外暴露的这个IP。也就是客户端要请求这个IP,可以绑定多个虚拟IP
      virtual_ipaddress {
      192.168.17.50
      }
      }
    4. 启动两台的nginx,并分别启动keepalived软件

    5. 客户端访问虚拟IP(此时请求的就是主服务器),而宕掉主服务器之后,再次请求,请求的是备份服务器。即通过暴露虚拟IP,背后可设置多台服务器集群。

由上面的配置其实可以发现,高可用只需要在原来的负载均衡基础上,再添加一台/多台备份nginx服务器,并同样设置负载均衡,然后添加keepalived,设置keepalived配置文件即可。

6. Nginx原理

Nginx启动之后,会有两个进程,一个是master,一个是worker(可以有多个)。master接收到任务后会不会自己处理任务,而是将任务分配给worker。

image-20221003134055993

image-20221003133715056

但是本质上,worker是以“争抢”的机制来获取任务的,而不是master轮询的方式。抢到后,依据反向代理机制来交给tomcat等服务器处理。

image-20221003134137373

master-worker机制的好处:

那么多个worker,前面提到过存在热部署,此时执行热部署命令后,空闲的worker就是加载配置文件,而执行任务的worker在执行完之后再加载配置文件。即达到了热部署的效果。

另外,对于每个worker进程来说,都是独立的进程,不需要加锁,所以省掉了锁带来的开销。同时在编程以及问题查找时,也会方便很多。其次,采用独立的进程,互相之间不会影响,一个进程退出后,其他进程还在工作,服务不会中断,master进程则会快启动新的worker进程。

那么到底设置多少个worker比较合适呢?

nginx同redis类似,都采用了IO多路复用机制,每个worker都是一个独立的进程,每个进程里只有一个主线程,通过异步非阻塞的方式来处理请求,即使是千万个请求也不在话下。每个worker的线程可以把一个CPU的性能发挥到极致。所以worker数和服务器的CPU数相等是最为适宜的。设置少了会浪费CPU,设置多了会造成CPU频繁切换上下文带来的损耗。

即上面配置文件中的worker_processes 1,设置的worker数量。

worker_connection连接数

这个值是表示每个worker进程所能建立连接的最大值,所以,一个nginx能建立的最大连接数应该是 worker_connections * worker_processes

注意,如果http请求本地资源,那么能够支持的最大并发数量就是上面的。

如果是http1.1,其浏览器每个访问要占两个连接,所以最大并发数量需要除以二。

而如果是http作为反向代理来说,最大并发数量应该是除以4。

这里的意思是:客户端向nginx发送需要一个连接,而nginx返回给客户端也需要一个连接,因此在nginx端,一次接受和处理实际上是两个连接。如果是反向代理,那么nginx还需要和tomcat服务器建立请求和响应连接,也会占用两个,即除以4。

注意连接数connection和并发数的区别。

7. 备注

参考B站《尚硅谷》。


文章作者: 浮云
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 浮云 !
  目录