こちらは Perl Advent Calendar 2025 の14日目の記事になります。
昨日は @shogo82148 さんによる PerlOnJavaで遊んでみた でした。
今年は諸々の環境変更が重なり、なかなか記事を書けていませんでした。
忘れてしまう前に、自分自身の備忘も兼ねて、この話を書いておこうと思います。
今回のネタ
今年の春先に、mod_perlで動いている某WEBサービスのバージョンアップやクラウド移行などを行っていました。
約20年ほどの歴史があるサービスのため、細かいハマりどころが色々ありました。
本記事では、その中でも「実際に困った点・対応した点」を中心にメモとして残します。
2年前にも別サービスで同じような記事を書いていたのですが、そのあたりに近い感じのメモ記事になります。
主な変更点
オンプレからクラウドに移行するにあたり、以前のままだとバージョンが合わない、コンテナがビルドできないなどの問題があり、以下のような感じで移行を行いました。
※以下は OCI (Oracle Cloud Infrastructure) に移行した時点のものとなっています。
| 項目 | 変更前 (Before) | 変更後 (After) |
|---|---|---|
| インフラ | オンプレミス | Oracle Cloud |
| OS / ベースイメージ | コンテナベースイメージ CentOS 7 | コンテナベースイメージ AlmaLinux 9.4 |
| Web サーバ | Apache 1.3.42 | Apache 2.4.62 |
| Perl 実行環境 | mod_perl 1.31 | mod_perl 2.0.13 |
| Perl バージョン | Perl 5.8.8 | Perl 5.32.1 |
| DB | MySQL 4.0.30 | MySQL 8.0.41-cloud (MDS) |
| ストレージエンジン | MyISAM | InnoDB |
| CPAN モジュール | 2017 年前後のバージョンが中心 | 2025 年時点の最新版を基本採用 |
mod_perl とは?
つい先日、久々に mod_perl というキーワードがX上でちょっと賑わっていました。
平成の時代も終わり、もうすでに mod_perl をご存知ない方も増えてきていると思います。
インターネット老人会の文脈で語られることもあるかと思います。
mod_perl は2000年代前半を中心に広く使われていた、 Apache WebサーバーにPerl言語の機能を直接組み込み、Perlスクリプトを高パフォーマンスで実行できるようにするモジュールです。CGI(Common Gateway Interface)のようにリクエストごとにPerlインタプリタを起動するオーバーヘッドをなくし、PerlプログラムをApacheプロセス内で常駐させて実行するため、高速なWebアプリケーション開発を可能にします。
mod_perl と言えば @xtetsuji さんということで、
mod_perlの歴史や、 mod_perl 1系, mod_perl 2系の詳しい話、当時の情報などは以下の資料などをご覧いただくのが早いと思います。
また、先日行われた YAPC::Fukuoka 2025 では、1990年代に大流行したCGIによる掲示板の時代から、mod_perl を経て PSGI/Plack へ至る流れなどを紹介した素晴らしいセッション「Perl の生きのこり by わいとん & kobaken」がありましたので、こちらもぜひ。
それと、YAPC::Kyoto 2023で登壇された macopy さんの「デプロイ今昔物語 〜CGIからサーバーレスまで〜」もこのあたりの歴史を追体験できるので、ご興味のある方はぜひ…!
mod_perl 1 -> mod_perl 2 へアップグレード
前回の記事のシステムの場合、10年くらい前に mod_perl 2 -> PSGI/Plack 化を行っていたのですが、今回の場合はそもそも mod_perl 1 のままで長らく稼働していました。
今回は、PSGI/Plack 化は行わず、mod_perl 2 へのアップグレードを選択しました。
理由としては、歴史のあるプロダクトであるため書き換え箇所が膨大になり、
デバッグも含めた工数が読めなかったことが大きいです。
2025年の現在だと、この書き換えは AIコーディングエージェントでいい感じにVibe Codingできるのかもしれません。が、生成AIは mod_perl -> PSGI化あたりの学習自体が不足しており、結局人力でやらざるを得ない箇所も多いことも予想されます。
ただでさえ工数が無い中で、これから大きな改修を積極的に行っていくかどうかもまだ判断が難しいため、今回は安定を重視して mod_perl 2 にアップグレードすることにしました。
mod_perl 2のインストール
以前は mod_perl のインストールの時点で躓いた方も多くいらっしゃったかもしれません。
が、今回のコンテナのベースイメージにしたAlmaLinux 9などであれば、EPEL からサクッとインストールすることが可能になっています。いい時代になりました。
また、dockerで気軽にmod_perlを試してみたいという方は、新しいPerlバージョンで使えるDocker イメージを公開されています。素晴らしい…
mod_perl 1 から mod_perl2 への移行方法について
ここで細かく書いても、実際に同じような作業をされる方はあまりいらっしゃらないと思いますので詳しくは省略しますが、公式のドキュメントなどを貼っておきます。
mod_perl 1 と2で、地味に大きな変更があったりしました。
https://perl.apache.org/docs/2.0/user/porting/porting.html
https://perl.apache.org/docs/2.0/user/porting/compat.html
https://perl.apache.org/docs/2.0/api/Apache2/compat.html
MySQL 4.0 -> MySQL 8.0 アップグレード
MySQL 4.0から8.0アップグレードにあたっては、すでにいろんなところに出ているかと思いますので詳細は省きますが、例えば以下の記事に近い状況がありました。
バージョン番号が2倍になるということは、その分苦しみも2倍……
というわけではもちろんなく、それ以上に地道な作業が山ほどありました。
ある程度の人員がいるのであればMySQL 4.0を自前で管理するという方法もあるかもしれませんが、そもそもそういったリソースが無い状況であればマネージドに寄せる方が良いと判断しました。
Oracle CloudのMDS(MySQL HeatWave Database Service)に持っていくためにはMySQL 8.0に上げるのが必須となります。(近日中に 8.0 -> 8.4化も必須になります)
TIMESTAMPのフォーマット問題
MySQL 4.0でよくある違いとして、TIMESTAMPのフォーマットは YYYYMMDDHHMMSS です。
- my $timestamp = Time::Piece->strptime($self->timestamp,"%Y%m%d%H%M%S");
+ my $timestamp = Time::Piece->strptime($self->timestamp,"%Y-%m-%d %H:%M:%S");
こういうのも、そこそこあったりしました。
文字化け(というか範囲外文字列)が混入している問題
の時にもあったのですが、テーブルは ujis(EUC-JP) になっていても、必ずしもきれいなデータが入っているとは限りません。不完全なサロゲートペア文字(?)などが入っていたりすると、
Incorrect string value
のエラーでデータの移行が止まってしまいます。
というときは、一旦
STRICT_TRANS_TABLES
を外して新しいMySQLに移行した後で、
後から STRICT_TRANS_TABLES を入れるという形で不正文字が削除されて移行することができました。
URL中のダブルスラッシュ (//) 問題
こちらはApache 2.4へのアップグレードによる問題になります。
このシステムでは、ユーザが任意のURLのコンテンツを作成できる機能があり、
例えば福山雅治さんの曲で、
Revolution//Evolution
というのがあります。
途中にスラッシュが複数入っていますが、このようなURLがApache 2.4への移行で認識できないという問題がありました。
例)
https://example.com/myapp/content/Revolution//Evolution が内部的に
↓
https://example.com/myapp/content/Revolution/Evolution
として解釈されてしまう問題です。
Apache 2.4 では URL 正規化や rewrite 処理周りの挙動が 2.2 以前と変わっており、
THE_REQUEST 変数 でダブルスラッシュのようなURLを保持するようにして対応しました。
せっかくなので、AIにこのダブルスラッシュ問題を検証するリポジトリを作ってもらいました。
修正前
修正後
これで Revolution//Evolution や (//∇//) のようなURLも再現できるようになりました。。
Perl のアップグレードによる問題
Perl は 5.8.8 -> 5.32.1 にアップグレードとなったのですが、
ここでややこしい問題が発生しました。
一部のページで一定のランダムの確率で500エラーになるという問題が発生しました。
hash の順序に依存したコードが存在しており、
特定の条件下で未定義値を参照して 500 エラーになっていました。
これは Perl 5.18 から導入された Hash Randomization(ハッシュのランダム化)によるもので、そう言えばそういうのもあったなぁという感じなのですが、 5.8.8 で動いていたため、すっかり忘れた頃に顕在化してしまって、 sort keys するように対応しました。
他にも様々なバグがあったのですが、
力尽きてしまったので今回はこのくらいとさせていただきます。
まとめ
ざっくりな紹介でしたが、20年ほど続くレガシーなmod_perlのWEBサービスをバージョンアップした話の紹介でした。
今回のクラウド移行で、コストの削減も出来てまだまだ戦えるようになったのではないかと考えています。
最近でPerlで稼働しているWEBサービスの話を表で見ることが少なくなりつつあり寂しい限りですが、生成AI全盛の時代になり、人不足でちょっとした改修でもだいたいAIと相談してなんとかなりそうなところも多いかと思いますので、まだまだやれるうちは、こうした歴史のあるサービスを少しずつ現代に適応させながら繋いでいきたいところですね。

