首页 >后端开发 >php教程 >nginx相关知识点总结分享

nginx相关知识点总结分享

小云云
小云云原创
2018-03-31 13:59:251544浏览

Nginx本身不会对PHP进行解析,终端对PHP页面的请求将会被Nginx交给FastCGI进程监听的IP地址及端口,由php-fpm作为动态解析服务器处理,最后将处理结果再返回给nginx。其实,Nginx就是一个反向代理服务器。Nginx通过反向代理功能将动态请求转向后端php-fpm,从而实现对PHP的解析支持,这就是Nginx实现PHP动态解析的原理。  

     Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket(这个socket可以是文件socket,也可以是ip socket)。为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接收到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端。

经典的模型就是Nginx中所用的Master-Worker多进程异步驱动模型。

父进程创建socket,bind、listen后,通过fork创建多个子进程,每个子进程继承了父进程的socket,调用accpet开始监听等待网络连接。这个时候有多个进程同时等待网络的连接事件,当这个事件发生时,这些进程被同时唤醒,就是“惊群”。进程被唤醒,需要进行内核重新调度,这样每个进程同时去响应这一个事件,而最终只有一个进程能处理事件成功,其他的进程在处理该事件失败后重新休眠或其他。

其实在Linux2.6版本以后,内核内核已经解决了accept()函数的“惊群”问题,当内核接收到一个客户连接后,只会唤醒等待队列上的第一个进程或线程。

Nginx中使用accept_mutexmutex互斥锁解决这个问题,具体措施有使用全局互斥锁,每个子进程在epoll_wait()之前先去申请锁,申请到则继续处理,获取不到则等待,并设置了一个负载均衡的算法(当某一个子进程的任务量达到总设置量的7/8时,则不会再尝试去申请锁)来均衡各个进程的任务量。

现在我们对惊群及 Nginx 的处理总结如下:

  • accept 不会有惊群,epoll_wait 才会。

  • Nginx 的 accept_mutex,并不是解决 accept 惊群问题,而是解决 epoll_wait 惊群问题。

  • 说Nginx 解决了 epoll_wait 惊群问题,也是不对的,它只是控制是否将监听套接字加入到epoll 中。监听套接字只在一个子进程的 epoll 中,当新的连接来到时,其他子进程当然不会惊醒了。

简单了说,就是同一时刻只允许一个nginx worker在自己的epoll中处理监听句柄。它的负载均衡也很简单,当达到最大connection的7/8时,本worker不会去试图拿accept锁,也不会去处理新连接,这样其他nginx worker进程就更有机会去处理监听句柄,建立新连接了。而且,由于timeout的设定,使得没有拿到锁的worker进程,去拿锁的频繁更高。

nginx 多进程模型真的没有锁了吗?其实还是有一个的:ngx_accept_mutex。

nginx是一个多进程程序,80端口为各worker进程共享,每当有连接到来时,势必多个worker进程都要争着去响应,这也就是所谓的惊群现象。

当内核accept一个链接时,会唤醒所有等待中的进程,但实际上只有一个进程能获取连接,其它的进程都被无效唤醒,这种无效唤醒无疑将会增加应用的开销。为此,nginx提供了一把accept锁避免九子夺嫡的悲剧。

ngx_accept_mutex的作用也就是让那些当前负载严重

的worker进程主动放弃对新到来的请求的处理,提高

应用整体的唤醒效率,进而提升应用的整体性能。

proxy_cache

upstream

fastcgi_pass

location

非标准状态码444表示关闭连接且不给客户端发响应头。

nginx -s  reload 命令加载修改后的配置文件,命令下达后发生如下事件

1. Nginx的master进程检查配置文件的正确性,若是错误则返回错误信息,nginx继续采用原配置文件进行工作(因为worker未受到影响)

2. Nginx启动新的worker进程,采用新的配置文件

3. Nginx将新的请求分配新的worker进程

4. Nginx等待以前的worker进程的全部请求已经都返回后,关闭相关worker进程

5. 重复上面过程,知道全部旧的worker进程都被关闭掉

以上过程是参考nginx官方的相关文档后得出。

以 proxy_next_upstream为例, 一般的配置如下:

proxy_next_upstream http_504 timeout;

这个指令有两个作用 :

  1. 告诉nginx,如果发生了连接超时,上游返回504的时候,需要重试upstream

  2. 告诉nginx, http 504 ,连接超时 是 请求失败

总的来说, nginx对于 error, timeout, invalide_header 均默认是失败, 其他的行为如果想当作失败,需要加入类似 proxy_next_upstream之类的指令里面的 。 其中 http_403, http_404均不认识是失败。

论两点, 对 server 失败的定义 和 server失败后的行为。

  • server 失败的定义 : 上面的模块失败定义主要用于说明一个请求在什么情况下是失败的;但是什么定义一个server是失败的呢? nginx里面主要用两个参数控制 : max_fails和fail_timeout。 简单的说,如果一个请求在 fail_timeout内发生了max_fails次失败,就认识改server当前是down。

  • 失败后的行为 : 主要为:

  • 在 fail_timeout 时间段,都不会选择该server ;

  • 在 fail_timeout 时间后,会将该server标记为 normal,重复已有的逻辑。

Ngxin把对客户端请求的处理过程划分为11个阶段

#1  NGX_HTTP_POST_READ_PHASE:      读取请求内容阶段

#2  NGX_HTTP_SERVER_REWRITE_PHASE: Server请求地址重写阶段

#3  NGX_HTTP_FIND_CONFIG_PHASE:    配置查找阶段

#4  NGX_HTTP_REWRITE_PHASE:        Location请求地址重写阶段

#5  NGX_HTTP_POST_REWRITE_PHASE:   请求地址重写提交阶段

#6  NGX_HTTP_PREACCESS_PHASE:      访问权限检查准备阶段

#7  NGX_HTTP_ACCESS_PHASE:         访问权限检查阶段

#8  NGX_HTTP_POST_ACCESS_PHASE:    访问权限检查提交阶段

#9  NGX_HTTP_TRY_FILES_PHASE:      配置项try_files处理阶段

#10 NGX_HTTP_CONTENT_PHASE:        内容产生阶段

#11 NGX_HTTP_LOG_PHASE:            日志模块处理阶段

Nginx的请求处理流程

#1 Nginx如何确认由哪个server处理该请求?

1. 利用ip + port 确认监听该ip和端口的server。

2. 根据请求中的host首部确认选择那个server处理该请求。

3. 如果没有匹配到任何server,则把该请求转给默认(default)server处理,

   一般而言,不加任何设置的话,配置文件中顺序出现的第一个server作为

   default server。

4. 可以对listen指令使用default_server标志,去设置某个server为

   default server。

#2 Nginx如何根据host首部匹配server?

    Nginx主要是通过比较server中的server_name和host首部来匹配server的。

    比较顺序如下所示:

1. 精确的name;

2. 最长匹配的前导通配符name(如:*.zhidao.baidu.com);

3. 最长的后导通配符name(如:zhidao.baidu.*);

#3 初始化http请求,http请求的11个阶段

location匹配命令

~      波浪线表示执行一个正则匹配,区分大小写。

~*    表示执行一个正则匹配,不区分大小写。

^~    ^~表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录。

=      进行普通字符精确匹配。

@     "@" 定义一个命名的 location,使用在内部定向时,例如 error_page,try_files。

示例: 


请求URI例子:

  • / -> 符合configuration A

  • /documents/document.html -> 符合configuration B

  • /images/1.gif -> 符合configuration C  

  • /documents/1.jpg ->符合 configuration D

相关推荐:

nginx反向代理机制解决前端跨域问题

nginx如何修改上传文件大小

Nginx动静分离操作讲解

以上是nginx相关知识点总结分享的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn