プロフィール
しらせ(HN)
プロフィール
とあるIT企業のインフラエンジニア。プライベートでは開発もちょっとやります。
※本ブログの内容はすべて個人の見解であり、所属する企業とは関連ありません。
カテゴリ別
内部リンク
相互リンク
Twitter
来訪
423459 [合計]
162 [今日]
479 [昨日]
Powered by
Powered by AWS Cloud Computing

ByProduct - FukuSanButsu

ふくさんぶつBlog

社内インフラエンジニアの自宅からはじまるIT
自宅のPCに向き合いながら気づいたことや個人的な体験をまとめいます


【ブログ】EC2上のWebサーバをいまさらHTTP/2に移行した話

Date:2021/07/18
Update:2021/07/23

Category:ブログ


お疲れ様です。
しらせです。

先日、毎月恒例となっているEC2サーバ群のメンテナンスをしている時に、
以下のような警告がhttpdのerror_logにガッツリ出ていることに気づきました。

[Sun Jul 18 03:26:02.305324 2021] [http2:warn] [pid 2799] AH10034: The mpm module (prefork.c) is not supported by mod_http2. The mpm determines how things are processed in your server. HTTP/2 has more demands in this regard and the currently selected mpm will just not do. This is an advisory warning. Your server will continue to work, but the HTTP/2 protocol will be inactive.

前はこんなの出てなかったような?
と、思いながら調べていると、どうやらhttdpdがMPM(*1)で動いてないなくて、HTTP/2に対応していないことを示すものでした。

そんな馬鹿な?
という事でChromeの開発者ツールで使っているプロトコルを見てみると、、、

確かにHTTP/1.1でした。。。

最近ではQUICの話も出てきていて、早く使いたいなぁなんでお思っていた矢先に。
てっきり、最近のhttpdはデフォでHTTP/2で動いているものだと思い込んでいたので自分の無知にショックでした。

ということで、
EC2上でhttpdとphp74/php80で動いているWebサーバをさっさとHTTP/2に変えようと(いまさら)頑張った話です。

(参考*1)マルチプロセッシングモジュール (MPM) - httpd.apache.org
https://httpd.apache.org/docs/2.2/ja/mpm.html

もくじ

現状確認

まずは現状をしっかり確認するところから。

Chromeの開発者ツールで確認しても確かにHTTP1.1で動いているようです。

本番サーバも自宅の検証用マシンも全て同じ結果でした。

対応方法を調べる

設定で簡単に修正できれるならさっさと直しちゃおうと思っていました。

ところが調べてみるとちょっとすぐには直せなそうな感じでした。(私の知識不足的な意味で)

ざっと調べた限りでは、主な考慮点は以下の通りでした。

  • nghttp2かmod_http2が必要
  • mod_phpからphp-fpmへの変更が必要
  • httpd.confを修正する必要がある

検証環境でテスト

手っ取り早くテストしたいならHyper-V。
CentOS7で適当にマシンを作って、本番で動いているEC2インスタンスから必要な情報を物故抜いて動かします。

AWSのEC2インスタンスに慣れてしまうと、1から環境を作るのが億劫になりますね。

epel、remi、ius入れて、、依存関係を解決して、remiからphp系の各種パッケージをインストール。
iusからhttpdを入れて、、、面倒だ。

この後詳説しますが、Chromeの開発者ツールから接続時のプロトコルをチェックできるのですが、HTTP/2にするためにはいろいろと条件があるみたいです。

最終的にはProtocolが"h2"になるように目指します。
※画像は実施後のもの。

手元の検証環境はの通りです。

  • OS
    CentOS Linux release 7.9.2009 (Core)
  • Web
    httpd24u 2.4.46 @ius
  • PHP
    7.4.21 @remi-php74

検証環境の構築

epel , remi , ius インストール

# yum install epel-release
# yum -y install "http://rpms.famillecollet.com/enterprise/remi-release-7.rpm"
# yum install -y "https://repo.ius.io/ius-release-el7.rpm"

Nghttp2(HTTP/2コアエンジン)のインストール

# yum --enablerepo=epel -y install nghttp2

mime.typesとBrotli(ブロートリ)のインストール

# yum -y install mailcap
# yum --enablerepo=epel -y install brotli

(参考)【Linuxサーバー構築(CentOS 7)】最新バージョンのApacheのインストールと設定 (HTTP/2 & SSL対応) 2019年12月現在 - iwatani.tv
https://iwatani.tv/linux-server/centos7-apache/

httpdとmod_sslインストール

# yum --disablerepo=base,epel,extras,updates --enablerepo=ius install httpd
# yum --disablerepo=base,epel,extras,updates --enablerepo=ius install mod_ssl
# systemctl enable httpd

その他不足しているパッケージのインストール

# yum install libxslt* autoconf libtool openssl-devel libonig* libsodium libgd libraqm gcc* libgd

※とりあえず動かしたくて適当に入れたので実際のコマンドとは異なります。

phpインストール

# yum -y install php php-devel php-mbstring php-pdo php-xml php-cli php-pear php-gd php-fpm --disablerepo=* --enablerepo=remi-php74

php-fpmインストール

# yum --enablerepo=remi-php74 -y install php-fpm

php-fpm自動起動

# systemctl start php-fpm
# systemctl enable php-fpm

mpmの有効化とprefork無効化

# vi /etc/httpd/conf.modules.d/00-mpm.conf
---
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so #←コメントアウト
LoadModule mpm_event_module modules/mod_mpm_event.so #←コメント外す ↓最下行に以下を追加


StartServers 3
MinSpareThreads 24
MaxSpareThreads 48
ThreadsPerChild 64
MaxRequestWorkers 128
MaxConnectionsPerChild 0

SetHandler "proxy:fcgi://127.0.0.1:9000"


---

(参考)CentOS7 環境設定 (Apache2.4 EventMPM + php-fpm + php7.4) - qiita.com
https://qiita.com/daichi_pd/items/1d9b4c8bef2579abc670

preforkモジュール無効化

# vi /etc/httpd/conf.modules.d/15-php.conf

※中身を全てコメントアウトした

php-fpmの拡張子変更

# vi /etc/php-fpm.d/www.conf
---
security.limit_extensions = .php .html .htm

※.htmlとか.htmとかでもphpを動かしたいので。

httpdとphp-fpmの相互依存関係の設定

# vi /etc/systemd/system/multi-user.target.wants/httpd.service
---
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Requires=php-fpm.service #←追加
---

# vi /etc/systemd/system/multi-user.target.wants/php-fpm.service
---
[Unit]
Description=The PHP FastCGI Process Manager
After=syslog.target network.target
Requires=httpd.service #←追加
---

あと、Chroemの開発者ツールで"h2"にするためには暗号化通信が必須になります。

80/TCPでアクセスしてもh2にはならずHTTP/1.1の状態のままになってしまいます。
httpd.confを弄ってh2cとHTTP/1.1を消してh2だけにしてもダメです。

そのためサーバの証明書が必要なんですが検証用に用意するのが面倒なので自己署名証明書で代用しました。

動きました。
Chromeで確認すると全ての通信がh2になっています。

EC2インスタンスを直す

だいたい要領を掴めたのでAWSの本番環境であるEC2インスタンスのほうを修正します。

本番環境はいくつかありますが主に以下の通りです。
php本体をremi-safeから持ってきてしまっている点ご了承ください。

blog
  • OS
    Amazon Linux 2
  • Web
    httpd 2.4.48 @amzn2-core
  • PHP
    7.4.21 @remi-safe
websona ※こちらを最初に片付けました
  • OS
    Amazon Linux 2
  • Web
    httpd 2.4.48 @amzn2-core
  • PHP
    8.0.8 @remi-safe

事前準備

いきなりEC2インスタンスを弄ってぶっ壊しても嫌なので、スナップショットを作成の上、事前にセキュリティグループを修正して自宅回線からのみアクセスを許可としておきます。

中途半端に変な状態で公開されても嫌なので。。

現状確認

httpd

httpdはamzn2-coreから2.4.48が入っています。

あとnghttp2の代わりにmod_http2がすでに入っていますね。素晴らしい。
現在のhttpdの動作も確かにpreforkになっています。

$ yum list installed | grep http
generic-logos-httpd.noarch 18.0.0-4.amzn2 @amzn2-core
httpd.x86_64 2.4.48-2.amzn2 @amzn2-core
httpd-filesystem.noarch 2.4.48-2.amzn2 @amzn2-core
httpd-tools.x86_64 2.4.48-2.amzn2 @amzn2-core
libnghttp2.x86_64 1.41.0-1.amzn2 installed
mod_http2.x86_64 1.15.19-1.amzn2.0.1 @amzn2-core
python-ndg_httpsclient.noarch 0.3.2-1.el7 @epel

$ httpd -V
~~~割愛~~~
Server MPM: prefork
threaded: no
forked: yes (variable process count)
~~~割愛~~~

php

phpはremi-safeから8.0.8が入っていました。
同じようにphp-fpmもインストールしておきました。

$ yum list installed | grep php
oniguruma5php.x86_64 6.9.7.1-1.el7.remi @remi-safe
php80-php.x86_64 8.0.8-1.el7.remi @remi-safe
php80-php-cli.x86_64 8.0.8-1.el7.remi @remi-safe
php80-php-common.x86_64 8.0.8-1.el7.remi @remi-safe
php80-php-devel.x86_64 8.0.8-1.el7.remi @remi-safe
php80-php-fpm.x86_64 8.0.8-1.el7.remi @remi-safe ←php-fpm
php80-php-mbstring.x86_64 8.0.8-1.el7.remi @remi-safe
php80-php-pdo.x86_64 8.0.8-1.el7.remi @remi-safe
php80-php-pear.noarch 1:1.10.12-7.el7.remi @remi-safe
php80-php-process.x86_64 8.0.8-1.el7.remi @remi-safe
php80-php-sodium.x86_64 8.0.8-1.el7.remi @remi-safe
php80-php-xml.x86_64 8.0.8-1.el7.remi @remi-safe
php80-runtime.x86_64 1.0-3.el7.remi @remi-safe

httpdもphpも設定だけで動作できそうです。

設定変更

php80-php-fpmの自動起動

# sudo systemctl start php80-php-fpm
# sudo systemctl enable php80-php-fpm

mpmの有効化とprefork無効化

# sudo vi /etc/httpd/conf.modules.d/00-mpm.conf
---
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so #コメントアウト
LoadModule mpm_event_module modules/mod_mpm_event.so #←コメント外す ↓最下行に以下を追加


StartServers 3
MinSpareThreads 24
MaxSpareThreads 48
ThreadsPerChild 64
MaxRequestWorkers 128
MaxConnectionsPerChild 0

SetHandler "proxy:fcgi://127.0.0.1:9000"


php-fpmの拡張子変更

# sudo vi /etc/opt/remi/php80/php-fpm.d/www.conf
---
security.limit_extensions = .php .html .htm

php-fpmチューニング

# sudo vi /etc/opt/remi/php80/php-fpm.d/www.conf
---
pm.max_children = 15
pm.max_spare_servers = 15
pm.max_requests = 512

私の環境とはOSのバージョンが異なりますが、EC2インスタンスがt2.microのためメモリへの労りが必要です。
(参考)CentOS 6.5:nginx,php-fpm環境が「重い」と感じる場合の対応 - blog.offline-net.com
https://blog.offline-net.com/2015/05/09/centos-65-nginx-php-fp%EF%BD%8D-memory-tunables/

依存関係

# sudo vi /etc/systemd/system/multi-user.target.wants/httpd.service
---
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Requires=php-fpm.service #←追加
---

# sudo vi /etc/systemd/system/multi-user.target.wants/php80-php-fpm.service
---
[Unit]
Description=The PHP FastCGI Process Manager
After=syslog.target network.target
Requires=httpd.service #←追加
---

動作テストとリリース

設定は以上で完了です。
systemctl restart httpdやphp80-php-fpmを実行して、エラーが出なければ動作しているはずです。

httpdの動作モードも変わっていることが確認できます。

# httpd -V
~~~割愛~~~
Server MPM: event
threaded: yes (fixed thread count)
forked: yes (variable process count)
~~~割愛~~~

この時何度リロードしてもHTTP/1.1から変わらない場合は、ブラウザのキャッシュが効いている可能性があります。
ブラウザをシークレットモードで開くなどすると変わります。

変更前と変更後のtopの結果です。
左がHTTP/1.1の以前のもので、右がHTTP/2に変更した直後です。1.1の方はしばらく再起動していなかったので比較としてはNGですね。

最後に/var/logを確認したり細かい動作も見ましたが、大きな問題はなさそうなのでリリースします。
最後にセキュリティグループを戻して公開です。

正直、早くなったかどうかは微妙です。
それでもやっとHTTP/1.1から脱却できたことに達成感がありますね。

その他、参考にさせて頂いたサイトを共有させていただきます。
(参考) 【図解/apache】MPM prefork/worker /event (イベント駆動)の違い~CPUコアの使い方~ - milestone-of-se.nesuke.com
https://milestone-of-se.nesuke.com/sv-basic/linux-basic/apache-mpm-prefork-worker-event/
(参考)CentOS 7.4 で手軽になった HTTP/2 対応 Apache のインストールメモ - blog.apar.jp
https://blog.apar.jp/linux/8339/#toc7

以上
おつかれさまでした。



View:516 この記事をツイート!