前言

Nginx 是一个高性能的 HTTP 和反向代理服务器,特点是占有内存少,并发能力强,事实上 nginx 的并发能力确实在同类型的网页服务器中表现较好。

正向代理

客户端请求目标服务器之间的代一个理服务器;请求会先通过代理服务器,然后再转发请求到目标服务器,获得内容后再响应给客户端

图片

反向代理

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

图片

图片

负载均衡

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

图片

但是随着信息数量的不断增长,访问量和数据量的飞速增长,以及系统业务的复杂 度增加,这种架构会造成服务器相应客户端的请求日益缓慢,并发量特别大的时候,还容易造成服务器直接崩溃。
将原先请求集中到单个服务器上的情况改为将请求分发到多个服务器上,将负载分发到不同的服务器,也就是我们所说的负载均衡 。
将下面的21个请求分发到三个服务器上:

图片

动静分离

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

安装

Nginx官网
复制下载链接(推荐选择稳定版下载):
图片
linux环境安装:
安装依赖(为简便操作,使用yum安装):
安装前,可以先检查下是否已安装:

1
2
3
4
5
6
7
8
9
# gcc -v

# rpm -qa prce

# yum list installed | grep zlib*

# rpm -qa openssl

# openssl version

图片

  • 安装gcc环境,主要用于使用nginx的rewrite(url重写跳转)功能

    1
    # yum install gcc-c++
  • 安装PCRE库,用于解析正则表达式(rewrite需要使用正则表达式,因此需要安装pcre依赖包)

    1
    # yum install -y pcre pcre-devel
  • 安装zlib压缩和解压缩依赖

    1
    # yum install -y zlib zlib-devel
  • 安装openssl,用于实现https
    1
    # yum install -y openssl openssl-devel
    安装nginx:
    1
    # wget http://nginx.org/download/nginx-1.20.2.tar.gz
    解压:
    1
    # tar -zxvf nginx-1.20.2.tar.gz
    进入解压缩目录,编译:
    1
    2
    3
    # cd nginx-1.20.2/

    # ./configure
    安装:
    1
    # make && make install

开放端口

查看开放的端口号:

1
# firewall-cmd --list-all

设置开放的端口号:

1
2
# firewall-cmd --add-service=http –permanent
# sudo firewall-cmd --add-port=80/tcp --permanent

重启防火墙:

1
# firewall-cmd –reload

卸载

需要将nginx的进程关闭:

1
# ./nginx -s stop

将安装的nginx进行删除:

1
# rm -rf /usr/local/nginx

将安装包之前编译的环境清除掉:

1
# make clean

常用命令

以下命令均需要进入nginx目录(默认usr/local/nginx),在/sbin路径操作

启动

进入nginx目录的sbin路径下,启动nginx:

1
2
3
# cd /usr/local/nginx/sbin/

# ./nginx

访问服务器IP地址:
图片

关闭

1
# ./nginx -s stop

重新加载

1
# ./nginx -s reload

配置文件

nginx默认的配置文件(包括主配置文件nginx.conf)都放在nginx默认路径(usr/local/nginx)下的conf 目录下。

第一部分:全局块

从配置文件开始到 events块之间的内容,主要会设置一些影响 nginx 服务器整体运行的配置指令,主要包括配置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以及配置文件的引入等。
比如顶部的配置项:

1
2
3
4
5
6
7
8
9
10

#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;

这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约

第二部分:events 块

比如下面的配置:

1
2
3
events {
worker_connections 1024;
}

events块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word process 可以同时支持的最大连接数等。
上述例子就表示每个 work process 支持的最大连接数为 1024。这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。

第三部分:http 块

这算是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。
需要注意的是:http块也可以包括 http全局块server块

http 全局块

http全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。

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
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;
# }
#}

}

server块

这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了节省互联网服务器硬件成本。
每个 http块可以包括多个 server块,而每个 server块就相当于一个虚拟主机。
而每个 server块也分为全局 server块,以及可以同时包含多个locaton块

  1. 全局server块

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

  2. location块

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

反向代理

修改nginx配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    server {
listen 80;
server_name 101.123.145.xx;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root html;
proxy_pass http://www.baidu.com;
index index.html index.htm;
}
.......

将域名映射到服务器IP(即server_name,上例值为101.123.145.xx),当访问域名时,会解析到服务器IP(如果没有通过域名映射,可以直接访问服务器IP),会代理到http://www.baidu.com(proxy_pass)。
也就是说,上例中当访问域名(或直接访问域名映射的IP)会跳转到百度

修改完配置文件后,重启nginx服务。
由于80端口被占用,所以下例使用81端口做演示:
图片

示例2:

新建一个server块,或者直接在之前的server块修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  server {
# 监听101.123.145.xxx下的999端口
listen 999;
# listen somename:8080;
server_name 101.123.145.xxx;

# 使用正则匹配路径
location ~ /baidu/ {
root html;
proxy_pass http://baidu.com;
index index.html index.htm;
}
.......
}

location指令用于匹配 URL。
语法如下:

  • = :用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配

成功,就停止继续向下搜索并立即处理该请求。

  • ~:用于表示 uri 包含正则表达式,并且区分大小写。
  • ~*:用于表示 uri 包含正则表达式,并且不区分大小写。
  • ^~:用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字

符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location 块中的正则 uri 和请求字符串做匹配。
注意:如果 uri 包含正则表达式,则必须要有 ~ 或者 ~*标识。

示例3:

我们知道,使用Nginx的反向代理一般是为了隐藏真实请求地址。

所以一般都是对公开的域名进行代理,当访问到域名的指定路径时,通过反向代理,由Nginx访问我们真实的请求地址。

比如下面这个示例,当我们访问ahzoo.cn下的api路径时(即http://ahzoo.cn/api/xxx),会由Nginx代理,来访问我们本机的真实请求(即http://本机IP:8080/api/xxx)。

1
2
3
4
5
6
7
8
9
10
11
   server {
# 监听80端口
listen 80;
server_name ahzoo.cn;

# 当前访问当前服务(ahzoo.cn)下所有的/api/路径,都会被代理为proxy_pass下(即本机)的/api/路径
location /api/ {
proxy_pass http://127.0.0.1:8080;
}
.......
}

上面只是一个简单的示例,实际使用中locationproxy_pass中末尾斜杠(/)的添加与否,也会影响代理到结果。

负载均衡

负载均衡即是将负载分摊到不同的服务单元,既保证服务的可用性,又保证响应足够快,给用户很好的体验。快速增长的访问量和数据流量催生了各式各样的负载均衡产品,很多专业的负载均衡硬件提供了很好的功能,但却价格不菲,这使得负载均衡软件大受欢迎,nginx 就是其中的一个,在 linux 下有 Nginx、LVS、Haproxy 等等服务可以提供负载均衡服务。

修改nginx配置文件:
创建一个upstream配置,并在server配置中(proxy_pass)使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
upstream myserver {
ip_hash;
server 101.123.145.xxx:8080 weight=1;
server 101.123.145.xxx:999 weight=1;
}
server {
listen 80;
server_name 101.123.145.xxx;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
proxy_pass http://myserver;
root html;
index index.html index.htm;
}
.......

启动两个(tomcat)服务器(8080端口和999端口);
由于在upstream中对两个服务器的权重都设为了1,所以当访问server_name中的Ip地址时会,同等概率跳转到999端口和8080端口的服务器.
Nginx 提供了几种分配方式(策略):

  1. 轮询(默认)

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

  1. weight

weight 代表权,重默认为 1,权重越高被分配的客户端越多
指定轮询几率,weight 和访问比率成正比,用于后端服务器性能不均的情况。 例如:

1
2
3
4
upstream server_pool { 
server 101.123.145.xxx weight=9;
server 101.123.145.xxx weight=9;
}
  1. ip_hash

每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。 例如:

1
2
3
4
5
upstream server_pool { 
ip_hash;
server 101.123.145.xxx:80;
server 101.123.145.xxx:80;
}
  1. fair(第三方)

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

1
2
3
4
5
upstream server_pool { 
server 101.123.145.xxx:80;
server 101.123.145.xxx:80;
fair;
}

动静分离

Nginx 动静分离简单来说就是把动态跟静态请求分开,可以理解成使用 Nginx 处理静态页面,服务器处理动态页面。
动静分离从目前实现角度来讲大致分为两种:

  1. 一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案;
  2. 另外一种方法就是动态跟静态文件混合在一起发布,通过 nginx 来分开。

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

示例:
/data/路径下创建一个web文件夹作为动态资源访问路径,并在web目录下创建一个html文件作为动态资源;
/data/路径下创建一个image文件夹作为静态资源访问路径,并在该image目录上传静态资源,以供测试
图片
修改nginx配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  server {
listen 81;
server_name 101.123.145.XXX;

#charset koi8-r;

#access_log logs/host.access.log main;

location ~ /web/ {
root /data/;
index index.html index.htm;
}
location ~ /image/ {
root /data/;
# autoindex表示文件是否以目录展示
autoindex on;
}

....

图片
图片

重写跳转

示例1:
使用重写跳转,将网址全部跳转到https:

1
rewrite ^(.*)$ https://$host$1 permanent;

实例:

1
2
3
4
5
6
7
8
9
10
server
{
listen 80;
server_name ahzoo.cn;
include enable-php.conf;
rewrite ^(.*)$ https://$host$1 permanent;

......
......
}