对码当歌,猿生几何?

Nginx php-fpm 运行原理详解


一、代理与反向代理

现实生活中的例子

1、正向代理:

访问 google.com
1554133221876790.png


如上图,因为 google 被墙,我们需要 vpn 翻墙才能访问google.com

vpn 对于“我们”来说,是可以感知到的(我们连接 vpn)

vpn 对于"google 服务器"来说,是不可感知的(google 只知道有 http 请求过来)。

对于人来说可以感知到,但服务器感知不到的服务器,我们叫他正向代理服务器。

2、反向代理:

通过反向代理实现负载均衡
1554133307635398.png

如上图,我们访问 baidu.com 的时候,baidu 有一个代理服务器,通过这个代理服务器,可以做负载均衡,路由到不同的server。

此代理服务器,对于“我们”来说是不可感知的(我们只能感知到访问的是百度的服务器,不知道中间还有代理服务器来做负载均衡)。此代理服
务器,对于"server1 server2 server3"是可感知的(代理服务器负载均衡路由到不同的server)对于人来说不可感知,

但对于服务器来说是可以感知的,我们叫他反向代理服务器

总结:

说白了:“正向”、“反向”是相对于人的感知来说的。

人能感受到的代理就是正向代理,人感受不到的代理就是反向代理。

二、初识 Nginx 与 php-fpm

Nginx 是什么

Nginx (“engine x”)  是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 服务器。

Php-fpm 是什么

1、cgi、fast-cgi 协议

cgi 的历史

早期的 webserver 只处理 html 等静态文件,但是随着技术的发展,出现了像 php 等动态语言。webserver 处理不了了,怎么办呢?那就交给 php 解释器来处理吧!交给 php 解释器处理很好,但是,php 解释器如何与 webserver 进行通信呢?

为了解决不同的语言解释器(如 php、python 解释器)与 webserver 的通信,于是出现了 cgi 协议。只要你按照 cgi 协议去编写程序,就能实现语言解释器与 webwerver 的通信。如 php-cgi 程序。

fast-cgi的改进

有了 cgi 协议,解决了 php 解释器与 webserver 通信的问题,webserver 终于可以处理动态语言了。但是,webserver 每收到一个请求,都会去 fork 一个 cgi 进程,请求结束再 kill 掉这个进程。这样有 10000 个请求,就需要 fork、kill php-cgi 进程10000次。

有没有发现很浪费资源?

于是,出现了 cgi 的改良版本,fast-cgi。fast-cgi 每次处理完请求后,不会 kill 掉这个进程,而是保留这个进程,使这个进程可以一次处理多个请求。这样每次就不用重新 fork 一个进程了,大大提高了效率。

2、php-fpm是什么

php-fpm 即 php-Fastcgi Process Manager. php-fpm 是 FastCGI 的实现,并提供了进程管理的功能。进程包含 master 进程和 worker 进程两种进程。master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个(具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方。

三、Nginx 如何与 php-fpm 结合

上面我们说了,Nginx 不只有处理 http 请求的功能,还能做反向代理。

Nginx 通过反向代理功能将动态请求转向后端 php-fpm。

下面我们来配置一个全新的 Nginx+php-fpm

1、配置 nginx.conf 文件

进入 nginx 目录下,编辑 nginx.conf 文件。

如图,在 nginx.conf 最后一行,添加 include 文件

1554133392789112.png
2、添加对应的 server

进入上面 include 的路径,添加一个 server.
1554133469368747.png

下面我们解释一下配置项的含义:

server {listen       80; #监听80端口,接收http请求server_name  www.example.com; #就是网站地址root /usr/local/etc/nginx/www/huxintong_admin; # 准备存放代码工程的路径#路由到网站根目录www.example.com时候的处理location / {index index.php; #跳转到www.example.com/index.phpautoindex on;}   #当请求网站下php文件的时候,反向代理到php-fpmlocation ~ .php$ {include /usr/local/etc/nginx/fastcgi.conf; #加载nginx的fastcgi模块fastcgi_intercept_errors on;fastcgi_pass   127.0.0.1:9000; #nginx fastcgi进程监听的IP地址和端口}}

总而言之:当我们访问 www.example.com 的时候,处理流程是这样的:

www.example.com
        |
        |
      Nginx
        |
        |
路由到www.example.com/index.php
        |
        |
加载nginx的fast-cgi模块
        |
        |
fast-cgi监听127.0.0.1:9000地址
        |
        |
www.example.com/index.php请求到达127.0.0.1:9000
        |
        |
     等待处理...

下面我们启用 php 的 php-fpm 来处理这个请求

打开 php-fpm.conf 文件,我们看到如下配置:
1554133517409200.png

即: php-fpm 模块监听 127.0.0.1:9000 端口,等待请求到来去处理。

四、总结

nginx 与 php-fpm 的结合,完整的流程是这样的。

www.example.com
        |
        |
      Nginx
        |
        |
路由到www.example.com/index.php
        |
        |
加载nginx的fast-cgi模块
        |
        |
fast-cgi监听127.0.0.1:9000地址
        |
        |
www.example.com/index.php请求到达127.0.0.1:9000
        |
        |
php-fpm 监听127.0.0.1:9000
        |
        |
php-fpm 接收到请求,启用worker进程处理请求
        |
        |
php-fpm 处理完请求,返回给nginx
        |
        |
nginx将结果通过http返回给浏览器
五、效果展示

1、启动 nginx 与 php-fpm 模块
1554133653533426.png

启动成功,我们查看 php-fpm 进程
1554133700726631.png

如上图,有一个 master 进程,3个 worker 进程。

2、在网站目录下建立文件
我们编辑文件如下图:
1554133738920845.png

3、访问网站

1554133593467203.png