Nginx 配置文件在线生成: https://nginxconfig.io/
第一次打开 nginx.conf,看到 main、events、http、server、location 一层套一层的大括号,多数人的反应是先去搜一段能用的配置贴进去。能跑起来,但下次要改哪一行、为什么某个指令写在这层就报错、reload 到底做了什么,全都是黑箱。
这篇是我把 Nginx 从头装一遍、再把配置文件结构拆开看的记录。重点不在于给你多少段能直接抄的配置,而是把「为什么是这个结构」讲明白,包括编译参数怎么选、master 和 worker 各自在干什么、上下文继承的规则是什么、那一堆 $ 开头的变量分别从哪来。看懂这些,后面遇到任何一段陌生配置,你都能读懂它在做什么。
至于反向代理、负载均衡、HTTPS、跨域这些具体场景怎么配,本篇会给出配置和基本说明,展开的实战细节放在了 工作中常用的 Nginx 配置总结回顾 那篇里,两篇配合着看。
在本篇文章中,我们将从浅入深,和大家一起学习以下知识:
- 编译安装 Nginx 的完整流程,以及
./configure那些参数到底在决定什么 - 开机自启动的两种做法,systemd 和 rc.local 各自适用什么场景
- 启动、重载、平滑退出这几条运维命令的区别
- master 和 worker 的分工,以及
reload为什么能不断连接 nginx.conf的上下文层级,哪些指令只能写在哪一层- 常用正则、内置变量和单位符号速查
- 反向代理、负载均衡、性能优化和常见场景配置的入门版本
先说一句,下面的安装步骤是 2018 年在 CentOS 上做的记录,命令和路径都保留原样。今天如果只是想快点用起来,直接 yum install nginx 或者 apt install nginx 就够了,发行版的包已经把常用模块编译进去了。但编译安装这一遍还是建议走一次,因为它逼着你去看每个 --with- 参数是什么意思,这个理解后面查问题时反复用得上。
Nginx 是一款面向性能设计的 HTTP 服务器,能反向代理 HTTP,HTTPS 和邮件相关(SMTP,POP3,IMAP)的协议链接。并且提供了负载均衡以及 HTTP 缓存。它的设计充分使用异步事件模型,削减上下文调度的开销,提高服务器并发能力。采用了模块化设计,提供了丰富的第三方模块。
所以关于 Nginx 有这些标签:「异步」「事件」「模块化」「高性能」「高并发」「反向代理」「负载均衡」。
这几个词里最核心的是「事件驱动」。传统的 Apache prefork 模式是一个连接一个进程,一万个并发连接就要一万个进程,内存直接爆掉。Nginx 用的是 epoll 这类 I/O 多路复用,一个 worker 进程在一个循环里轮询所有连接,谁有数据就处理谁,几万个连接也只占几个进程的内存。这个差别就是为什么同样一台机器,Nginx 扛并发的能力能高出一个数量级。
代价是编程模型受限,worker 里不能有阻塞操作,一个慢的磁盘读会卡住整个 worker 上的所有连接。这也是为什么后面 sendfile、aio、open_file_cache 这些围绕 I/O 的优化项那么重要。
# 一、安装
# 1.1 安装依赖
prce(重定向支持)和openssl(https支持,如果不需要https可以不安装)
yum install -y pcre-devel
yum -y install gcc make gcc-c++ wget
yum -y install openssl openssl-devel
CentOS 6.5 我安装的时候是选择的「基本服务器」,默认这两个包都没安装全,所以这两个都运行安装即可。
这三行 yum 装的东西各有各的用处,值得说清楚,因为漏装哪个,./configure 报的错都不一样。
pcre-devel 提供正则引擎,Nginx 的 location ~ 正则匹配和整个 rewrite 模块都靠它。不装的话 ./configure 会直接停下来说找不到 PCRE。openssl-devel 是 HTTPS 的前提,不装就没法编译 http_ssl_module,那你这台 Nginx 永远只能跑 80 端口。gcc、make、gcc-c++ 是编译工具链,最小化安装的系统上通常都没有。
注意包名带 -devel 后缀的是开发库,包含头文件,编译时必需;只装不带后缀的运行库是不够的。这个细节在 Debian 系上对应的是 -dev 后缀,包名叫 libpcre3-dev 和 libssl-dev。
# 1.2 下载
wget http://nginx.org/download/nginx-1.13.3.tar.gz
wget http://nginx.org/download/nginx-1.13.7.tar.gz
# 如果没有安装wget
# 下载已编译版本
$ yum install wget
# 解压压缩包
tar zxf nginx-1.13.3.tar.gz
版本选择上有个规矩要知道。Nginx 的版本号第二位是偶数表示稳定版(stable),奇数是主线版(mainline)。这里下的 1.13 就是主线版,新功能先进这里;生产环境按惯例用 stable 分支。不过 Nginx 官方自己是推荐用 mainline 的,理由是它其实很稳,而且能更早拿到 bug 修复。我的做法是自己的服务器用 stable,图省心。
上面这段同时下了 1.13.3 和 1.13.7 两个版本,实际用的时候挑一个就行。
# 1.3 编译安装
然后进入目录编译安装,configure参数说明
cd nginx-1.11.5
./configure
....
Configuration summary
+ using system PCRE library
+ OpenSSL library is not used
+ using system zlib library
nginx path prefix: "/usr/local/nginx"
nginx binary file: "/usr/local/nginx/sbin/nginx"
nginx modules path: "/usr/local/nginx/modules"
nginx configuration prefix: "/usr/local/nginx/conf"
nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
nginx pid file: "/usr/local/nginx/logs/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
安装报错误的话比如:
C compiler cc is not found,这个就是缺少编译环境,安装一下就可以了yum -y install gcc make gcc-c++ openssl-devel
如果没有error信息,就可以执行下边的安装了:
make
make install
这里有个坑要注意,上面的 ./configure 输出里写着 OpenSSL library is not used,意思是这次编译没带 SSL 模块。也就是说这样装出来的 Nginx 配 listen 443 ssl 会直接报错说不认识这个参数。想要 HTTPS,./configure 后面必须显式加上 --with-http_ssl_module。
这就是编译安装最容易翻车的地方:./configure 不带参数跑一遍确实能装上,但装出来的是个功能最小集。我第一次装完发现 HTTPS 配不了,还以为是证书的问题,排查了半天才反应过来是模块没编进去。
那份 Configuration summary 输出一定要逐行看完,它把安装路径、配置文件位置、日志位置全列出来了,后面找文件全靠它。特别是 nginx configuration file 那一行,这就是你要改的 nginx.conf 的绝对路径。
还有一点,make install 之后源码目录别删。以后要加模块得回到这个目录重新 ./configure 再 make,删了就得重新下载重新配一遍参数。
# 1.4 nginx测试
- 运行下面命令会出现两个结果,一般情况
nginx会安装在/usr/local/nginx目录中
cd /usr/local/nginx/sbin/
./nginx -t
# nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
# nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
nginx -t 这条命令请养成肌肉记忆,每次改完配置都敲一遍再 reload。它只做语法检查不动服务,配置写错了会告诉你具体第几行有问题。
跳过这一步的后果是这样的:直接 nginx -s reload,如果新配置有语法错误,Nginx 会拒绝加载并保持旧配置继续跑。服务没挂,但你以为改生效了其实没有,改动跟着下一次重启才会暴露出来,那时候现场早就变了。这类问题排查起来特别费时间。
-t 还会尝试打开配置里引用到的所有文件,证书路径写错、include 的文件不存在,它一并能查出来。
# 1.5 设置全局nginx命令
vi ~/.bash_profile
将下面内容添加到 ~/.bash_profile 文件中
PATH=$PATH:$HOME/bin:/usr/local/nginx/sbin/
export PATH
运行命令 source ~/.bash_profile 让配置立即生效。你就可以全局运行 nginx 命令了。
这一步纯粹是为了少敲路径,但它顺带解决了一个实际问题:编译安装的 Nginx 不在系统 PATH 里,而很多脚本和文档默认你能直接敲 nginx。不配这个,写自动化脚本时到处都要写全路径。
如果这台机器有多个用户都要操作 Nginx,写到 /etc/profile.d/ 下建个 .sh 文件比改单个用户的 .bash_profile 更合适。
# 二、开机自启动
服务器重启之后 Nginx 不会自己起来,这件事一定要在上线前解决掉,不然某次机房断电恢复后你的站点就一直是 502。下面两种做法,systemd 是现在的标准答案,rc.local 是老系统的兜底方案。
开机自启动方法一