0%

学习nginx看这一篇文章就够了

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 25.54% busiest sites in April 2020. Here are some of the success stories: Dropbox, Netflix, Wordpress.com, FastMail.FM.

nginx 是一个可用于 web server(static contents), web reverse proxy (http),cache

nginx 的优点:

  • 高并发、高性能
  • 可扩展性好
  • 高可靠性
  • 热部署
  • BSD 许可证

nginx 的基本组成

  • nginx 的二进制可执行文件
  • nginx conf 配置文件
  • access.log 访问日志
  • error.log 错误日志

nginx 相关版本

  • nginx opensource
  • nginx Plus 整合第三方模块以及运营监控 技术支持
  • alibaba tengine 很多特性领先于 nginx 的官方版本,由于修改了主干代码,无法跟随 nginx 迭代同步升级
  • openresty 将 nginx 和 LuaJIT 整合,并集成很多第三方组件(也有开源版和商业版)

相关概念

正向代理

正向代理服务器是一个位于客户端和目标服务器之间的代理服务器(中间服务器)。正向代理隐藏了客户端,通过代理服务器访问目标服务器。
常见的正向代理,就是翻墙或者是各种游戏的加速器。
客户端(浏览器) ——————> 代理服务器 ——————> 目标服务器

反向代理

反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就是目标服务器。

负载均衡

一台服务器的 QPS、并发是有限的,那么当一台服务器满足不了总的 QPS、并发的时候,我们会怎么做呢?当然是加服务器了。负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,从而完成工作。对于上述的例子而言,多个服务器就是多个操作单元。

动静分离

动态资源(jsp、ftl、thymeleaf)与静态资源(js、css、img)分开部署。
如果我们静态资源与动态资源存放在同一台服务器上面,当静态资源不断增多的时候,我们的服务器访问是扛不住,因为静态资源消耗过多的带宽,导致静态资源无法访问或者访问非常的慢。

nginx 的 安装

  • 对两种安装方式进行了简单,更推荐于通过源代码安装,因为这样才可以真正使用到 nginx 的强大生态圈。

通过源代码编译安装 (主要安装方式)

  1. 下载 nginx 压缩包
1
2
# 如果wget不存在 执行 sudo apt install wget
wget http://nginx.org/download/nginx-1.18.0.tar.gz
  1. 解压文件到对应的目录
1
sudo tar -xf nginx-1.18.0.tar.gz nginx-1.18.0

简单介绍下 nginx-1.18.0 源码包

1
2
3
4
5
6
7
8
9
10
11
drwxr-xr-x 6 xiongxiaoyu xiongxiaoyu 4.0K Jun  2 02:43 auto       # 辅助configure脚本,用以判断系统特性、模块等给与使用
-rw-r--r-- 1 xiongxiaoyu xiongxiaoyu 296K Apr 21 14:09 CHANGES # 版本迭代的改变
-rw-r--r-- 1 xiongxiaoyu xiongxiaoyu 452K Apr 21 14:09 CHANGES.ru # 俄罗斯语言
drwxr-xr-x 2 xiongxiaoyu xiongxiaoyu 4.0K Jun 2 02:43 conf # conf的示例
-rwxr-xr-x 1 xiongxiaoyu xiongxiaoyu 2.5K Apr 21 14:09 configure # 生成Makefile
drwxr-xr-x 4 xiongxiaoyu xiongxiaoyu 4.0K Jun 2 02:43 contrib # 常用的工具
drwxr-xr-x 2 xiongxiaoyu xiongxiaoyu 4.0K Jun 2 02:43 html # 默认的网页
-rw-r--r-- 1 xiongxiaoyu xiongxiaoyu 1.4K Apr 21 14:09 LICENSE # 开源协议
drwxr-xr-x 2 xiongxiaoyu xiongxiaoyu 4.0K Jun 2 02:43 man # Liunx的帮助
-rw-r--r-- 1 xiongxiaoyu xiongxiaoyu 49 Apr 21 14:09 README
drwxr-xr-x 9 xiongxiaoyu xiongxiaoyu 4.0K Jun 2 02:43 src # nginx 的源代码
  1. 编译安装
1
./configure

如果此时提示 ERROR C complier cc is not found,执行命令: sudo apt install -y build-essential
解决依赖包 openssl 安装,执行命令:sudo apt-get install openssl libssl-dev
解决依赖包 pcre 安装,执行命令:sudo apt-get install libpcre3 libpcre3-dev
解决依赖包 zlib 安装,执行命令:sudo apt-get install zlib1g-dev

执行完./configure 会在目录下生成一个objs的文件夹。

1
2
3
4
5
6
-rw-rw-r-- 1 xiongxiaoyu xiongxiaoyu 17529 Jun  2 07:42 autoconf.err
-rw-rw-r-- 1 xiongxiaoyu xiongxiaoyu 40144 Jun 2 07:42 Makefile
-rw-rw-r-- 1 xiongxiaoyu xiongxiaoyu 7009 Jun 2 07:42 ngx_auto_config.h
-rw-rw-r-- 1 xiongxiaoyu xiongxiaoyu 657 Jun 2 07:42 ngx_auto_headers.h
-rw-rw-r-- 1 xiongxiaoyu xiongxiaoyu 5856 Jun 2 07:42 ngx_modules.c # 这个文件存储了哪些模块会在后续的编译中编译进nginx可执行文件
drwxrwxr-x 9 xiongxiaoyu xiongxiaoyu 4096 Jun 2 07:42 src/
1
sudo make && sudo make install
  1. 验证 nginx
    进入到目录 cd /usr/local/nginx/sbin
    执行./nginx -v
    打印出nginx version: nginx/1.18.0 安装完毕。

编译安装如果没有特别设定,安装目录都会在/usr/local/nginx

通过软件包安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Install the prerequisites:
sudo apt install curl gnupg2 ca-certificates lsb-release

#To set up the apt repository for stable nginx packages, run the following command:
echo "deb http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

# If you would like to use mainline nginx packages, run the following command instead:
echo "deb http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

#Next, import an official nginx signing key so apt could verify the packages authenticity:
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -

# To install nginx, run the following commands:
sudo apt update
sudo apt install nginx

验证安装 执行nginx -v 打印出nginx version: nginx/1.18.0 安装完毕。

安装目录如下:

1
2
3
4
5
6
7
8
9
10
/etc/init.d/nginx
/etc/logrotate.d/nginx
/etc/default/nginx
/etc/nginx # 配置文件所在位置
/usr/share/doc/nginx
/usr/share/nginx
/usr/sbin/nginx # nginx 本程序所在
/usr/lib/nginx # nginx 模块lib库 so存放位置
/var/log/nginx
/var/cache/nginx

nginx 的简单命令

输入nginx -h得到如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
-?,-h : this help
-v : show version and exit
-V : show version and configure options then exit
-t : test configuration and exit
-T : test configuration, dump it and exit
-q : suppress non-error messages during configuration testing
-s signal : send signal to a master process: stop, quit, reopen, reload
-p prefix : set prefix path (default: /usr/local/nginx/)
-c filename : set configuration file (default: conf/nginx.conf)
-g directives : set global directives out of configuration file

启动 nginx: nginx
停止 nginx: nginx -s stop
退出 nginx: nginx -s quit
重启 nginx: nginx -s reload
验证 nginx 配置文件: nginx -t 默认配置文件地址
验证 nginx 配置文件: nginx -t -c /xxx/xxx/xxx.conf 指明验证某个配置文件

nginx 原理

nginx 在启动时会以 daemon 形式在后台运行,采用多进程+异步非阻塞 IO 事件模型来处理各种连接请求。
nginx 是一个多进程模型分为一个 master 进程和多个 worker 进程,一般 worker 进程个数是根据服务器 CPU 核数来决定的。master 进程负责管理 Nginx 本身和其他 worker 进程。

master 进程的作用是? 读取并验证配置文件 nginx.conf;管理 worker 进程;

worker 进程的作用是? 每一个 worker 进程都维护一个线程(避免线程切换),处理连接和请求;注意 worker 进程的个数由配置文件决定,一般和 CPU 个数相关(有利于进程切换),配置几个就有几个 worker 进程。

nginx 多进程处理模型

nginx 为什么会采用多进程处理模型,而不是采用多线程处理模型呢?
那是因为nginx最核心的目的,需要保持它的高可用性和高可靠性,当使用了多线程结构,因为线程之间是共享同一个地址空间的,如果当某一个第三方模块引发了一个地址空间导致的段错误时,在地址越界错误是,会导致进程全部挂掉。

首先,master 进程一开始就会根据我们的配置,来建立需要listen的网络socket fd,然后 fork 出多个 worker 进程。
其次,根据进程的特性,新建立的worker进程,也会和master进程一样,具有相同的设置。因此,其也会去监听相同 ip 端口的套接字socket fd
然后,这个时候有多个worker进程都在监听同样设置的socket fd,意味着当有一个请求进来的时候,所有的worker都会感知到,这样就会产生所谓的“惊群现象”。为了保证只会有一个进程成功注册到listen fd的读事件,nginx 中实现了一个accept_mutex类似互斥锁,只有获取到这个锁的进程,才可以去注册读事件。其他进程全部accept失败。
最后,监听成功的worker进程,读取请求,解析处理,响应数据返回给客户端,断开连接,结束。因此,一个request请求,只需要worker进程就可以完成。
PS:其实如果你只有一个 woker,惊群不惊群无所谓的,对吧。这个时候可以选择关闭accept_mutex设置。这样反而还能获得更高的性能。

但是这样也会有一个问题,就是有可能所有的请求都被同一个worker争取了,导致其他worker进程都比较空闲.而某一个进程会处于忙碌的状态,这种状态可能还会导致无法及时响应连接而丢弃掉本有能力处理的请求.针对这种现象,nginx 采用了一个是否打开accept_mutex选项的值,ngx_accept_disabled标识控制一个worker进程是否需要去竞争获取accept_mutex选项,进而获取accept事件。

nginx 热部署

所谓热部署,就是在修改文件nginx.conf后,可以在不停机的情况下应用配置文件。
nginx 热部署原理,修改配置文件nginx.conf后,使用命令nginx -s reload。这个时候,会将暂时没有工作的worker杀掉,创建使用新配置文件的 worker。正在工作的worker等待运行完,杀掉,创建新的。

nginx 使用的事件驱动模型

我看到很多的博客都直接断言 ngnix 使用的是 epoll,其实是错误的。
nginx 提供了 selectpollkqueueepoll/dev/polleventport事件驱动模型。
官方说明:http://nginx.org/en/docs/events.html

架构图

最后附上一张架构图

图来源:http://www.aosabook.org/en/nginx.html

nginx 的 配置

我在nginx config篇里面做了专门概述。

nginx 的 日志记录

  • 定义一个 log_format 并指定名称
  • 在 http,server,location 中指定 access_log

nginx 的 常用指南

我在nginx 常用指南篇里面做了专门概述。

可视化实时监控access.log

使用 GoAccess