大約一個月前,有人在我所在的 IRC 頻道中提到了 HTTP/2。由於某種原因,我從未聽說過它,而且新協定的一些功能(比如無需開啟多個 TCP 連線就能復用請求)似乎很酷。
說實話,我剛剛重寫了管理我們備份程式的 Puppet 程式碼,啟用 HTTP/2 似乎是一種轉向另一個大型專案之前有效的拖延方式。這有多難?
結果我花了大約 25 個小時來完成。坐下來穿上舒適的拖鞋,聽聽這個 HTTP/2 的故事!
當我第一次看到如何在 Apache 上啟用 HTTP/2 時,這似乎是一項非常簡單的任務。文件提到載入 http2
模組並通過如下組態檔確保新協定優先:
Protocols h2 h2c http/1.1H2Push onH2PushPriority * afterH2PushPriority text/css beforeH2PushPriority image/jpeg after 32H2PushPriority image/png after 32H2PushPriority application/javascript interleaved
這當然很容易。即使 Apache 中的所有內容都已正確設定,網站仍然使用的是 HTTP/1.1。不過,顯然我做得沒錯,因為我的網站現在傳送了一個新的 HTTP 頭:Upgrade: h2, h2c
。
在浪費了大量時間偵錯 TLS 金鑰(HTTP/2 與 TLS 1.1 不相容)之後,我終於發現問題是沒有使用正確的 Apache 多進程處理模組。
事實證明,在使用 mpm_prefork
(預設 MPM)時,Apache 不會使用 HTTP/2,因為 mod_http2
不支援它。儘管 Apache 還有兩個其他的 MPM,但只有 mpm_prefork
支援 mod_php
。突然之間,新增對 HTTP/2 的支援意味著我們將要把所有的 PHP 網站切換到 PHP-FPM。
在很長一段時間裡,一位好友一直試圖讓我相信 PHP-FPM 的優點。雖然表面上看起來很好,但我從來沒有真正試過。它看起來很複雜。常規的 mod_php
做得很好,還有其他事情需要我注意。
事實上,這次的 HTTP/2 事件是讓我鑽研它的一個契機。在我理解了 FPM 池的工作原理後,它實際上很容易設定。由於我不得不重寫我們用於部署網站的 Puppet 組態檔,我也藉此機會鞏固了一堆東西。
PHP-FPM 允許你在不同的 Unix 使用者下執行網站來增加隔離性。最重要的是,我決定是時候讓我們伺服器上的 PHP 程式碼以唯讀模式執行,並且不得不為我們的 Wordpress、Nextcloud、KanBoard 和 Drupal 範例調整一些東西來減少報錯。
過了很長時間通過 Puppet 的自動任務後,我終於能夠全部關閉 mod_php
和 mpm_prefork
並啟用 mpm_event
和 mod_http2
。PHP-FPM 和 HTTP/2 帶來的速度提升不錯,但更讓我感到高興的是這次磨練增強了我們的 Apache 處理 PHP 的能力。