这是一系列免费的知识,有图文版和视频版,你现在看到的是图文版。
NGINX 系列课分为三篇,基础篇、进阶篇和企业实践篇,你现在正在阅读的是基础篇。
视频版发布在我自己的社区,喜欢看视频的朋友可前往社区,微信扫码登录或微信授权登录后即可播放。
写在前面
基础篇学习目的:了解 NGINX,并能够自己动手操作,能独立完成负载均衡配置,并绑定域名,实现通过域名访问后端服务。
NGINX系列课课学习目的:了解 NGINX、能够自己独立完成负载均衡配置、能够自己搭建高可用的企业级生产环境、对 NGINX 进行监控。
听过视频课的朋友已经能够独立完成负载均衡配置了,还提交了作业
我们这半年,将会输出非常多公开课,有图文版、有视频版。重要的是,这些都是免费的!!! 来了就能听。课程清单如下
其中绿色标注的是已经发布的内容,红色的是正在准备素材的内容。
NGINX 基础篇图文版
好的,正题来了,开始吧。
如果平时接触后端或者服务器比较少的朋友可能会问,NGINX 是什么?
关于它是什么,我们可以引用 NGINX 官网和百度百科中的介绍,NGINX 是一款高性能的 HTTP 服务器,同时也是一款反向代理服务器(NGINX 官网原文称为 reverse proxy server
)。除了支持 HTTP 协议外,还支持邮件协议、TCP/UDP 等。
它能够做什么?
在我看来,它其实是一款网关。作用 1 请求转发,作用 2 限流,作用 3 鉴权,作用 4 负载均衡。上面提到的反向代理 reverse proxy server
,可以归类到请求转发。
正向代理,反向代理???
太多道理我们就不讲了,可以阅读其他平台上关于这个问题的解读 zhuanlan.zhihu.com/p/25707362
这里我们简单总结一下,正向代理代理的对象是客户端,反向代理代理的对象是服务端。
做爬虫的朋友们,平时你们用的 IP 代理就是正向代理,爬虫程序通过代理,将请求转发给后端。而我们提到的 NGINX 反向代理则是将客户端的请求转发到后端。从上面讲到的文章里借几张图
用 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
如果页面显示的是 Welcome to nginx
字样,说明服务正常。如果没有,请检查安装时 Terminal 输出的错误信息,或者检查自己的防火墙、安全组策略等(如果不懂,或者怎么操作也不对,可以通过社区之前发布的 Linux 云服务器公开课学习)
NGINX 基本工作原理和模块关系简述
NGINX 有一个主进程和多个工作进程。主进程用于维护自身运转,例如读取配置、解析配置、维护工作进程、重新载入配置等等;工作进程才是具体响应请求的进程。
工作进程数可在配置文件中调整。
NGINX 由模块组成,这些模块受配置文件中的配置操控,也就是说配置文件决定了 NGINX 的工作方式。
这里还是引用其他文章,就不自己一一写明了。NGINX 原理和架构可以参考 zhuanlan.zhihu.com/p/133257100,实际上在初期我们需要关注的只有一个地方,也就是模块那部分,随便看看做个大体了解即可,不必深入。
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"
复制代码
官方文档-日志格式 nginx.org/en/docs/htt…
默认的日志格式
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 这两个后端服务交替返回信息,这说明负载均衡配置成功。
域名解析与配置实践
打开云服务商控制台(后续以腾讯云为例,因为教程录制时使用的是腾讯云轻量级服务器),其他云服务商界面有差异,请大家见机行事。
在搜索框处搜索域名解析(腾讯的的是 DNSPOD)
进入找到要解析的域名(这里的前提是你自己已经买了域名,做好备案。如果没有,那看我操作也可以),点击解析
点击添加记录
在主机记录处输入子域名名称(例如 ke
)、在记录值处输入服务器 IP 地址后选择保存即可,其他选项默认。
完成云服务器控制台的设置后,还不可以通过域名访问到我们服务器上的应用
前往服务器改动 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/
访问服务了
课后作业:在社区课程帖子下晒出后端程序的 NGINX 负载均衡配置截图,3 张。一张是配置截图;另外两张是浏览器访问时负载配置生效的截图。
后续进阶篇和企业实践篇的课程大纲如下,后续课程的学习目的:能够在工作中很好的应用 NGINX,完成企业级生产环境部署和监控告警
NGINX 进阶篇
NGINX 负载均衡策略理论
编译安装 NGINX
基于 NGINX 实现权限验证
基于 NGINX 实现访问限流
基于 NGINX 的简单反爬虫
基于 NGINX 实现不停机更新
NGINX 企业级实践篇
NGINX 的 HTTPS 配置实践
NGINX 插件安装
NGINX 数据监控实战
NGINX 生产环境高可用部署实践