Nginx

cccs7 Lv5

Nginx

Nginx 是高性能的 HTTP 和反向代理的服务器,处理高并发能力是十分强大的,能经受高负载的考验,有报告表明 支持高达 50000 个 并发连接数

Nginx 简介

Nginx 发行版本

  • Nginx开源版 http://nginx.org/en/

    官方原始的Nginx版本

  • Nginx plus商业版

    开箱即用,集成了大量功能

  • Open Resty https://openresty.org/cn/

    OpenResty是一个基于Nginx与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。更适用于需要大量二次开发的场景,有极强的扩展性

  • Tengine https://tengine.taobao.org/

    由淘宝网发起的Web服务器项目。它在Nginx (opens new window) 的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网 (opens new window) 天猫商城 (opens new window) 等得到了很好的检验。相比于Open Resty,扩展性不够强,但是能够满足绝多数使用场景

Nginx 安装


下载Nginx包

官网下载地址(opens new window)

image-20220501140833867

使用FTP工具将文件上传到虚拟机中

我直接将其放在了 /usr/local/

解压 Nginx 包

1
2
3
4
tar -zxvf  nginx-1.21.6.tar.gz #解压到当前目录

cd nginx-1.21.6 #进入解压后的文件夹
ls #文件夹中的文件:auto CHANGES.ru configure html man src CHANGES conf contrib LICENSE README

安装依赖库

1
2
3
4
5
6
7
8
#安装C编译器
yum install -y gcc

#安装pcre库
yum install -y pcre pcre-devel

#安装zlib
yum install -y zlib zlib-devel

安装

1
2
3
./configure --prefix=/usr/local/nginx #使用prefix选项指定安装的目录
make
make install

启动

1
2
3
4
5
cd /usr/local/nginx/sbin

ls # 里面是一个nginx的可执行文件

./nginx # 启动这个可执行

关闭防火墙

1
systemctl stop firewalld

补充 Nginx 命令

1
2
3
4
./nginx -s stop #快速停止
./nginx -s quit #完成已接受的请求后,停止
./nginx -s reload #重新加载配置
./nginx -t #检查nginx配置是否正确

查看 Nginx 状态

ps -ef | grep nginx

启动时

image-20230325144826485

停止后

image-20230325145328879

注册系统服务

通过系统服务的方式启动 Nginx

vim /usr/lib/systemd/system/nginx.service


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit] 
Description=nginx
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
ExecQuit=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target # 多用户

Nginx 概述


Nginx (“engine x“) 是一个高性能的 HTTP 和 反向代理服务器,特点是 占有内存少,并发能力强,事实上 Nginx 的并发在同类型的网页服务器中表现确实较好,国内有很多网站使用 Nginx

Nginx 作为 web 服务器

Nginx 可以作为静态页面的 web 服务器,同时还支持 CGI 协议的动态语言,比如 Perl、PHP 等。但是不支持 Java。Java 程序只能通过与 Tomcat 配合完成。Nginx 专为性能优化而开发,性能是其最重要的考量,实现上非常注重效率,能经受高负载的考验。

正向代理

Nginx 不仅可以做反向代理,实现负载均衡。还能用作正向代理来进行上网等功能。

正向代理: 如果把局域网外的 Internet 想象成为一个巨大的资源库,则局域网中的客户端访问 Internet,则需要通过代理服务器进行访问,这种代理服务器就称为正向代理

正向代理可以理解为 【客户端】 的代理

image-20230325173206891

反向代理

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

反向代理可以理解为【服务器】代理

image-20230325174430764

负载均衡

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

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

首先,我们想到的可能是升级服务器的配置,比如提高 CPU 执行的频率,加大内存等提高机器的物理性能来解决此问题。但是我们知道 摩尔定律的 日益失效,硬件的性能提升已经不能满足日益提升的需求了,那么怎么办呢?

上面的分析我们去掉了增加服务器 物理配置来解决问题的办法,也就是说 纵向解决办法不行,那么横向呢,横向增加服务器的数量,这时候 集群 的概念产生了,单个服务器解决不了,我们增加服务器的数量,然后 将请求分发到各个服务器上去,将原先请求集中到 单个服务器的请求 改为将请求分发到多个服务器上,将负载分发到不同的服务器,也就是我们所说的 负载均衡

Nginx 使用

Nginx 目录

Nginx 一般安装在 /usr/local/nginx 下, 安装时 也可 --prefix 指定安装目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
conf #配置文件
|-nginx.conf # 主配置文件
|-其他配置文件 # 可通过那个include关键字,引入到了nginx.conf生效

html #静态页面

logs
|-access.log #访问日志(每次访问都会记录)
|-error.log #错误日志
|-nginx.pid #进程号

sbin
|-nginx #主进程文件

*_temp #运行时,生成临时文件

image-20230325180400275

Nginx 配置


每次 修改 Nginx 配置文件,都需要重载才能生效

systemctl reload nginx

简化版的 nginx.conf

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
worker_processes  1; # 启动的worker进程数

events {
worker_connections 1024; #每个worker进程的连接数
}


http {
include mime.types; #include是引入关键字,这里引入了mime.types这个配置文件(同在conf目录下,mime.types是用来定义,请求返回的content-type)
default_type application/octet-stream; #mime.types未定义的,使用默认格式application/octet-stream

sendfile on; #详情,见下文
keepalive_timeout 65; #长链接超时时间

#一个nginx可以启用多个server(虚拟服务器)
server {
listen 80;#监听端口80
server_name localhost; #接收的域名

location / {
root html; #根目录指向html目录
index index.html index.htm; #域名/index 指向 index.html index.htm文件
}

error_page 500 502 503 504 /50x.html; # 服务器错误码为500 502 503 504,转到"域名/50x.html"
location = /50x.html {# 指定到html文件夹下找/50x.htm
root html;
}

}
}

根据上述文件,我们可以很明显的 将 nginx.conf 配置文件 分为三个部分

全局块

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

worker_processes 1;

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

events 块

比如上述的配置

1
2
3
events {
worker_connections 1024;
}

vents 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 wordprocess 可以同时支持的最大连接数等。

上述例子就表示每个 work process 支持的最大连接数为 1024.

这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置

http 块

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
 http {
#....其他属性
server {
listen 80;
server_name pro.cccs7.com;

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

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

server {
listen 80;
server_name test.cccs7.com;

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

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

这算是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。

需要注意的是: http 块也昆虫包括 http 全局块、server 块

http 全局块

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

server 块

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

每个http 块可以包括多个 server 块,而 每个 server 块 就相当于一个虚拟主机

而每个 server 块也分为全局 server 块,以及可以同时包含多个 location 块

  • server

    二级域名,映射 到不同静态页面

    可以写多个 server 字段,从前向后匹配,先匹配到哪个就用哪个

    用户 访问 pro.cccs7.com ,就会走到第一个 server 配置;test.cccs7.com 走到第二个 配置

  • location 块

    一个 server 块可以配置多个 location 块

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

sendlife

打开sendfile,用户请求的数据不用再加载到nginx的内存中,而是直接发送

image-20230325211126855

不同域名,映射到同一静态页面

server_name
  • 可以写多个,用空格分开
  • 使用 通配符(*)
  • 使用正则表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
http{ 		
server {
listen 80;
server_name *.cccs7.com ~^[0-9]+\.cccs7\.com$; # "\."是转译"."

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

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

反向代理和负载均衡


反向代理

这种代理方式叫做,隧道代理。有性能瓶颈,因为所有的数据都经过 Nginx,所以 Nginx 服务器的性能至关重要

image-20230325212844273

负载均衡

把请求 按照一定算法规则,分配给多态业务服务器(即使其中一个坏了/维护升级,还有其他服务器可以继续提供服务)

image-20230325213051123

反向代理 + 负载均衡

Nginx.conf 配置文件

启动 proxy_pass,root 和 index 字段就会失效

proxy_pass 后的地址必须写完整 http://xxx,不支持 HTTPS

当 访问 localhost 时(Nginx服务器),网页打开的是 http://xxx(应用服务器),网页地址栏写的还是 localhost

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
http{ 		
server {
listen 80;
server_name localhost;

location / {
proxy_pass http://xxx;
#root html/test;
#index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

*定义地址别名 **

使用upstream定义一组地址【在server字段下】

访问localhost,访问都会代理到192.168.174.133:80192.168.174.134:80这两个地址之一,每次访问这两个地址轮着切换(后面讲到,因为默认权重相等)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
http{
upstream httpds{
server 192.168.21.136:80; #如果是80端口,可以省略不写
server 192.168.21.137:80;
}
server {
listen 80;
server_name localhost;

location / {
proxy_pass http://httpds;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

设置权重

访问使用哪个地址的权重

1
2
3
4
upstream httpds{
server 192.168.174.133:80 weight=10;
server 192.168.174.134:80 weight=80;
}

关闭

1
2
3
4
upstream httpds{
server 192.168.174.133:80 weight=10 down;
server 192.168.174.134:80 weight=80;
}

备用机

如果192.168.174.133:80出现故障,无法提供服务,就用使用backup的这个机器

1
2
3
4
upstream httpds{
server 192.168.174.133:80 weight=10;
server 192.168.174.134:80 weight=80 backup;
}

动静分离


当用户请求时,动态请求分配到 Tomcat 业务服务器,静态资源放到 Nginx 服务器中


例子:

  • 如果请求的资源地址是location//的优先级比较低,如果下面的location没匹配到,就会走http://xxx这个地址的机器
  • 如果请求的资源地址是location/css/*,就会被匹配到nginx的html目录下的css文件夹中(我们把css静态资源放在这个位置)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
listen 80;
server_name localhost;

location / { # /的优先级比较低,如果下面的location没匹配到,就会走http://xxx这个地址的机器
proxy_pass http://xxx;
}

location /css { # root指的是html,location/css指的是root下的css,所以地址就是html/css
root html;
index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

使用正则

1
2
3
4
location ~*/(js|css|img){
root html;
index index.html index.htm;
}

URL 重写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
rewrite是URL重写的关键指令,根据regex(正则表达式)部分内容,重定向到replacement,结尼是flag标记。

rewrite <regex> <replacement> [flag];
关键字 正则 替代内容 flagt标记

正则:per1森容正则表达式语句进行规则匹配
替代内容:将正则匹配的内容替换成replacement

flag标记说明:
last #本条规则匹配完成后,继续向下匹配新的1ocation URI规则
break #本条规则匹配完成即终止,不再匹配后面的任何规则

redirect #返回302临重定向,游览器地址会显示跳转后的URL地址
permanent #返回301永久重定向,测览器地址栏会显示跳转后的URL地址

浏览器地址栏访问 xxx/123.html实际上是访问xxx/index.jsp?pageNum=123

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

location / {
rewrite ^/([0-9]+).html$ /index.jsp?pageNum=$1 break;
proxy_pass http://xxx;
}


error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

网关服务器

image-20230326173904991

上图中,应用服务器,不能直接被外网访问到,只能通过Nginx服务器进行访问(使用proxy_pass),这时候这台Nginx服务器就成为了网关服务器(承担入口的功能)

所以,我们启动应用服务器的防火墙,设置其只能接受这台Nginx服务器的请求

添加rich规则

1
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.174.135" port protocol="tcp" port="8080" accept" #这里的192.168.174.135是网关 服务器地址

移除rich规则

1
firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.174.135" port port="8080" protocol="tcp" accept"

重启

移除和添加规则都要重启才能生效

1
firewall-cmd --reload

查看所有规则

1
firewall-cmd --list-all #所有开启的规则

防盗链


当我们请求到一个页面后,这个页面一般会再去请求其中的静态资源,这时候请求头中,会有一个refer字段,表示当前这个请求的来源,我们可以限制指定来源的请求才返回,否则就不返回,这样可以节省资源image-20220503162830153

1
valid_referers none|server_name

设置有效的refer值

  • none:检测地址没有refer,则有效
  • server_name:检测主机地址,refer显示是从这个地址来的,则有效(server_name必须是完整的http://xxxx

注意:if ($invalid_referer)中if后有个空格,不写就会报错

1
nginx: [emerg] unknown directive "if($invalid_referer)" in /usr/local/nginx/conf/nginx.conf:27

例子:这里设置nginx服务器中的img目录下的图片必须refer为http:192.168.174/133才能访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
listen 80;
server_name localhost;

location / {
proxy_pass http://xxx;
}

location /img{
valid_referers http:192.168.174/133;
if ($invalid_referer){#无效的
return 403;#返回状态码403
}
root html;
index index.html index.htm;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

如果引用这张图片的页面且refer并没有被设置,图片无法加载出来

如果直接访问图片地址,因为没有refer字段指向来源,会直接显示Nginx的页面

image-20220503153401325

设置盗链图片

将提示图片放在html/img/x.png,访问设置防盗链图片时,就返回这x.png张图

1
2
3
4
5
6
7
8
location /img{
valid_referers http:192.168.174/133;
if ($invalid_referer){#无效的
rewrite ^/ /img/x.png break;
}
root html;
index index.html index.htm;
}

高可用场景


image-20220503174125433

用户访问时,访问的是一个 虚拟 IP, Keepalived 会选定一个 主服务器使用这个虚拟 IP

每台机器上的 Keepalived 会相互通信,根据其他机器上的 Keepalived 进程是否存在,判断服务器状态,如果 默认的 Master 停止了,就会在剩下的 Backup 机器中,竞选出一台 Nginx 服务器 作为 Master

安装 Keepalived

yum -y install keppalived

  • 配置文件在 /etc/keepalived/keepalived.conf
  • vrrp_instancevirtual_rouer_idauthenticationvirtual_ipaddr 这几个一样的机器,才算是在一个组里。这个组才会选出一个作为 Master 机器

这里设置两台机器,分别下载好 Keepalived,然后进行配置

机器一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
! Configuration File for keepalived

global_defs {
router_id lb1 # 名字与其他配置了keepalive的机器不重复就行
}

vrrp_instance cccs7 {#vrrp实例名可以随意取
state MASTER #只能有一个默认的Master,其他写BACKUP
interface ens33 # ip addr查看下网卡名,默认时ens33
virtual_router_id 51
priority 100 # 多台安装了keepalived的机器竞争成为Master的优先级
advert_int 1 #通信时间
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.16 #虚拟IP
}
}

机器二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
! Configuration File for keepalived

global_defs {
router_id lb2
}

vrrp_instance cccs7 {
state BACKUP #只能有一个默认的Master,其他写BACKUP
interface ens33
virtual_router_id 51
priority 50
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.16 #虚拟IP
}
}

通过 命令 ip addr 查看机器一的 ip 信息,可以看到虚拟 IP

image-20230326180207525

配置证书


购买服务器——>购买域名,并解析到这个主机——>购买证书,绑定到域名上,并且把证书文件安装到服务器,并在Nginx上配置好

这时候,这个域名就可以使用https进行访问里(https://xxxx),浏览器上会有一个小锁

image-20220503191754606

这里直接写申请到证书后的Nginx配置部分

下载证书文件

image-20220503192840029

image-20220503192957256

下载后,解压压缩包,可以看到两个文件,一个是 xxx.key(私钥)和xxx.pem(证书)

配置

将两个文件上传到Nginx目录中,记得放置的位置。我这里直接放在nginx.conf配置文件所在的目录(/user/local/nginx/conf),所以写的都是相对路径

1
2
3
4
5
6
server {
listen 443 ss1;

ss1 certificate xxx.pem; #这里是证书路径
ss1_ certificate_key xxx.key #这里是私钥路径
}
  • Title: Nginx
  • Author: cccs7
  • Created at: 2023-03-25 14:23:00
  • Updated at: 2023-06-29 23:13:26
  • Link: https://blog.cccs7.icu/2023/03/25/Nginx/
  • License: This work is licensed under CC BY-NC-SA 4.0.
 Comments