Nginx 笔记

简介

Nginx:是一款轻量级的 Web 服务器、反向代理服务器,由于它的内存占用少(一个 worker 进程只占用 10-12M 内存)、启动极快、高并发能力强,在互联网项目中广泛应用。

代理

正向代理

由于防火墙的原因,我们并不能直接访问谷歌,那么我们可以借助 VPN 来实现,这就是一个简单的正向代理的例子。这里你能够发现,正向代理“代理”的是客户端,客户端是知道目标的,而目标是不知道客户端是通过 VPN 访问的。

反向代理

当我们在外网访问百度的时候,其实会进行一个转发,代理到内网去,这就是所谓的反向代理,即反向代理“代理”的是服务器端,而且这一个过程对于客户端而言是透明的。

web 服务器对比

对比项 \ 服务器 Apache Nginx Lighttpd
Proxy代理 非常好 非常好 一般
Rewriter 非常好 一般
Fcgi 不好 非常好
热部署 不支持 支持 不支持
系统压力 很大 很小 比较小
稳定性 非常好 不好
安全性 一般 一般
静态文件处理 一般 非常好
反向代理 一般 非常好 一般

负载均衡

负载均衡作为流量转发服务,将来自客户端的请求通过负载均衡集群转发至后端服务器,后端服务器再将响应通过内网返回给负载均衡。基础架构是采用集群部署,提供四层(TCP 协议和 UDP 协议)和七层(HTTP 和 HTTPS 协议)的负载均衡,可实现会话同步,以消除服务器单点故障,提升冗余,保证服务的稳定性。

  • 硬件负载均衡:是直接在服务器和外部网络间安装负载均衡设备,这种设备通常是一个独立于系统的硬件,我们称之为负载均衡器,例如 F5。
  • 软件负载均衡:是指在一台或多台服务器相应的操作系统上安装一个或多个附加软件来实现负载均衡,例如 Nginx、LVS。
  • 四层负载均衡:是指基于IP + 端口的负载均衡,常见例子有:LVS,F5。
  • 七层负载均衡:是基于虚拟URL或主机IP的负载均衡,常见例子有: HAProxy,MySQL Proxy。

Nginx 进程

启动 Nginx 后,其实就是在 80 端口启动了 Socket 服务进行监听,Nginx 涉及 Master 进程和 Worker 进程。

  • Master 进程:读取并验证配置文件 nginx.conf,管理 worker 进程。
  • Worker 进程:每一个 Worker 进程都维护一个线程(避免线程切换),处理连接和请求,Worker 进程的个数由配置文件决定,一般和 CPU 个数相关(有利于进程切换),配置几个就有几个 Worker 进程。

思考1:Nginx 如何做到热部署?

所谓热部署,就是配置文件 nginx.conf 修改后,不需要 stop nginx,不需要中断请求,就能让配置文件生效!

实现方案:修改配置文件 nginx.conf 后,重新生成新的 worker 进程,当然会以新的配置进行处理,而且新的请求都必须交给新的 worker 进程,至于老 worker 进程,等把那些以前的请求处理完毕,kill 掉即可。

思考2:Nginx 如何做到高并发下的高效处理?

实现方案:Nginx 采用了 Linux 的 epoll 模型,epoll 模型基于事件驱动机制,它可以监控多个事件是否准备完毕,如果 OK,那么放入 epoll 队列中,这个过程是异步的,worker 只需要从 epoll 队列循环处理即可。

思考3:Nginx 挂了怎么办?

实现方案:Keepalived + Nginx 实现高可用

  • 请求不要直接打到 Nginx 上,应该先通过 Keepalived(这就是所谓虚拟 IP,VIP),消除单点故障
  • Keepalived 应该能监控 Nginx 的生命状态(提供一个用户自定义的脚本,定期检查 Nginx 进程状态,进行权重变化,从而实现 Nginx 故障切换)

安装

  • 安装
1
2
rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
yum install -y nginx
  • 路径
1
2
3
4
5
6
7
8
$ whereis nginx
nginx: /usr/sbin/nginx /usr/lib64/nginx /etc/nginx /usr/share/nginx /usr/share/man/man8/nginx.8.gz

- Nginx配置路径:/etc/nginx/nginx.conf
- PID目录:/var/run/nginx.pid
- 错误日志:/var/log/nginx/error.log
- 访问日志:/var/log/nginx/access.log
- 默认站点目录:/usr/share/nginx/html

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 80;
server_name zentao.smocer.top;

access_log /var/log/nginx/zentao.access.log;

location / {
try_files /_not_exists_ @backend;
}

location @backend {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;

proxy_pass http://10.133.0.53:8080;
}

常用命令

启动

1
nginx

检查配置

1
nginx -t

热加载

1
nginx -s reload

查询进程

1
ps -ef | grep nginx

停服务

1
nginx -s stop

FAQ

Nginx 启动成功,加载页面,报错 ERR_CONTENT_LENGTH_MISMATCH

错误日志

1
2020/03/23 17:20:17 [crit] 87961#0: *419 open() "/usr/local/var/run/nginx/proxy_temp/5/08/0000000085" failed (13: Permission denied) while reading upstream, client: 127.0.0.1, server: x-dev.qd-ctcc.haier.net, request: "GET /console/vendors~alarm.js HTTP/1.1", upstream: "http://127.0.0.1:8040/console/vendors~alarm.js", host: "x-dev2.qd-ctcc.haier.net", referrer: "http://x-dev2.qd-ctcc.haier.net/console"

原因分析

Nginx 在压力之下,试图从它的缓存中拉取 /usr/local/var/run/nginx/,但是由于权限问题无法访问。出现这个问题的根本原因是使用管理员账号启动了 Ngnix,然后又使用普通账号启动了一次导致无法访问缓存目录。

解决办法

使用管理员账号删除 /usr/local/var/run/nginx/proxy_temp 目录缓存,然后使用非管理员账号重启 Nginx。