Nginx原理及九大常见故障解决方法
#作者:Unstopabler
文章目录
- 一、 Nginx简介
- Ngnix特点:
- 二、 Nginx原理架构
- 内核和模块
- nginx的工作流程
- 三、 常见问题及解决方法
- 3.1 认识返回码
- 3.2 nginx中localion后路径带或不带/的匹配规则问题
- 3.3 nginx重定向问题:
- 3.4 Nginx防盗链问题:
- 3.5 错误码504问题
- 3.6 nginx报错500的解决办法
- 3.7 docker运行nginx,绑定配置文件启动报错解决方法
- 3.8 docker容器中启动nginx后容器会挂掉解决方法
- 3.9 k8s启动nginx容器错误CrashLoopBackOff
一、 Nginx简介
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,是由伊戈尔·赛索耶夫开发的,第一个公开版本0.1.0发布于2004年10月4日, Nginx代码完全用C语言从头写成,已经移植到许多体系结构和操作系统,包括:Linux、FreeBSD、Solaris、Mac OS X、AIX以及Microsoft Windows。Nginx有自己的函数库,并且除了zlib、PCRE和OpenSSL之外,标准模块只使用系统C库函数。而且,如果不需要或者考虑到潜在的授权冲突,可以不使用这些第三方库。事实上nginx的并发能力在同类型的网页服务器中表现较好。
Ngnix特点:
1.高并发:单机支持10万以上的并发连接;
2.高性能:低内存消耗:一般1万个非活跃的 HTTP Keep-Alive 连接在 Nginx 中仅消耗2.5MB内存;
3.高可靠性:可以在服务器上持续不间断运行数年;
4.高拓展性:主要体现在它的模块化设计,模块化设计非常的稳定使得nginx的第三方模块生态圈非常的丰富,丰富的生态圈为我们nginx丰富的功能提供了保证;
5.热部署:master 管理进程与 worker工作进程的分离设计,使得 Nginx 能够支持热部署;
6.开源协议:使用 BSD 许可协议,免费使用,且可修改源码。
二、 Nginx原理架构
内核和模块
Nginx由内核和模块组成,Nginx的模块从结构上分为核心模块、基础模块和第三方模块:
- 核心模块:HTTP模块、EVENT模块和MAIL模块
- 基础模块:HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块
- 第三方模块:HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块。
nginx的工作流程
每个 Worker 进程都是从 Master 进程fork过来,在 Master 进程里面,先建立好需要 listen 的 socket(listenfd)之后,然后再 fork 出多个 Worker 进程。所有 Worker 进程的 listenfd 会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有 Worker 进程在注册 listenfd 读事件前抢互斥锁accept_mutex,抢到互斥锁的那个进程注册 listenfd 读事件,在读事件里调用 accept 接受该连接。当一个 Worker 进程在 accept 这个连接之后,就开始读取、解析、处理请求,在产生数据后再返回给客户端,最后才断开连接,这样一个完整的请求就是这样的了
一个worker进程可以同时处理多个请求,每个worker进程只有一个主线程,而是采用异步非阻塞的方式来处理并发请求。比如同时有多个http request的时候,worker主线程与第一条request建议连接将其处理转发给下游fast cgi后,并不会挂起等待,而是立马处理下一条,可以理解轮询处理。与多线程相比,这种事件处理方式是有很大的优势的,不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级。并发数再多也不会导致无谓的资源浪费(上下文切换),更多的并发数,只是会占用更多的内存而已。因此nginx 是非常适合处理高并发请求的。
三、 常见问题及解决方法
3.1 认识返回码
Nginx返回码的含义,可以帮助我们排查Nginx的故障
3.2 nginx中localion后路径带或不带/的匹配规则问题
proxy_pass代理地址端口后无任何,转发后地址:代理地址+访问URL目录部。
proxy_pass代理地址端口后有目录(包括 / ),转发后地址:代理地址+访问URL目录部分去除location匹配目录proxy_pass末尾有斜杠
请求地址:http://localhost/api/test
转发地址:http://127.0.0.1:8000/test
(1)proxy_pass末尾无斜杠
请求地址:http://localhost/api/test
转发地址:http://127.0.0.1:8000/api/test
(2)proxy_pass包含路径,且末尾有斜杠
请求地址:http://localhost/api/test
转发地址:http://127.0.0.1:8000/user/test
(3)proxy_pass包含路径,且末尾无斜杠
请求地址:http://localhost/api/test
转发地址:http://127.0.0.1:8000/usertest
3.3 nginx重定向问题:
重定向是一个非常常用的功能,在 web 服务中,通常会通过重定向功能,将一个域名的请求转发到另一个域名上, 常用的重定向类型有 301 和 302 两种, 301 永久重定向,302 临时重定向
301 跳转
302跳转:将permanent修改为redirect即为临时性跳转
3.4 Nginx防盗链问题:
HTTP Referer是Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理,
例如防止未经允许的网站盗链图片、文件等。因此HTTP Referer头信息是可以通过程序来伪装生成的,所以通过Referer信息防盗链并非100%可靠,但是,它能够限制大部分的盗链
图片防盗链示例:
server {listen 80;server_name www.test.com www.test1.comroot /usr/share/nginx/html;location ~*\.(gif|jpg|jpeg|png|bmp|swf)$ {valid_referers www.test1.com;if ($invalid_referer) {return 403;#rewrite ^/ http://www.test1.com/fangdaolian.jpg;}}}
说明:
location ~ .(jpg|png|gif|jpeg)$ {}为设置防盗链的文件类型,使用竖线|分隔。
valid_referers ;为白名单,使用空格分隔,可以使用*进行泛域名设置。
if ($invalid_referer) {}为判断是否符合白名单,不符合白名单将执行{}内的内容。
rewrite为重写资源,如果不合符白名单,则重写为该地址。
return 403;代表返回的状态码为403。
3.5 错误码504问题
造成错误码504原因很多,504错误一般是与nginx.conf配置有关,在这列举其中之一:
问题:在使用ajax向tomcat部署的rest服务(使用nginx作为反向代理服务器)请求数据时返回了Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource这个异常,错误码是504(网关超时)
原因:问题产生的根源在于tomcat上rest服务异常导致没有返回任何数据给nginx代理服务器,而nginx超时后就会返回504这个错误给chrome浏览器。
解决:通过设置proxy_connect_timeout参数来设置nginx连接tomcat服务器超时时间
3.6 nginx报错500的解决办法
500–服务器内部错误:服务器遇到错误,无法完成请求:500错误码一般因nginx配置原因导致较少,大部分是tomcat或者后端程序原因较多
问题一:系统开发程序写的有问题,则报HTTP500错误。例如有些指针问题没有处理好的,有空指针情况的存在。修改程序后问题解决。
问题二:如果测试中所进行的操作需要向数据库中插入数据,若大数据量的情况下导致数据库中表空间已满,或 缓冲池较小无法满足数据的存取等,都有可能导致HTTP500错误。调整数据库、修改连接池大小,问题解决
3.7 docker运行nginx,绑定配置文件启动报错解决方法
现象:docker cp命令报错Error: No such container:path:
解决:通常在docker cp 这一步后面的路径没有指定好,docker启动的nginx,一定要注意映射目录,nginx只能访问到容器内的目录,所以,最好提前进行目录挂载
3.8 docker容器中启动nginx后容器会挂掉解决方法
现象:在Dockerfile中调用一个脚本,如ENTRYPOINT [ “sh”, “/test.sh” ]该脚本用来根据启动时传入的参数修改nginx默认的配置文件,然后重启nginx服务,出现挂掉服务
解决:在docker容器中pid=1的进程挂掉后整个容器就会挂掉,对于基于nginx的容器而言,默认pid=1的进程就是nginx,但是一旦你在Dockerfile中使用CMD或者ENTRYPOINT之后,这个对应的程序就会替换nginx变为pid=1的进程,而一旦这个脚本执行完退出,这个容器就会停掉。当使用nginx -g "daemon off;"之后就是告诉nginx在启动后不退出,可以保证生成的容器可以正常运行.
3.9 k8s启动nginx容器错误CrashLoopBackOff
现象:nginx的POD错误为CrashLoopBackOff
解决:
在yaml文件中添加如下:
command: ["/data/nginx/sbin/nginx", "-g", "daemon off;"]