这几天在复习 nginx 的知识,刚好就把常用的 nginx 操作整合出来,方便查阅,这里分享给大家:
本文将会从:安装 -> 全局配置 -> 常用的各种配置 来书写,其中常用配置写的炒鸡详细,需要的童鞋可以直接滑倒响应的位置查看。
目录
安装 nginx
下载 nginx 的压缩包文件到根目录,官网下载地址:nginx.org/download/nginx-x.xx.xx.tar.gz
1 | yum update #更新系统软件 |
解压tar.gz压缩包文件,进去 nginx-1.17.2
1 | tar -xzvf nginx-1.17.2.tar.gz |
进入文件夹后进行配置检查
1 | ./configure |
通过安装前的配置检查,发现有报错。检查中发现一些依赖库没有找到,这时候需要先安装nginx的一些依赖库
1 | yum -y install pcre* #安装使nginx支持rewrite |
再次进行检查操作 ./configure 没发现报错显示,接下来进行编译并安装的操作
1 | // 检查模块支持 |
这里得特别注意下,你以后需要用到的功能模块是否存在,不然以后添加新的包会比较麻烦。
查看默认安装的模块支持
命令ls nginx-1.17.2
查看 nginx 的文件列表,可以发现里面有一个 auto 的目录。
在这个 auto 目录中有一个 options 文件,这个文件里面保存的就是 nginx 编译过程中的所有选项配置。
通过命令:cat nginx-1.17.2/auto/options | grep YES
就可以查看
编译并安装
1 | make && make install |
这里需要注意,模块的支持跟后续的nginx配置有关,比如 SSL,gzip 压缩等等,编译安装前最好检查需要配置的模块存不存在。
查看 nginx 安装后在的目录,可以看到已经安装到 /usr/local/nginx 目录了
1 | whereis nginx |
启动 nginx 服务
1 | cd /usr/local/nginx/sbin/ |
服务启动的时候报错了:nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
,通过命令查看本机网络地址和端口等一些信息,找到被占用的 80 端口 netstat -ntpl
的 tcp 连接,并杀死进程(kill 进程 pid)
1 | netstat -ntpl |
继续启动 nginx 服务,启动成功
1 | ./nginx |
在浏览器直接访问 ip 地址,页面出现 Welcome to Nginx! 则安装成功。
nginx 配置
基本结构
1 | main # 全局配置,对全局生效 |
主要配置含义
- main:nginx 的全局配置,对全局生效。
- events:配置影响 nginx 服务器或与用户的网络连接。
- http:可以嵌套多个 server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。
- server:配置虚拟主机的相关参数,一个 http 中可以有多个server。
- location:配置请求的路由,以及各种页面的处理情况。
- upstream:配置后端服务器具体地址,负载均衡配置不可或缺的部分。
nginx.conf 配置文件的语法规则
- 配置文件由指令与指令块构成
- 每条指令以 “;” 分号结尾,指令与参数间以空格符号分隔
- 指令块以 {} 大括号将多条指令组织在一起
- include 语句允许组合多个配置文件以提升可维护性
- 通过 # 符号添加注释,提高可读性
- 通过 $ 符号使用变量
- 部分指令的参数支持正则表达式,例如常用的 location 指令
内置变量
nginx 常用的内置全局变量,你可以在配置中随意使用:
TCP | UDP |
---|---|
$host | 请求信息中的 Host,如果请求中没有 Host 行,则等于设置的服务器名 |
$request_method | 客户端请求类型,如 GET、POST |
$remote_addr | 客户端的 IP 地址 |
$args | 请求中的参数 |
$content_length | 请求头中的 Content-length 字段 |
$http_user_agent | 客户端 agent 信息 |
$http_cookie | 客户端cookie信息 |
$remote_port | 客户端的端口 |
$server_protocol | 请求使用的协议,如 HTTP/1.1 |
$server_addr | 服务器地址 |
$server_name | 服务器名称 |
$server_port | 服务器的端口号 |
常用命令
这里列举几个常用的命令:
1 | nginx -s reload # 向主进程发送信号,重新加载配置文件,热重启 |
以上命令通过 nginx -h
就可以查看到,还有其它不常用这里未列出。
Linux 系统应用管理工具 systemd 关于 nginx 的常用命令:
1 | systemctl start nginx # 启动 Nginx |
配置 nginx 开机自启
利用 systemctl 命令:
如果用 yum install 命令安装的 nginx,yum 命令会自动创建 nginx.service 文件,直接用命令:
1 | systemctl enable nginx # 设置开机启动 Nginx |
就可以设置开机自启,否则需要在系统服务目录里创建 nginx.service 文件。
创建并打开 nginx.service 文件:
1 | vi /lib/systemd/system/nginx.service |
内容如下:
1 | [Unit] |
:wq
保存退出,运行 systemctl daemon-reload
使文件生效。
这样便可以通过以下命令操作 nginx 了:
1 | systemctl start nginx.service # 启动nginx服务 |
通过开机启动命令脚本实现开机自启
创建开机启动命令脚本文件:
1 | vi /etc/init.d/nginx |
在这个 nginx 文件中插入一下启动脚本代码,启动脚本代码来源网络复制,实测有效:
1 |
|
设置所有人都有对这个启动脚本 nginx 文件的执行权限:
1 | chmod a+x /etc/init.d/nginx |
把nginx加入系统服务中:
1 | chkconfig --add nginx |
把服务设置为开机启动:
1 | chkconfig nginx on |
reboot 重启系统生效,可以使用上面 systemctl 方法相同的命令:
1 | systemctl start nginx.service # 启动nginx服务 |
如果服务启动的时候出现 Restarting nginx daemon: nginxnginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: No such file or directory) nginx not running
的错误,通过nginx -c 参数指定配置文件即可解决
1 | /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf |
如果服务启动中出现 nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
的错误,可以先通过 service nginx stop
停止服务,再启动就好。
配置 nginx 全局可用
当你每次改了 nginx.conf
配置文件的内容都需要重新到 nginx 启动目录去执行命令,或者通过 -p 参数指向特定目录,会不会感觉很麻烦?
例如: 直接执行 nginx -s reload
会报错 -bash: nginx: command not found
,需要到 /usr/local/nginx/sbin
目录下面去执行,并且是执行 ./nginx -s reload
。
这里有两种方式可以解决,一种是通过脚本对 nginx 命令包装,这里介绍另外一种比较简单:通过把 nginx 配置到环境变量里,用 nginx 执行指令即可。步骤如下:
1、编辑 /etc/profile
1 | vi /etc/profile |
2、在最后一行添加配置,:wq 保存
1 | export PATH=$PATH:/usr/local/nginx/sbin |
3、使配置立即生效
1 | source /etc/profile |
这样就可以愉快的直接在全局使用 nginx 命令了。
nginx 常用功能
反向代理
我们最常说的反向代理的是通过反向代理解决跨域问题。
其实反向代理还可以用来控制缓存(代理缓存 proxy cache),进行访问控制等等,以及后面说的负载均衡其实都是通过反向代理来实现的。
1 | server { |
访问控制
1 | server { |
上面的命令表示禁止 192.168.1.1 和 192.168.1.2 两个 ip 访问,其它全部允许。从上到下的顺序,匹配到了便跳出,可以按你的需求设置。
负载均衡
通过负载均衡充利用服务器资源,nginx 目前支持自带 4 种负载均衡策略,还有 2 种常用的第三方策略。
轮询策略(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果有后端服务器挂掉,能自动剔除。但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。
1 | http { |
根据服务器权重
例如要配置:10 次请求中大概 1 次访问到 8888 端口,9 次访问到 8887 端口:
1 | http { |
客户端 ip 绑定(ip_hash)
来自同一个 ip 的请求永远只分配一台服务器,有效解决了动态网页存在的 session 共享问题。例如:比如把登录信息保存到了 session 中,那么跳转到另外一台服务器的时候就需要重新登录了。
所以很多时候我们需要一个客户只访问一个服务器,那么就需要用 ip_hash 了。
1 | http { |
最小连接数策略
将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。
1 | http { |
最快响应时间策略(依赖于第三方 NGINX Plus)
依赖于 NGINX Plus,优先分配给响应时间最短的服务器。
1 | http { |
按访问url的hash结果(第三方)
按访问 url 的 hash 结果来分配请求,使每个 url 定向到同一个后端服务器,后端服务器为缓存时比较有效。 在 upstream 中加入 hash 语句,server 语句中不能写入 weight 等其他的参数,hash_method 是使用的 hash 算法
1 |
|
采用 HAproxy 的 loadbalance uri 或者 nginx 的 upstream_hash 模块,都可以做到针对 url 进行哈希算法式的负载均衡转发。
gzip 压缩
开启 gzip 压缩可以大幅减少 http 传输过程中文件的大小,可以极大的提高网站的访问速度,基本是必不可少的优化操作:
1 | gzip on; # 开启gzip 压缩 |
解释一下:
- gzip_types:要采用 gzip 压缩的 MIME 文件类型,其中 text/html 被系统强制启用;
- gzip_static:默认 off,该模块启用后,Nginx 首先检查是否存在请求静态文件的 gz 结尾的文件,如果有则直接返回该 .gz 文件内容;
- gzip_proxied:默认 off,nginx 做为反向代理时启用,用于设置启用或禁用从代理服务器上收到相应内容 gzip 压缩;
- gzip_buffers:获取多少内存用于缓存压缩结果,16 8k 表示以 8k*16 为单位获得;
- gzip_min_length:允许压缩的页面最小字节数,页面字节数从 header 头中的 Content-Length 中进行获取。默认值是 0,不管页面多大都压缩。建议设置成大于 1k 的字节数,小于 1k 可能会越压越大;
- gzip_comp_level:gzip 压缩比,压缩级别是 1-9,1 压缩级别最低,9 最高,级别越高压缩率越大,压缩时间越长,建议 4-6;
- gzip_http_version:默认 1.1,启用 gzip 所需的 HTTP 最低版本;
- gzip_vary:用于在响应消息头中添加 Vary:Accept-Encoding,使代理服务器根据请求头中的 Accept-Encoding 识别是否启用 gzip 压缩;
- gzip_disable 指定哪些不需要 gzip 压缩的浏览器
其中第 2 点,普遍是结合前端打包的时候打包成 gzip 文件后部署到服务器上,这样服务器就可以直接使用 gzip 的文件了,并且可以把压缩比例提高,这样 nginx 就不用压缩,也就不会影响速度。一般不追求极致的情况下,前端不用做任何配置就可以使用啦~
附前端 webpack 开启 gzip 压缩配置,在 vue-cli3 的 vue.config.js 配置文件中:
1 | const CompressionWebpackPlugin = require('compression-webpack-plugin') |
HTTP服务器
nginx 本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用 nginx 来做服务器:
1 | server { |
这样如果访问 http://ip 就会默认访问到 /usr/local/app 目录下面的 index.html,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署,比如一个静态官网。
动静分离
就是把动态和静态的请求分开。方式主要有两种:
- 一种是纯粹把静态文件独立成单独的域名,放在独立的服务器上,也是目前主流推崇的方案
- 一种方法就是动态跟静态文件混合在一起发布, 通过 nginx 配置来分开
1 | # 所有静态请求都由nginx处理,存放目录为 html |
注意上面设置了 expires,当 nginx 设置了 expires 后,例如设置为:expires 10d; 那么,所在的 location 或 if 的内容,用户在 10 天内请求的时候,都只会访问浏览器中的缓存,而不会去请求 nginx 。
请求限制
对于大流量恶意的访问,会造成带宽的浪费,给服务器增加压力。可以通过 nginx 对于同一 IP 的连接数以及并发数进行限制。合理的控制还可以用来防止 DDos 和 CC 攻击。
关于请求限制主要使用 nginx 默认集成的 2 个模块:
- limit_conn_module 连接频率限制模块
- limit_req_module 请求频率限制模块
涉及到的配置主要是:
- limit_req_zone 限制请求数
- limit_conn_zone 限制并发连接数
通过 limit_req_zone 限制请求数
1 | http{ |
如果共享内存空间被耗尽,服务器将会对后续所有的请求返回 503 (Service Temporarily Unavailable) 错误。
当多个 limit_conn_zone 指令被配置时,所有的连接数限制都会生效。比如,下面配置不仅会限制单一 IP 来源的连接数,同时也会限制单一虚拟服务器的总连接数:
1 | limit_conn_zone $binary_remote_addr zone=perip:10m; |
通过 limit_conn_zone 限制并发连接数
1 | limit_req_zone $binary_remote_addr zone=creq:10 mrate=10r/s; |
限制平均每秒不超过一个请求,同时允许超过频率限制的请求数不多于5个。
如果不希望超过的请求被延迟,可以用 nodelay 参数,如:
limit_req zone=creq burst=5 nodelay;
这里只是简单讲讲,让大家有这个概念,配置的时候可以深入去找找资料。
正向代理
正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理,比如我们使用的 VPN 服务就是正向代理,直观区别(图片来源于 前端开发者必备的 Nginx 知识):
配置正向代理:
1 | resolver 8.8.8.8 # 谷歌的域名解析地址 |
正向代理的对象是客户端,服务器端看不到真正的客户端。
图片防盗链
1 | server { |
以上设置就能防止其它网站利用外链访问我们的图片,有利于节省流量
适配 PC 或移动设备
根据用户设备不同返回不同样式的站点,以前经常使用的是纯前端的自适应布局,但是复杂的网站并不适合响应式,无论是复杂性和易用性上面还是不如分开编写的好,比如我们常见的淘宝、京东。
根据用户请求的 user-agent 来判断是返回 PC 还是 H5 站点:
1 | server { |
设置二级域名
新建一个 server 即可:
1 | server { |
配置 HTTPS
这里我使用的是 certbot 免费证书,但申请一次有效期只有3个月(好像可以用 crontab 尝试配置自动续期,我暂时没试过):
先安装 certbot
1 | wget https://dl.eff.org/certbot-auto |
申请证书(注意:需要把要申请证书的域名先解析到这台服务器上,才能申请):
1 | sudo ./certbot-auto certonly --standalone --email admin@abc.com -d test.com -d www.test.com |
执行上面指令,按提示操作。
Certbot 会启动一个临时服务器来完成验证(会占用 80 端口或 443 端口,因此需要暂时关闭 Web 服务器),然后 Certbot 会把证书以文件的形式保存,包括完整的证书链文件和私钥文件。
文件保存在 /etc/letsencrypt/live/ 下面的域名目录下。
修改 nginx 配置:
1 | server{ |
配置 HTTP 转 HTTPS
1 | server { |
以上配置选择自己需要的一条即可,不用全部加。
单页面项目 history 路由配置
1 | server { |
vue-router 官网只有一句话 try_files $uri $uri/ /index.html;
,而上面做了一些重定向处理。
配置高可用集群(双机热备)
当主 nginx 服务器宕机之后,切换到备份的 nginx 服务器
首先安装 keepalived:
1 | yum install keepalived -y |
然后编辑 /etc/keepalived/keepalived.conf
配置文件,并在配置文件中增加 vrrp_script
定义一个外围检测机制,并在 vrrp_instance
中通过定义 track_script
来追踪脚本执行过程,实现节点转移:
1 | global_defs{ |
其中检测脚本 nginx_check.sh
,这里提供一个:
1 | !/bin/bash |
复制一份到备份服务器,备份 nginx 的配置要将 state
后改为 BACKUP
,priority
改为比主机小。
设置完毕后各自 service keepalived start
启动,经过访问成功之后,可以把 Master 机的 keepalived 停掉,此时 Master 机就不再是主机了 service keepalived stop
,看访问虚拟 IP 时是否能够自动切换到备机 ip addr。
再次启动 Master 的 keepalived,此时 vip 又变到了主机上。
配置高可用集群的内容来源于:Nginx 从入门到实践,万字详解!
其它功能和技巧
代理缓存
nginx 的 http_proxy 模块,提供类似于 Squid 的缓存功能,使用 proxy_cache_path 来配置。
nginx 可以对访问过的内容在 nginx 服务器本地建立副本,这样在一段时间内再次访问该数据,就不需要通过 nginx 服务器再次向后端服务器发出请求,减小数据传输延迟,提高访问速度:
1 | proxy_cache_path usr/local/cache levels=1:2 keys_zone=my_cache:10m; |
上面的配置表示: nginx 提供一块 10 M 的内存用于缓存,名字为 my_cache, levels 等级为 1:2,缓存存放的路径为 usr/local/cache
。
访问日志
访问日志默认是注释的状态,需要可以打开和进行更详细的配置,一下是 nginx 的默认配置:
1 | http { |
错误日志
错误日志放在 main 全局区块中,童鞋们打开 nginx.conf 就可以看见在配置文件中和下面一样的代码了:
1 | error_log logs/error.log; |
nginx 错误日志默认配置为:
error_log logs/error.log error;
静态资源服务器
1 | server { |
禁止指定 user_agent
nginx 可以禁止指定的浏览器和爬虫框架访问:
1 | http_user_agent 为浏览器标识 |
请求过滤
根据请求类型过滤
1 | 非指定请求全返回 403 |
根据状态码过滤
1 | error_page 502 503 /50x.html; |
这样实际上是一个内部跳转,当访问出现 502、503 的时候就能返回 50x.html 中的内容,这里需要注意是否可以找到 50x.html 页面,所以加了个 location 保证找到你自定义的 50x 页面。
根据URL名称过滤
1 | if ($host = zy.com' ) { |
ab 命令
ab命令全称为:Apache bench,是 Apache 自带的压力测试工具,也可以测试 Nginx、IIS 等其他 Web 服务器:
- -n 总共的请求数
- -c 并发的请求数
- -t 测试所进行的最大秒数,默认值 为 50000
- -p 包含了需要的 POST 的数据文件
- -T POST数据所使用的 Content-type 头信息
1 | ab -n 1000 -c 5000 http://127.0.0.1/ # 每次发送1000并发的请求数,请求数总数为5000。 |
测试前需要安装 httpd-tools: yum install httpd-tools
泛域名路径分离
这是一个非常实用的技能,经常有时候我们可能需要配置一些二级或者三级域名,希望通过 nginx 自动指向对应目录,比如:
- test1.doc.test.club 自动指向 /usr/local/html/doc/test1 服务器地址;
- test2.doc.test.club 自动指向 /usr/local/html/doc/test2 服务器地址;
1 | server { |
泛域名转发
和之前的功能类似,有时候我们希望把二级或者三级域名链接重写到我们希望的路径,让后端就可以根据路由解析不同的规则:
- test1.serv.test.club/api?name=a 自动转发到 127.0.0.1:8080/test1/api?name=a
- test2.serv.test.club/api?name=a 自动转发到 127.0.0.1:8080/test2/api?name=a
1 | server { |
附 nginx 模块
nginx 模块分类
- 核心模块:nginx 最基本最核心的服务,如进程管理、权限控制、日志记录;
- 标准 HTTP 模块:nginx 服务器的标准 HTTP 功能;
- 可选 HTTP 模块:处理特殊的 HTTP 请求
- 邮件服务模块:邮件服务
- 第三方模块:作为扩展,完成特殊功能
模块清单
核心模块:
- ngx_core
- ngx_errlog
- ngx_conf
- ngx_events
- ngx_event_core
- ngx_epll
- ngx_regex
标准 HTTP 模块:
- ngx_http
- ngx_http_core #配置端口,URI 分析,服务器相应错误处理,别名控制 (alias) 等
- ngx_http_log #自定义 access 日志
- ngx_http_upstream #定义一组服务器,可以接受来自 proxy, Fastcgi,Memcache 的重定向;主要用作负载均衡
- ngx_http_static
- ngx_http_autoindex #自动生成目录列表
- ngx_http_index #处理以/结尾的请求,如果没有找到 index 页,则看是否开启了random_index;如开启,则用之,否则用 autoindex
- ngx_http_auth_basic #基于 http 的身份认证 (auth_basic)
- ngx_http_access #基于 IP 地址的访问控制 (deny,allow)
- ngx_http_limit_conn #限制来自客户端的连接的响应和处理速率
- ngx_http_limit_req #限制来自客户端的请求的响应和处理速率
- ngx_http_geo
- ngx_http_map #创建任意的键值对变量
- ngx_http_split_clients
- ngx_http_referer #过滤 HTTP 头中 Referer 为空的对象
- ngx_http_rewrite #通过正则表达式重定向请求
- ngx_http_proxy
- ngx_http_fastcgi #支持 fastcgi
- ngx_http_uwsgi
- ngx_http_scgi
- ngx_http_memcached
- ngx_http_empty_gif #从内存创建一个 1×1 的透明 gif 图片,可以快速调用
- ngx_http_browser #解析 http 请求头部的 User-Agent 值
- ngx_http_charset #指定网页编码
- ngx_http_upstream_ip_hash
- ngx_http_upstream_least_conn
- ngx_http_upstream_keepalive
- ngx_http_write_filter
- ngx_http_header_filter
- ngx_http_chunked_filter
- ngx_http_range_header
- ngx_http_gzip_filter
- ngx_http_postpone_filter
- ngx_http_ssi_filter
- ngx_http_charset_filter
- ngx_http_userid_filter
- ngx_http_headers_filter #设置 http 响应头
- ngx_http_copy_filter
- ngx_http_range_body_filter
- ngx_http_not_modified_filter
可选 HTTP 模块:
- ngx_http_addition #在响应请求的页面开始或者结尾添加文本信息
- ngx_http_degradation #在低内存的情况下允许服务器返回 444 或者 204 错误
- ngx_http_perl
- ngx_http_flv #支持将 Flash 多媒体信息按照流文件传输,可以根据客户端指定的开始位置返回 Flash
- ngx_http_geoip #支持解析基于 GeoIP 数据库的客户端请求
- ngx_google_perftools
- ngx_http_gzip #gzip 压缩请求的响应
- ngx_http_gzip_static #搜索并使用预压缩的以.gz 为后缀的文件代替一般文件响应客户端请求
- ngx_http_image_filter #支持改变 png,jpeg,gif 图片的尺寸和旋转方向
- ngx_http_mp4 #支持.mp4,.m4v,.m4a 等多媒体信息按照流文件传输,常与 ngx_http_flv 一起使用
- ngx_http_random_index #当收到 / 结尾的请求时,在指定目录下随机选择一个文件作为 index
- ngx_http_secure_link #支持对请求链接的有效性检查
- ngx_http_ssl #支持 https
- ngx_http_stub_status
- ngx_http_sub_module #使用指定的字符串替换响应中的信息
- ngx_http_dav #支持 HTTP 和 WebDAV 协议中的 PUT/DELETE/MKCOL/COPY/MOVE 方法
- ngx_http_xslt #将 XML 响应信息使用 XSLT 进行转换
邮件服务模块:
- ngx_mail_core
- ngx_mail_pop3
- ngx_mail_imap
- ngx_mail_smtp
- ngx_mail_auth_http
- ngx_mail_proxy
- ngx_mail_ssl
第三方模块:
- echo-nginx-module #支持在 nginx 配置文件中使用 echo/sleep/time/exec 等类 Shell 命令
- memc-nginx-module
- rds-json-nginx-module #使 nginx 支持 json 数据的处理
- lua-nginx-module
感谢阅读~
参考链接: