yokila
yokila
Published on 2024-01-17 / 70 Visits
0
0

Linux nginx的安装与入门

零、前言

本文先介绍了什么是nginx,然后从零开始给一台Linux服务器安装nginx,最后介绍了相关的nginx配置示例。

本文基于系统:Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-60-generic x86_64)

本文使用远程SSH客户端:OpenSSH Client

本文基于nginx版本:1.24.0

nginx官网:点击前往

注:在官网上,我看到官网都是叫“nginx”或“NGINX”,而国内外的各种文章/书有的叫“Nginx”,有的叫“nginx”,有的叫“NGINX”,看样子似乎都行。

注:虽然基本都是在Linux上玩nginx,但是其实nginx有支持windows,且一直在更新,只是没看到支持到了什么程度(有些较早的文章说相比于Linux缺乏了不少功能,随着时间的推进,不知道补齐功能了没有)。

一、什么是nginx

nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. For a long time, it has been running on many heavily loaded Russian sites including Yandex, Mail.Ru, VK, and Rambler. According to Netcraft, nginx served or proxied 20.72% busiest sites in December 2023. 

——官网介绍

收购变化:2019 年 3 月,著名硬件负载均衡厂商 F5 宣布收购 nginx,nginx 成为 F5 的一部分。

特点:系统资源消耗低、运行稳定且具有高性能的并发处理能力。

编写语言:C

nginx的不同版本:

  1. 开源版 nginx(官方):2004年发布。

  2. 商业版 nginx plus(官方):2013年推出。

  3. 淘宝版 Tengine:2011年开始开源。

  4. OpenResty:开源。

二、安装(Linux-Ubuntu)

官方教程:Installing nginx

注:不同操作系统平台安装的方式存在差异,建议遵循上面官方教程的步骤执行为主。

注:这里是使用apt安装的方式,还有通过压缩包安装的,建议另行寻找教程。

1、安装必备组件

执行命令:sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring

注意:可以先一个一个检测一下看看是否已经安装了,已安装了就不要重复安装。

Linux因为安装软件的方式多种多样,实在是不好检查一个软件是否真的没安装。

可能是用rpm安装的(检查命令例如:rpm -qa|grep curl

可能是用apt安装的(检查命令例如:apt list --installed|grep curl

源码编译安装的等等。

还可以检查一下相关文件是否存在,比如用 whereis curl

注意:如果rpm等没安装,则基本可以排除用对应方式安装的可能。

2、导入官方的 nginx 签名密钥

目的:以便 apt 可以验证下载的nginx软件包的真实性。

执行命令:curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

执行示例

命令解析(扩展了解):

curl 地址:发出get请求,这里是向nginx官网请求获取签名密钥。

gpg:GNU Privacy Guard,是PGP的一个开源替代品。PGP,即Pretty Good Privacy,一个专有的加密程序,用于对文件和目录进行签名、加密和解密。

gpg --dearmor:将下载到的pgp内容转换成gpg内容。

tee:将转换后的gpg内容输出到指定的文件中(命令行输出流照常输出)。

/usr/share/keyrings:在Ubuntu上,该目录是转换后的GPG文件的推荐位置,因为它是Ubuntu存储keyring的默认位置。

>/dev/null:在 Linux 系统中,/dev/null 是一个特殊的文件,它被称为“空设备”。它没有任何数据,读取它永远不会产生任何输出,写入它永远不会导致任何数据被存储。/dev/null 起着丢弃数据的作用,可以用于一些需要忽略输出或者输入的场合。>/dev/null表示禁止输出。(这里是让原本会显示的gpg密钥不显示出来)

3、验证下载的文件是否包含正确的密钥

执行命令:gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg

执行示例

注意:执行结果要和官网提供的示例结果做比对,如果输出的密钥信息不对,就要删除掉,重新下。点击前往官网

命令解析(扩展了解):

--dry-run:gpg指令,表示不进行任何更改,仅查看密钥

--quiet:gpg指令,表示尽量保持静默(让GPG别打印它的一些运行信息)

--no-keyring:gpg指令,表示不使用任何keyring。这将会覆盖默认和其他指定keyring的指令。(gpg几乎所有操作都需要一个keyring,如果不用这个选项则要么是gpg会使用默认的keyring,要么你必须指定一个keyring)

--import --import-options import-show:gpg指令,表示显示导入的密钥的信息,和--dry-run结合就是只查看密钥,不修改/导入到系统中。

4、 设置apt存储库为找稳定版的nginx软件包

执行命令:echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list

其实就是往apt的配置里,写上去哪里下nginx,以及用什么密钥去校验。

5、设置存储库固定以优先选择nginx官方提供的发行版

执行命令:echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | sudo tee /etc/apt/preferences.d/99nginx

执行示例

其实本身也是在给apt写配置信息,优先级为900。

6、apt获得系统上所有包的最新信息

执行命令:sudo apt update

该命令实际上是为了加载nginx的最新信息,使得等下就可以安装最新的nginx官方提供的稳定版的nginx。

7、安装nginx

执行命令:sudo apt install nginx

执行示例

注意:提示文本最后第二行,有写nginx.service的绝对路径(而且还配置进了sytemctl里),比如我的是在这里:/lib/systemd/system/nginx.service

注意安装过程中有文本提示:The following packages were automatically installed and are no longer required.

所以我们可以按照提示,删除这些无用的包。

执行命令:sudo apt autoremove (当然,删不删取决于你,都行)

三、配置与操作

nginx的各种官方文档(包括配置文件的各字段说明)nginx documentation

nginx操作指引:Beginner’s Guide

1、先查看一下nginx服务的启动配置

service nginx status (或systemctl status nginx

服务未启动

注意服务运行中时的Unit描述内容里的第二行:

Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)

Loaded 描述的是操作系统启动时会不会启动这个服务。

enabled 表示开机时启动,disabled 表示开机时不启动。

该服务路径为:/lib/systemd/system/nginx.service

vendor preset 为 Linux发行版 默认配置,是在Linux 发行制作过程预设的,一般一些重要的系统服务会配置为enabled。使用 systemctl enable/disable 来设置为开机自启动,并没有设置到操作系统的发行预设里,所以进行设置开机启动项的时候,不会影响到 vendor preset 的值。 如果是同一名称的服务(例如现在这个nginx.service),既使用了 systemctl enable,又配置了vendor preset,systemctl enable/disable 的优先级要高于vendor preset(毕竟 systemctl 相当于是用户手动设置)。

如果要禁止nginx.service开机自启动,则可以执行命令:systemctl disable nginx.service

如果要设置nginx.service开机自启动,则可以执行命令:systemctl enable nginx.service

2、启动nginx

执行命令:service nginx start (或:systemctl start nginx

注意:用 service/systemctl 启动的话,就得用 service/systemctl 停止nginx,service和sytemctl可以混用,但是不能和nginx -s xxx混用,具体为啥请见下文 【停止nginx】的内容。

(直接操作nginx来启动的方式,见下文)

启动实例

注:service nginx status 是看启动后的情况,非必须执行。

通过查看nginx服务的信息,可以看到几个关键信息。

① 执行的nginx程序位于 /usr/sbin/nginx

所以,实际上你也可以去到这个目录,直接执行这个 可执行文件 来启动nginx。(如果是以本文的安装方式,任意位置都能直接执行nginx,不需要特意到达文件所在目录)

步骤:

  1. 执行命令:cd /usr/sbin

  2. 执行命令:nginx

注意,这种方式启动的话,Linux服务感知不到nginx已经启动了。所以此后不能用service和systemctl来管理。

示例

② nginx加载的配置文件在/etc/nginx/nginx.conf

按照官方描述,默认情况下,nginx的配置文件叫nginx.conf,会被放置在这几个目录之一中:

/usr/local/nginx/conf

/etc/nginx

 /usr/local/etc/nginx

③ nginx有三个进程,一个主进程,多个工作进程

nignx正常会有一个主进程,多个工作进程。

主进程用来读取和验证配置,以及管理工作进程(比如创建)。

工作进程用来真正意义上的处理请求。工作进程的数量由配置文件进行设置,默认是会和CPU核心数一致(配置文件里对应值配置成auto)。

默认情况下,nginx启动后,就在监听80端口。

可以通过端口监听命令查看到,执行命令:netstat -ntulp | grep nginx

此时浏览器中输入:服务器IP:80 (例如:127.0.0.1:80)就能访问到nginx的默认页面(该页面也是用来证明nginx运行正常的途径)(因为80是http的默认端口,所以访问80端口时其实也可以不附带端口号)

nginx默认页面

注:如果访问不通,可能是 防火墙安全组 没开启对应端口的访问允许。

3、修改nginx配置以定义代理

前文中,我们已经知道nginx所加载的配置文件的路径。

那么,我们就可以去编辑对应的配置文件。

注:下文仅以常见的http代理为例,不涉及mail等代理。

nginx修改配置文件前须知:

① 其实nginx的代理,简单来说就是在一个个顶级上下文(如:http,stream,mail)里写一个一个的server块。具体server块是直接放在nginx.conf里,还是以独立的文件形式存在再配置好路径加载,都行。(这也就使得下文定义代理的修改配置方式有两种)

② 监听的端口,需要检查Linux防火墙是否允许访问(命令:sudo ufw status),如果是云服务器,则还要检查云服务的安全组是否开放了对应端口。

Ubuntu防火墙允许外部访问端口(以12300为例),执行命令:sudo ufw allow 12300

Ubuntu防火墙删除增加的规则(以12300为例),执行命令:sudo ufw delete allow 12300

接下来是操作:

(1) 进入到配置文件所在目录(比如我的在 /etc/nginx/ )

执行命令:cd /etc/nginx/

(2) 修改配置(方式一:直接修改配置文件nginx.conf)(不太推荐在这里写server)

执行命令: vi nginx.conf

默认内容

各个字段含义:

error_log  /var/log/nginx/error.log notice:配置nginx运行期间的处理流程相关信息的日志输出路径,不只是错误日志信息(当前级别为notice,所有选项:debuginfonoticewarnerrorcritalertemerg

worker_connections  1024:单个工作进程的最大同时连接数(所有连接,包括与客户端和代理服务器之间的连接等)。需要注意不能超过系统的最大同时打开文件数。

log_formatmain xxxx:配置access_log的日志格式,main表示这个格式的命名,后面一大串就是格式定义。

access_log  /var/log/nginx/access.log  main:配置请求接入,即访问的相关信息日志输出路径。main是指定使用的日志格式的名字。

include /etc/nginx/conf.d/*.conf:加载指定的文件。这里是指明当前的http上下文额外加载的配置文件路径(注意通配符)

例:新增http代理server(代理静态文件的加载)

执行命令:vi nginx.conf

访问某文件夹里的静态文件代理

在其他PC上获取nginx代理的这个静态文件内容,执行命令:curl 128.0.0.1:12302/files/example.txt

(128.0.0.1是nginx所在服务器的地址)

(example.txt是nginx所在服务器上/apps/files文件夹中的一个文件)

请求获取文件内容示例

listen值将被nginx用于监听网络请求,可以是 IP 协议的形式(主机有多个IP时可以指定监听某个IP下的请求,不写IP只写端口就是所有IP的该端口),也可以是 UNIX 域套接字(sock文件路径)。如果不设置 listen 指令,nginx 在以超管运行时则监听 80 端口,以非超管运行时则监听 8000 端口。

server_name,有域名写域名,没域名写服务器的ip地址。

location 表示请求路径匹配(后面跟着的URI可以写正则表达式),以匹配程度最高的作为优先,然后是按出现顺序。匹配到后,就会进入location里面。

root设置请求的根路径。这里配置的路径,会被放在location的URI前面。例如本例中,root配置的是【/apps/】 ,location匹配的是 【/files/】 ,则请求 【128.0.0.1:12302/files/example.txt 】会变成 【128.0.0.1:12302/apps/files/example.txt 】。

(实测,root 路径的最后加不加斜杠都一样,即也可以写成【/apps】)

(实测,像此处访问本地路径,location 路径的最后加不加斜杠都一样,即也可以写成 【/files】)

(如果路径规则写错,获取文件失败,则会在error_log中看到对应的日志信息)

(2)修改配置 (方式二:独立配置文件)(推荐如此新增server)

进入前文nginx.conf中的【额外加载的配置文件路径】(例如我的是在:/etc/nginx/conf.d/)

执行命令:cd /etc/nginx/conf.d/

新建的配置,只要文件名符合 *.conf 的命名格式,就会被nginx加载(依据nginx.conf中的加载配置)。

例1:代理前端静态文件的加载

执行命令(新建并编辑新配置文件):vi simpleFront.conf

文件里输入如下的内容:

server {
    listen  12300;
    server_name  127.0.0.1;

    location / {
        root /apps/simpleWeb/dist;
        index index.html index.htm;
    }

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

index 定义将用作索引的文件,名称可以包含变量,可以提供多个,最后一个文件可以是绝对路径,nginx将按照顺序检查提供的文件。使用索引文件,会使得内部进行重定向,即路径只输入到了 / ,但是最终重定向加载了index匹配到的文件(比如常见的Vue项目的index.html)。

error_page 定义发生特定错误时(500 502之类的HTTP状态码)将给客户端展示的页面(如 /50x.html最终指向的/usr/share/nginx/html/50x.html)。

例2:代理后端服务

执行命令(新建并编辑新配置文件):vi simpleBackend.conf

输入如下的内容:

server {
    listen  12301;
    server_name  127.0.0.1;

    charset utf-8;

    location / {
        proxy_pass http://127.0.0.1:12313;
    }
}

charset将指定的字符集添加到响应的标头“Content-Type”上,例如常见的utf-8。

proxy_pass表示要把监听到的请求转发到哪里(哪个被代理的服务),例如这里写的是【本机的12313端口】(本机访问本机时防火墙不需要开放12313端口出来)。转发的目标路径,可以在端口后面加上URI路径,例如 http://127.0.0.1:12313/test/ 。

4、热更新nginx配置

先到达nginx可执行文件所在目录(前文启动的时候可以看到所在目录),执行命令:cd /usr/sbin/

注:如果是按照前文的方式安装,则在任意位置都能执行nginx。可以不用到达nginx可执行文件所在的目录。

执行nginx校验配置文件命令:nginx -t

校验通过

如果校验没通过,就要回过头改改自己写的配置了。

热更新nginx配置,执行命令:nginx -s reload

注意,如果配置文件格式不对,nginx -s reload 会失败,此时 nginx使用的还是旧的配置信息。

实际上,也可以先停止nginx,然后再启动,以这种“重启”的方式来达到更新nginx配置的目的。

5、停止nginx

(1)service/systemctl

如果启动时,执行命令: service nginx start(或:systemctl start nginx,则建议执行命令:service nginx stop(或:systemctl stop nginx来停止nginx。

(2)nginx自身

如果启动时,执行命令: nginx,则建议用下方的方式来停止nginx。

执行命令:nginx -s quit

执行命令:nginx -s stop

两种方式都是停止nginx服务。

quit是比较优雅地退出,会让工作线程把所有当前的请求处理完再停止。

stop是快速退出,不管工作线程是否正在处理请求。

注意:官网有提示说,执行停止nginx的命令的用户要和启动nginx时一致。(不太确定不一致会怎样)

额外说明:

执行命令:service nginx start(或:systemctl start nginx启动,但是用nginx自身命令停止nginx,实测会导致nginx虽然明面上关闭退出了,但是进程依然在。(如果反过来,则执行无效)

执行命令: netstat -ntulp 可以看到:

执行命令: service nginx status 会看到:

此时,若要再启动nginx,就要先杀死这些残存的进程。

查看监听端口的程序,执行命令:lsof -i:80 (其中80是前文发现nginx残存进程还在监听的端口)

依据结果执行命令:kill 522085 (522085是残存的进程ID)

把nginx残存的进程全部干掉,就行了。

四、Nginx 更新

如果已经按照以上流程完成安装旧版本的 Nginx,现在准备更新Nginx,则很简单。

1、更新 APT 源里的 Nginx的信息

apt update

如果出现类似报错:

An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://nginx.org/packages/ubuntu jammy InRelease: The following signatures were invalid: EXPKEYSIG ABF5BD827BD9BF62 nginx signing key <signing-key@nginx.com>

Failed to fetch http://nginx.org/packages/ubuntu/dists/jammy/InRelease The following signatures were invalid: EXPKEYSIG ABF5BD827BD9BF62 nginx signing key <signing-key@nginx.com>

则需要更新 nginx 签名密钥:

curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

更新后,可以通过以下命令,查看 APT 可以安装的 Nginx的版本信息。

apt-cache show nginx

2、执行更新Nginx命令

不指定版本的话,会以最新版本进行更新:

apt install nginx

此时,可以通过以下命令查看当前 Nginx 版本

nginx -v

五、相关词汇

1、C10K问题

2003年由 Dan Kegel 在个人网站上提出的——单机同时处理10k个连接问题。

文章链接:The C10K Problem

我的译文:The C10K Problem(译文)

具体刨析可以看原文,也可以去搜索一下相关分析,有很多文章,这里不赘述。

另外,虽然现在早已解决了C10K问题,但是我们也即将迎来C10M问题(即现在是10M)。如果有兴趣,可以另行搜索相关研究材料。

2、LNMP/LEMP/LAMP

LNMP 的全称是 Linux + nginx + MySQL + PHP (国外喜欢简称为LEMP,搜英文资料需要搜LEMP)

LAMP 的全称是 Linux + Apache + MySQL + PHP

3、反向代理(reverse proxy)

nginx就是一个反向代理服务。

简述:代理服务器“冒充”真正的目标服务器,给服务使用者(如浏览器)提供服务。对服务使用者(如浏览器)而言,并不关心谁才是真的目标服务器,反正它获得的服务是真的就行。(服务使用者不知道服务被代理了)

正向代理(proxy)简述:服务使用者主动配置代理服务器的地址,以代理服务器作为“中间商”去访问真正的目标服务器,以此获取服务。(服务使用者知道服务被代理了)

以浏览器为例,“是否知道服务被代理”,对应的就是有没有去给目标网址配置代理服务器地址。

4、事件驱动(Event-Driven)

即nginx基于的模型。

比喻:B一直在等着某事件的发生(事件处理器进行事件监听)。A做了某个行为,于是A大声喊“我产生了某事件”(事件源主动产生事件)。B听到这句话(事件处理器监听到事件发生),于是B开始依据事件信息做特定的事情(事件处理器执行事件处理)

5、异步非阻塞I/O模型

即nginx基于的模型。

Linux:epoll

FreeBSD:kquene

Windows:IOCP

Solaris:/dev/poll

上面各个平台接口的统一封装库:libevent

6、MIME

全程:Multipurpose Internet Mail Extensions(多用途互联网邮件扩展类型)

六、进阶用法示例

七、推荐阅读(参考资料)

  1. Nginx教程

  2. Tengine官网

  3. OpenResty官网

  4. The Architecture of Open Source Applications (Volume 2)

  5. 高性能网络编程(二):上一个10年,著名的C10K并发连接问题

  6. epoll(7) — Linux manual page

  7. libevent官网

  8. 手把手指导:在 Linux 上使用 GPG 加解密文件

  9. GPG官网命令文档

  10. 为初学者介绍的 Linux tee 命令(6 个例子)

  11. 深入理解 http 反向代理(nginx)


Comment