6
头图

这是一系列免费的知识,有图文版视频版,你现在看到的是图文版。

NGINX 系列课分为三篇,基础篇、进阶篇和企业实践篇,你现在正在阅读的是基础篇

视频版发布在我自己的社区,喜欢看视频的朋友可前往社区,微信扫码登录或微信授权登录后即可播放

写在前面

基础篇学习目的:了解 NGINX,并能够自己动手操作,能独立完成负载均衡配置,并绑定域名,实现通过域名访问后端服务。

NGINX系列课课学习目的:了解 NGINX、能够自己独立完成负载均衡配置、能够自己搭建高可用的企业级生产环境、对 NGINX 进行监控。

听过视频课的朋友已经能够独立完成负载均衡配置了,还提交了作业

image.png

我们这半年,将会输出非常多公开课,有图文版、有视频版。重要的是,这些都是免费的!!! 来了就能听。课程清单如下

image.png

其中绿色标注的是已经发布的内容,红色的是正在准备素材的内容。

NGINX 基础篇图文版

好的,正题来了,开始吧。

如果平时接触后端或者服务器比较少的朋友可能会问,NGINX 是什么

关于它是什么,我们可以引用 NGINX 官网百度百科中的介绍,NGINX 是一款高性能的 HTTP 服务器,同时也是一款反向代理服务器(NGINX 官网原文称为 reverse proxy server)。除了支持 HTTP 协议外,还支持邮件协议、TCP/UDP 等。

它能够做什么

在我看来,它其实是一款网关。作用 1 请求转发,作用 2 限流,作用 3 鉴权,作用 4 负载均衡。上面提到的反向代理 reverse proxy server,可以归类到请求转发。

正向代理,反向代理???

太多道理我们就不讲了,可以阅读其他平台上关于这个问题的解读 https://zhuanlan.zhihu.com/p/...

这里我们简单总结一下,正向代理代理的对象是客户端,反向代理代理的对象是服务端

做爬虫的朋友们,平时你们用的 IP 代理就是正向代理,爬虫程序通过代理,将请求转发给后端。而我们提到的 NGINX 反向代理则是将客户端的请求转发到后端。从上面讲到的文章里借几张图

image.png

image.png

用 NGINX 的公司多吗?

大部分公司都有用到 NGINX,大至 Google Meta(Facebook) Amazon Alibaba Tencent HUAWEI,小至全世界 70%+ (我猜的,实际比这更多)的互联网企业,社区使用的也是 NGINX

安装 NGINX

安装基于 Ubuntu20.04,云服务器。基础篇先通过快速安装,让我们可以操作起来,学一些基础,后续进阶篇会有编译安装。

打开 Terminal,执行 sudo apt install nginx -y,等待命令执行即完成安装。安装完成后它会自行启动,大家访问自己服务器的地址即可,例如我的服务器 IP 是 101.42.137.185,那我访问的是 http://101.42.137.185

image.png

如果页面显示的是 Welcome to nginx 字样,说明服务正常。如果没有,请检查安装时 Terminal 输出的错误信息,或者检查自己的防火墙、安全组策略等(如果不懂,或者怎么操作也不对,可以通过社区之前发布的 Linux 云服务器公开课学习)

NGINX 基本工作原理和模块关系简述

NGINX 有一个主进程和多个工作进程。主进程用于维护自身运转,例如读取配置、解析配置、维护工作进程、重新载入配置等等;工作进程才是具体响应请求的进程。

工作进程数可在配置文件中调整。

NGINX 由模块组成,这些模块受配置文件中的配置操控,也就是说配置文件决定了 NGINX 的工作方式。

这里还是引用其他文章,就不自己一一写明了。NGINX 原理和架构可以参考 https://zhuanlan.zhihu.com/p/...,实际上在初期我们需要关注的只有一个地方,也就是模块那部分,随便看看做个大体了解即可,不必深入。

NGINX 的信号

信号,这里指的是控制信号。信号是控制 NGINX 工作状态的模块,信号语法格式为

nginx -s signal

常用的信号有

stop 快速关停
quit 正常关停
reload 重新载入配置
reopen 重新打开日志文件

NGINX 的正确关停,是 nginx -s quit 它可以让 NGINX 处理完已经开始的工作后再退出。

NGINX 配置说明

基于之前的社区公开课,我们可以在正式讲 NGINX 配置前先看看它的应用程序管理配置。通过 status 命令找到 NGINX 的 Server 配置文件

> systemctl status nginx

查看 NGINX 的 Server 配置

[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

看到 ExecStart 选项,可以确定 NGINX 安装在 /usr/sbin/nginx,这个配置文件与我们之前的公开课 Linux 云服务器公开课讲到的知识遥相呼应,这里提一下。

查找默认的主配置文件

配置文件部分正式开始

NGINX 有主配置文件辅助配置文件,主配置文件默认名称为 nginx.conf,默认存放在 /etc/nginx/nginx.conf。辅助配置文件的路径受主配置文件控制,具体路径通过主配置文件设置,辅助配置的文件名称和路径都可更改,文件名通常以 conf 结尾。

安装完成后如果你不知道主配置文件在哪,可以通过默认路径查找,或者通过 find 命令搜索。

> sudo find / -name nginx.conf
/etc/nginx/nginx.conf

主配置文件基本结构和作用。使用 cat /etc/nginx/nginx.conf 可列出文件内容。如果你不懂,那么可以通过社区之前发布的的公开课 Linux 云服务器公开课学习具体的 Linux 文件查看指令。

user www-data;  # 用户
worker_processes auto; 工作进程数
pid /run/nginx.pid; # 进程文件
include /etc/nginx/modules-enabled/*.conf; # 插件模块配置

events {
        worker_connections 768;  # 允许同时连接的连接数
        # multi_accept on;
}

http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        include /etc/nginx/conf.d/*.conf;  # 辅助配置文件路径
        include /etc/nginx/sites-enabled/*;
}


# 示例
#mail {
  ...
#}

这里列出的配置文件我做了适当的调整,删除了被注释的内容,保留了有效内容。重要项的含义都用中文以注释的形式标记在上面了。

看到配置,你肯定有点懵,这都是些啥啊。接下来我们来学习 NGINX 配置文件的基础语法。

NGINX 配置文件基础语法

NGINX 配置文件中的配置项成为指令,指令分为简单指令块指令。简单的指令由指令名称参数组成,以空格进行分隔并以英文分号结尾,例如

worker_processes auto;

其中 worker_processes 是指令,这个指令的作用是设置工作进程数。auto 代表进程数的数量,可以是数字也可以是 auto(根据 CPU 数量按固定数学公式计算,一般是 CPU+1)。

块指令语法格式与简单指令相似,单以花括号包裹更多的简单指令,例如

http {
  server {
    ...
  }
}

上下文/语境

上下文有些地方也称语境,如果块指令内包含其他指令,则这个块指令称为上下文。常见的上下文例如

events
http
server
location

有一个隐藏的上下文指令,main。它不需要显示声明,所有指令的最外层就是 main 的范围。main 作为其他上下文的参考,例如 events 和 http 必须在 main 范围中;server 必须在 http 中;location 必须在 server 中;以上限定是固定的,不可以随意放置,否则无法运行 NGINX 程序,但能够在日志里看到错误提示信息。

讲了这么多,你一定乏了,拿我们来动手吧!

使用 NGINX 为后端程序配置代理

一个简单的 WEB 服务,例如下面这个 flask 应用

from flask import Flask
from flask_restful import Resource, Api
​
app = Flask(__name__)
api = Api(app)
​
​
class HelloWorld(Resource):
    def get(self):
        app.logger.info("receive a request, and response '穿甲兵技术社区'")
        return {'message': '穿甲兵技术社区', "address": "https://chuanjiabing.com"}
​
​
api.add_resource(HelloWorld, '/')
​
if __name__ == '__main__':
    app.run(debug=True, host="127.0.0.1", port=6789)

将内容写入到服务器上的某个文件,例如 /home/ubuntu/ke.py

启动前记得安装相关的 Python 库 pip3 install flask-restful

在 Ubuntu 20.04 上默认带有新版 Python,环境什么的不用担心。运行这个 Web 后端服务 python3 /home/ubuntu/ke.py

完成后端的启动后,我们来配置 NGINX

通过前面查看主配置文件可知,辅助配置文件的目录为 /etc/nginx/conf.d,那么现在我们在辅助配置文件目录新增配置文件

> sudo vim /etc/nginx/conf.d/ke.conf

server {
    listen 8000;
    server_name localhost;

    location / {
        proxy_pass http://localhost:6789;
    }
}

检查配置文件是否正确

> sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重新载入配置

> sudo nginx -s reload

浏览器访问 http://ip:port 例如我的服务器 http://101.42.137.185:8000/

就可以看到后端的输出了

NGINX 日志文件

默认分为正常日志和内部错误日志,日志路径可在主配置文件中设置

/var/log/nginx/access.log
/var/log/nginx/error.log

查看正常日志

> cat /var/log/nginx/access.log
117.183.211.177 - - [19/Nov/2021:20:18:46 +0800] "GET / HTTP/1.1" 200 107 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36"
117.183.211.177 - - [19/Nov/2021:20:18:48 +0800] "GET /favicon.ico HTTP/1.1" 404 209 "http://101.42.137.185:8000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36"

官方文档-日志格式 http://nginx.org/en/docs/http...

默认的日志格式

log_format compression '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $bytes_sent '
                       '"$http_referer" "$http_user_agent" "$gzip_ratio"';

可在主配置文件中自行配置,具体配置项参考官方文档。

使用 NGINX 为前端程序配置代理

一个简单的 HTML 文档

> vim /home/ubuntu/index.html
<html><meta charset="utf-8"/><body><title>穿甲兵技术社区</title><div><p>穿甲兵技术社区<p><a>https://chuanjiabing.com</a></div><body></html>

无论是大型前端项目还是中小型前端项目,一般来讲都需要编译为 HTML 文档,然后使用类似 NGINX 这样的应用提供可访问的服务。

注意:一些 Vue/React 的服务有可能会做服务端渲染部署,但大部分还是编译为 HTML。这里的简单示例和那些前端工程项目在配置上并没有什么区别。作为示例,不用纠结,学习 NGINX 才是要紧的。

> sudo vim /etc/nginx/conf.d/page.conf

server {
    listen 1235;
    server_name localhost;
    charset utf-8;
    
    location / {
        root /home/ubuntu/;
        index index.html index.htm;
    }
}

基于 NGINX 实现负载均衡

想象一下场景,例如现在你服务器上的后端服务主要是用于格式化时间,有很多爬虫程序需要调用它,而且还需要确保服务稳定可用。

场景延伸:假设你逆向了一个 JS 算法,现在所有爬虫都需要在发出请求前调用这个算法生成 sign 值,带着值去请求。如果你把 JS 代码放在 Python/Golang 这类代码里做本地调用执行,那么你改动算法时需要改动/重新部署所有爬虫程序,但做成 WEB 服务,只需要改动/重启这个 WEB 服务就可以了。

现在 1 个后端服务的情况下有 2 个明显缺点:

1、服务性能不够,请求太多会导致程序卡顿,响应速度慢,影响整体效率;

2、服务整体不稳定,一旦进程退出或者服务器死机,那服务将不可访问;

使用负载均衡的好处

1、启动多个后端服务,配置负载均衡,让请求按需(例如轮流)转发到它门那里进行处理,那么就能够承担更多的工作需求;

2、一个 NGINX 负载多个后端服务,当一个服务或者几个服务出现进程退出的情况,还有其他服务在工作;

NGINX 只需要引入 proxy_pass 指令和对应的 upstream 上下文即可实现负载均衡。一个简单的负载均衡配置例如

⚠️ 实验前,请先启动多个后端程序。可以将刚才的 Flask 代码复制到另一个文件(例如 /home/ubuntu/main.py,但记得需要改动里面的端口号,建议改为跟教程一样的 6799),如果你想在网页上看到负载的效果,可以在响应内容处用 6789/6799 来区分具体是那个后端程序。

# /etc/nginx/conf.d/ke.conf 内容改为
upstream backend{
    server localhost:6789;
    server localhost:6799;
}

server {
    listen 8000;
    server_name localhost;

    location / {
        proxy_pass http://backend;
    }
}

保存后重新载入配置即可

> sudo nginx -s reload

多次访问 http://101.42.137.185:8000/,可以看到页面上显示的内容是 6789 和 6799 这两个后端服务交替返回信息,这说明负载均衡配置成功

image.png

image.png

域名解析与配置实践

打开云服务商控制台(后续以腾讯云为例,因为教程录制时使用的是腾讯云轻量级服务器),其他云服务商界面有差异,请大家见机行事。

在搜索框处搜索域名解析(腾讯的的是 DNSPOD)

image.png

进入找到要解析的域名(这里的前提是你自己已经买了域名,做好备案。如果没有,那看我操作也可以),点击解析

image.png

点击添加记录

在主机记录处输入子域名名称(例如 ke)、在记录值处输入服务器 IP 地址后选择保存即可,其他选项默认。

image.png

完成云服务器控制台的设置后,还不可以通过域名访问到我们服务器上的应用

前往服务器改动 NGINX 辅助配置文件,更改端口、绑定域名

> sudo vim/etc/nginx/conf.d/ke.conf
# 改动 server 上下文中的 listen 和 server_name
listen 80;
server_name ke.chuanjiabing.com;

记得重载配置

> sudo nginx -s reload

然后就可以通过域名 http://ke.chuanjiabing.com/ 访问服务了

image.png

课后作业:在社区课程帖子下晒出后端程序的 NGINX 负载均衡配置截图,3 张。一张是配置截图;另外两张是浏览器访问时负载配置生效的截图。

后续进阶篇和企业实践篇的课程大纲如下,后续课程的学习目的:能够在工作中很好的应用 NGINX,完成企业级生产环境部署和监控告警

NGINX 进阶篇

NGINX 负载均衡策略理论

编译安装 NGINX

基于 NGINX 实现权限验证

基于 NGINX 实现访问限流

基于 NGINX 的简单反爬虫

基于 NGINX 实现不停机更新

NGINX 企业级实践篇

NGINX 的 HTTPS 配置实践

NGINX 插件安装

NGINX 数据监控实战

NGINX 生产环境高可用部署实践


今日长剑在握
840 声望869 粉丝