【精选】Go 和 PHP 在运行的时候有什么区别

发布于 2021-05-12 23:19 ,所属分类:区块连和PHP开发学习资料


PHP运行的时候是每个请求进来时都会创建 fpm-worker 进程,从而导致系统并发高时 CPU 会产生频繁创建进程的开销,具体可以看以下图片。

目前常见的 4 种 PHP 运行模式
CGI 通用网关接口模式
FAST-CGI 模式
CLI 命令行模式
模块模式

1 CGI 通用网关接口模式
每有一个用户请求,都会先要创建 cgi 的子进程,然后处理请求,处理完后结束这个子进程。

cgi 是一种为了保证 web server 传递过来的数据是标准格式的通用网关接口协议。

2 FAST-CGI 模式
这个是 cgi 的升级版本,FastCGI 像是一个常驻 (long-live) 型的 CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去 fork 一次,也是一种协议。

FastCGI 的工作原理是:
1)、Web Server 启动时载入 FastCGI 进程管理器【PHP 的 FastCGI 进程管理器是 PHP-FPM (php-FastCGI Process Manager)】(IIS ISAPI 或 Apache Module);

2)、FastCGI 进程管理器自身初始化,启动多个 CGI 解释器进程 (在任务管理器中可见多个 php-cgi.exe) 并等待来自 Web Server 的连接。

3)、当客户端请求到达 Web Server 时,FastCGI 进程管理器选择并连接到一个 CGI 解释器。Web server 将 CGI 环境变量和标准输入发送到 FastCGI 子进程 php-cgi。

4)、FastCGI 子进程完成处理后将标准输出和错误信息从同一连接返回 Web Server。当 FastCGI 子进程关闭连接时,请求便告处理完成。FastCGI 子进程接着等待并处理来自 FastCGI 进程管理器(运行在 WebServer 中)的下一个连接。在正常的 CGI 模式中,php-cgi.exe 在此便退出了。

在 CGI 模式中,可以想象 CGI 通常有多慢。每一个 Web 请求 PHP 都必须重新解析 php.ini、重新载入全部 dll 扩展并重初始化全部数据结构。使用 FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接 (Persistent database connection) 可以工作。

3 CLI 命令行模式
一般使用调用脚本、查看 php 信息时会使用到该模式
php -r”phpinfo ();” |less 分页显示

4 模块模式
  • Apache + mod_php
  • lighttp + spawn-fcgi
  • nginx + PHP-FPM

运行原理
PHP-CGI:fast-cgi 是一种协议,而 php-cgi 是实现了这种协议的进程。不过这种实现比较烂。它是单进程的,一个进程处理一个请求,处理结束后进程就销毁。

PHP-FPM:是对 php-cgi 的改进版,它直接管理多个 php-cgi 进程 / 线程。也就是说,php-fpm 是 php-cgi 的进程管理器因此它也算是 fastcgi 协议的实现。

php 的运行原理,就是在服务器启动时,自动载入 PHP-FPM 进程管理器,从而管理多个 PHP-CGI 进程来准备响应用户的。

请求,如下图所示:
多个运行模式相当于超市的不同入口,运行原理就是进入超市后的固定的行走路线,通过不同的运行模式进入到底层

Go语言的运行原理

golang 是先编译为静态二进制可执行文件,再去运行的。
主要看看 go run 与 go build 的区别
1go run 的执行过程,如图所示

  1. 创建了两个临时文件夹 b001 和 exe
  2. 先执行了 compile 命令,然后 link,生成了归档文件.a 和 最终可执行文件
  3. 最终的可执行文件放在 exe 文件夹里面。
  4. 命令的最后一步就是执行了可执行文件。

举个例子,生成的临时文件可以用go run -work看到,比如当前生成的临时文件夹是如下的路径:
localhost:helloruby$gorun-workmytest.go
WORK=/var/folders/kt/nlhsnpgn6lgd_q16f8j83sbh0000gn/T/go-build593750496
HelloWorld
你好,Go!!!
localhost:helloruby$

进入:/var/folders/kt/nlhsnpgn6lgd_q16f8j83sbh0000gn/T/go-build593750496目录,可以看到如下目录结构:

可以看到,最终 go run 命令是生成了 2 个文件,一个是归档文件,一个是可执行文件。

go run 命令在第二次执行的时候,如果发现导入的代码包没有发生变化,那么 go run 不会再次编译这个导入的代码包。直接静态链接进来。


go build 的执行过程
go build 的执行过程如下图所示
go build 用于编译我们指定的源码文件或代码包以及它们的依赖包。但是注意如果用来编译非命令源码文件,即库源码文件,go build 执行完是不会产生任何结果的。

这种情况下,go build 命令只是检查库源码文件的有效性,只会做检查性的编译,而不会输出任何结果文件。

go build 编译命令源码文件,则会在该命令的执行目录中生成一个可执行文件,上面的例子也印证了这个过程。

go build 后面不追加目录路径的话,它就把当前目录作为代码包并进行编译。go build 命令后面如果跟了代码包导入路径作为参数,那么该代码包及其依赖都会被编译。

go build 命令究竟做了些什么呢?我们可以执行 - n 这个命令来查看。这里略过打印输出。

执行过程和 go run 大体相同,唯一不同的就是在最后一步,go run 是执行了可执行文件,但是 go build 命令,只是把库源码文件编译了一遍,然后把可执行文件移动到了当前目录的文件夹中。


想要获取学习实战、高并发、架构、笔试面试资料,请架构师学习路线图
*声明:本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜

相关资源