关于持久连接和 FastCGI

PHP 作为一种脚本解释语言,其解析器在执行完脚本后会释放所有资源,包括数据库连接等等。这样下次需要再执行脚本时,就需要重新连接数据库了。
频繁地创建和关闭连接,无疑会造成不必要的开销。因此,在 PHP 中引入了持久连接的概念。具体可以看:
http://php.net/manual/en/features.persistent-connections.php

持久连接,不能工作在 CGI 模式下,因为 CGI 进程结束后,会释放所有资源。
PHP 当前主流的运行模式有两种,一种是以 web server 的 module 运行,另一种是 fastcgi。
在这两种模式下,都能够使用持久连接,因为创建连接后连接资源可以交给 web server 或 fastcgi server。

我个人更偏向于用 fastcgi,结构清晰,并且能提升 web server 的处理性能。
来看看一段简短地描述:

After all, Apache already has mod_php.
However, there are advantages to running PHP with FastCGI. Separating the PHP code from the web server removes ‘bloat’ from the main server, and should improve the performance of non-PHP requests. Secondly, having one permanent PHP process as opposed to one per apache process means that shared resources like persistent database connections are used more efficiently.

在 fastcgi 模式下,一个 PHP 进程固定地占用一个持久连接,只有可能连接数据库的 PHP 脚本才有可能装入这个 PHP 进程。
而 module 模式下,每个 apache 进程都会加载 PHP 模块,每个 apache 进程都会占用一个持久连接,这样不管是不是在处理 PHP ,都要占用连接。
因此,fastcgi 比 module 能够更好地利用持久连接。

在使用持久连接时,需要特别注意的是,数据库设置的允许的最大连接数不能小于 PHP 可能的实例数。

  • 在 module 模式下,数据库连接数要大于 apache 可能的最大进程数。
  • 在 fastcgi 模式下,数据库连接数要大于 php-cgi 最大进程数。

否则,可能出现连接数不够无法连接到数据库的错误。

来做个应用题:
一个网站的 PHP 运行在 fastcgi 模式下,流量大概是 1亿/日,需要持久连接的资源有 3 种。请估算下要几个 php-cgi 实例,几个持久连接?

1亿/日,估算高峰期每秒请求数为日均压力的 10 倍,为 (1亿/86400)*10 = 11574 requests/second。
假设每个请求平均耗时 0.3 秒,那么至少需要运行 11574/3 = 3858 个 php-cgi 实例。
采用持久连接,每个资源需要 1 个连接,需要 3858*3 = 11574 个持久连接。

挺险的,如果用 tcp 连接,数量级再大一倍,连接数都不够用了(当然我们还可以用 Unix Domain Socket),不过这种量也不可能跑在单台服务器上,所以连接数的问题也不愁啦。

— EOF —

19 thoughts on “关于持久连接和 FastCGI”

  1. 你好
    >假设每个请求平均耗时 0.3 秒,那么至少需要运行 11574/3 = 3858 个 php-cgi 实例。
    >采用持久连接,每个资源需要 1 个连接,需要 3858*3 = 11574 个持久连接。

    为什么是“需要 3858*3 = 11574 个持久连接”呢,我认为3858个持久连接就够了。你说的“每个资源”指的是什么意思呢?请指教。

    1. 我上面提到“需要持久连接的资源有 3 种”,比如一个请求过程中要同时对 Memcached,MySQLd 和 Sphinx Searchd 三种资源。连接每个资源都需要占用一个连接,因此最后要乘以3。

  2. php5.3以上版本使用mysqlnd改进了持久连接,单个的php-cgi进程能够占有多个持久连接(依据数据库的不同)。是不是mysql的配置里的连接数 >= php-cgi进程数 * 要访问的mysql数据库数目

发表评论

电子邮件地址不会被公开。 必填项已用*标注