启用 HTTP2 协议支持

准备

这些天一直在群里看阿忆在研究 LSWS(LiteSpeed Web Server),说是支持 HTTP/3,访问处理速度能达到现有的 30-50 倍以上(顺便催更@GOOD-AN 的 WordPress 优化教程),好奇搜索了一下,发现早在 2015 年 HTTP/2 协议就已经公布了,具体速度对比可以参考这个站点(HTTP/2: the Future of the Internet | Akamai)。于是决定对我的站点启用 HTTP/2 协议试图提高访问速度(然后发现微乎其微),在 apache 的完善 docs 和搜索引擎的帮助下可算成功了,现在记录一下遇到的坑和操作。

坑 1:MPM 配置

第一步需要确定自己的 apache 版本和 openssl 版本是否支持 HTTP/2 协议,httpd 的版本至少需要 2.4.17,openssl 版本至少需要 1.0.2e,如果是自己编译安装的 httpd 则需要添加编译属性

-enable-http2
启用在 Apache 服务器内部实现该协议的 ‘http2’ 模块。
--with-nghttp2=
指定 http2 模块需要的 libnghttp2 模块的非默认位置。如果 nghttp2 是在默认的位置,配置过程会自动采用。
--enable-nghttp2-staticlib-deps
很少用到的选项,你可能想将 nghttp2 库静态链接到服务器里。在大部分平台上,只有在找不到共享 nghttp2 库时才有用。

然后启用 mod_http2 模块并在 vhost 里面添加 Protocols h2 http/1.1(For HTTPS)或者 Protocols h2c http/1.1(For HTTP)即可,重启刷新,欸?怎么还是 HTTP/1.1?

翻看了一下 Apache 的文档,在 HTTP/2 指南-MPM 配置中找到了原因:

httpd随附的所有多处理模块均支持HTTP / 2。但是,如果您使用的是preforkmpm,则会受到严格的限制。
在中prefork,mod_http2每个连接一次只能处理一个请求。但是客户端(例如浏览器)将同时发送许多请求。如果其中之一需要花费很长时间进行处理(或者是长时间轮询),则其他请求将停止。
mod_http2默认情况下不会超出此限制。原因是, prefork今天仅在运行未准备用于多线程的处理引擎的情况下才选择该引擎,例如,将因多个请求而崩溃。
如果您的设置可以处理,那么配置eventmpm是当今最好的配置(如果您的平台支持)。
如果您确实遇到困难prefork并想要多个请求,则可以进行调整H2MinWorkers以使之成为可能。但是,如果破裂,您将拥有这两个部分。

好嘛,那就不用 prefork 这个 mpm 好了,修改 00-mpm.conf 注释掉LoadModule mpm_prefork_module modules/mod_mpm_prefork.so,然后启用LoadModule mpm_event_module modules/mod_mpm_event.so

坑 2:PHP 模块配置

修改完再刷新访问,测试站点完美使用 H2 协议了,看来也很简单的嘛,光速把博客等站点的配置文件也改了,然后博客就 500 了。。。出了问题就改撒,翻了下 error.log,提示为

[core:alert] [pid 918798:tid 140078739285760] [client 222.133.217.243:62909] /var/www/html/blog/.htaccess: Invalid command 'php_value', perhaps misspelled or defined by a module not included in the server configuration

嗯,,,WTF???怎么能不支持这个东西,我随即访问我测试站点的 info.php 发现也提示 500ERROR,这就超出我的处理能力了,经过一番搜索得知,PHP 默认是作为 Apache 的一个模块运行的,启用 event_mpm 则会通过 php-fpm 处理 PHP 站点,那也简单啊,禁用模块加载 PHP 启用 PHP-fpm 就好了撒。

遂注释掉 15-php.conf 的LoadModule php7_module modules/libphp7.so(后来发现不注释也行,因为它的调用条件为非 PHP5 和 prefork),然后systemctl start php-fpm就好了撒,简单难不倒我。

坑 3:PHP-FPM

然后再访问 info.php 发现直接变成下载文件了 23333,这个问题倒是清楚为 Apache 未启用 PHP 后端功能直接返回 PHP 文件,不应该啊,难不成 PHP-fpm 模块也有问题?再去搜索,发现 Apache 连接 PHP-fpm 还需要自行配置的,依照某篇 CSDN 文章(翻了好多都是这样配置的,也不知道从哪里抄的)进行了如下配置

1. 修改php-fpm配置文件(etc/php-fpm.d/www.conf)
user = nobody
group = nogroup
listen = 127.0.0.1:9000
listen.owner = nobody
listen.group = nogroup
listen.mode = 0666
pm = dynamic

2. 修改vhost配置文件
ProxyRequests Off
ProxyPassMatch "^/(.*\.php(/.*)?)$" "fcgi://127.0.0.1:9000/usr/share/htdocs/$1"

再重启 apache 和 php-fpm,访问 info 站点发现报错变成了 503,说明方法似乎行之有效(?),又翻看了一下日志,报错变成了连接 php-fpm 失败:

[Thu Feb 03 09:22:34.580738 2022] [proxy:error] [pid 922507:tid 140666578851584] (111)Connection refused: AH00957: FCGI: attempt to connect to 127.0.0.1:9000 (*) failed
[Thu Feb 03 09:22:34.580774 2022] [proxy_fcgi:error] [pid 922507:tid 140666578851584] [client 222.133.217.243:64293] AH01079: failed to make connection to backend: 127.0.0.1

妈卖批!怎么连接本地服务还能出现错误呢!算了,这 HTTP/2 我不开也罢了。光速把配置文件改成原来的然后睡觉去了。睡醒思来想去还是觉得有些许遗憾,算了开电脑继续搞!小爷就不信了搞个 HTTP/2 都能难倒,这一次长了个心眼,既然国内的都是同质教程抄来抄去那就去看看国外教程好了,遂在 bing 国际版检索“how can i link php-fpm with apache in centos”,果然依照第一篇文章(How to Install Apache with PHP-FPM on CentOS 8 – TecAdmin)配置成功!

具体操作

1. 修改MPM(etc/httpd/conf.module.d/00-mpm.conf)
# LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
LoadModule mpm_event_module modules/mod_mpm_event.so

2. 修改php-fpm站点配置(etc/php-fpm.d/www.conf)
; listen = 127.0.0.1:9000
listen = /run/php-fpm/www.sock
user = apache
group = apache
listen.allowed_clients = 127.0.0.1
listen.owner = apache
listen.group = apache
listen.mode = 0660
pm = dynamic

3. systemctl reload php-fpm
4. 修改虚拟站点配置
# Proxy declaration
<proxy quot="quot">
# we must declare a parameter in here (doesn't matter which) or
# it'll not register the proxy ahead of time
ProxySet disablereuse=off
# Note: If you configure php-fpm to use the "pm = ondemand"
#then use "ProxySet disablereuse=on"
</proxy>;
<filesmatch php="php">
SetHandler proxy:fcgi://php-fpm
</filesmatch>
5. systemctl reload httpd