packagist.JPの現状について(2015年12月)

Posted by Hiraku on 2015-12-29

私が個人的に運営している packagist.JP というサイトがある。PHPの実質的なパッケージリポジトリである https://packagist.org のミラーサイトであり、日本付近でのcomposerコマンドの速度向上を目的としたものだ。

2015年12月に、@yudsuzukさんにこのミラーサイトを取り上げていただき、その影響か以前より少しアクセスが増えた。ありがたいことです。

【PHP】たった1行コマンドを入力するだけでComposerを劇的に速くする方法【アジア圏限定】 - $yuzu->log();

ただ、個人運営のサイトということで、使ってよいのか、信頼して良いのか不安に思う人も多いと思う。というわけで現状のステータスをなるべく率直に書いておく。

packagist.jpの概要

去年のアドベントカレンダーにまとめたのでそちらを参照のこと。
packagist.orgのミラーサーバを立ててcomposer updateを18倍速くする #packagist - Qiita

なお、composer.lockがある状態からのcomposer install実行では影響がないので、Travis-CI上でのビルドが遅いからとpackagist.jpミラーを使っても意味は無い。この点は別の高速化方法を考えているところ。

予算

packagist.jpは特に広告も貼っておらず、お金になる要素はない。 毎月私の財布から2000円程度が消え続けている。ボランティアのつもりだ。まあ勉強にはなっているけれど、それぐらいだな。

packagist.JPの構成

クローラー兼WebサーバーのさくらVPS1台と、それの手前にCDNとしてCloudFlareを挟んでいる。geoipなどでpackagist.jpドメインを調べるとカリフォルニアや香港が出てくるが、CloudFlare側が見えているからだ。 CDNの威力により、別に日本以外でもそこそこ速いんじゃないかと思う。 ヨーロッパならオリジナルのpackagist.orgで十分だと思うけど、jpミラーの設定をしていても遅くなるわけではない。(たぶん。実測したことがないので遅かったら教えて下さい)

packagist.orgとの同期はcronで2分おきに実行している。以前は一日一回としていたのだが、クロール中の動作保証が取れたのと、差分だけの同期によって一回あたり1分以内に終わるようになったため、頻度を上げた。

クローラーはPHPで書いたけれど、サーバーにはcli版のPHPしかインストールしておらず、apache版やFPMは無効化してある。

Webサーバー(nginx)で配信しているのはダウンロードしてきた静的なJSONだけ。しかもダウンロード時にgzip圧縮も行ってしまい、nginxはgzip_staticモジュールを使っているため、配信時にCPUは殆ど使わないようになっている。

さくらVPSなのはSSDプランが安く転送量による課金がないこと、何より日本にサーバーがあることから。CDNとしてCloudFlareを選択しているのは、単に使用料が無料だから。

安上がりに作ってはいるけれど、あるとき突然日本のPHPerが全員同時にcomposer updateコマンドを打ち込んだとして、負荷が直撃するのはオリジンではなくCloudFlareの方だ。

少なくとも、アクセスが集中して死ぬことないと思っている。そもそも、composerは極力packagistにリクエストしないようにデザインされているというのもある。

冗長化について

同じスペックのVPSをもう一台用意してあって、裏で1台目と常に同期し続けるようにしている。

ただ、ロードバランサーを挟んで2台が同時に外に公開されるようにはしていない。 2台ともが同じようにpackagist.orgをクロールすると、微妙に時間がずれてしまって、ダウンロードしたJSONファイルに差分が出てしまうおそれがある。

ずれがある状態で、1台目と2台目をcomposerが交互にアクセスしてしまったら、足りないjsonファイルが発生してcomposer updateは失敗してしまうだろう。

そんなわけで、packagist.orgをクロールするのは1台目、その1台目を2台目がクロールするという直線の同期系統にしている。

もし1台目が何らかの原因で死亡したら、CloudFlare側で古いキャッシュファイルを配信し続けてくれる機能があるので、そちらで何とかなる。 1台目と2台目の切り替えは私の手動である。(ただし、一度もやったことはない)

同期が止まることより、リポジトリとして不整合が起きてしまいcomposerコマンドが役に立たなくなることの方がダメージが大きいので、こんな温度感にしている。

これより更に冗長化をまじめに考えると、クローラーとWebサーバーを分割するなど大掛かりになってしまうので、このぐらいがバランスかなと思っている。

同期中の整合性

packagistをクロールしている最中に、配信しているJSONファイルがおかしくなるような仕様だったら、ミラーサイトは役に立たない。もちろん考慮してある。

packagistが配信しているjsonファイルは packages.json → p/provider-xxxx$HASH.json → p/VENDOR/PACKAGE$HASH.json という3段階のリンクをたどることで参照していっている。

packages.jsonが更新されないかぎりはリポジトリが更新されたようには見えないので、全部同期が終わってからpackages.jsonを書き換えることで、同期中に整合性が取れるようにしている。

また、公式サイトで提供している各ファイルのsha256値を使ったチェックはクロール時に毎回、全ファイルに対して行うようにしているので、整合性の取れたスナップショットだけが公開されている。

クローラーのつらみ

最初にクロールのスクリプトを作ったとき、一晩かけて長時間クロールしていたら、ある時点からダウンロードが失敗するのが常だった。 これは、packagist.orgのデータは日々更新されており、古いJSONファイルは破棄されて参照できなくなることが原因である。古いファイルはあまり長期間保存されておらず、せいぜい半日で消えているようだった。(現在は変わっているかもしれないがよく知らない)

クローラーは整合性の取れているスナップショットを取得する必要があるため、データが更新されていようがスナップショットの時点でのファイルを全部取ってこなければならない。

クロールはsleepを入れながらゆっくり行うのが礼儀…そんなふうに最初は思っていたわけだが、そうも言ってられなくなった。ゆっくりダウンロードしていたら半日程度では同期が終わらない。

なので、4並列かつKeep-Alive、一つのコネクションが空いたら即座に使いまわして次のダウンロードを始める、みたいなコードを書いて、全力でクロールすることにした。お陰でコードが結構汚くなってしまった。PHPはこういう仕事が向いていない。

それでも初回は結構時間がかかるので、2分おき更新を実現できているのは差分更新だけ行っていることによるところが大きい。

ちなみにpackagist.jpは負荷的にも速度的にも余裕があるので、ミラーを作りたいならまずpackagist.jpを100並列ぐらいでクロールしてコピーしておき、その状態からpackagist.orgにミラー元を切り替える、という手順をオススメする。いきなり2分おきでcron起動すると、前のミラーリングが終わってなくて、うまく動かないはずだ。

合法性

同期しているjsonファイルはcomposerが日々の操作でダウンロードするものと全く同じものだ。だからコピーすることに違法性はないと思っている。問題があるとすれば再配布しているところだろう。

packagist.orgには探したけれどTerms of Serviceなどのページがないので、メールでお伺いを立てているところ。(返事がまだない)

この点は何か進捗があったらお伝えする。

ちなみに並列ダウンロードを入れるタイミングでクローラーのUser-AgentをクローラースクリプトのURLにしたのだが、今のところ特にお叱りの連絡は受けていない。

packagist公式のミラーサイト作成ソフトウェアと言えばToranProxyだが、これはOSSではなく、有料のライセンスを買わないと複数デベロッパーで共有できないとあるので、packagist.jpではToranProxyを一切使わずに作ってある。(ソースを読んで、自分で作った方がいいものになりそうと思ったというのもある)

Toranを使っている中華系ミラーを見つけたこともあるけど、よい子は真似しないように。

信頼性

ライブラリのリポジトリというのは信頼性がすごく重要だ。 ”phpunit/phpunit”をインストールして、phpunitコマンドを打ち込んだら、実は偽物のパッケージがインストールされてしまい、いきなりカレントディレクトリをrm -rfされた、なんてことがあったら嫌だろう。

“phpunit/phpunit”は本当にphpunitコマンドがインストールされる、というのが保証されなければならない。これは各OSやLinuxディストリビューションのソフトウェアリポジトリが腐心している部分でもある。

ミラーサイトはorgからコピーを作っているということで信頼性はどうしても劣ってしまう。 運営の私がjsonファイルをそのままコピーしていると、どうやって証明したら良いのか。JSONに勝手に改変を行う極悪人かもしれないではないか。

一方で、じゃあpackagist.org自体が信頼できるのかというと、特に登録に審査があるわけでもなく、PHP公式のサイトでもないので、信頼性はどっこいどっこいなのかもしれない。きっと不審なライブラリがいっぱい登録されていると思う。

私はよい答えを持ち合わせていない。せいぜい、スクリプトやサーバーのセットアップ手順書を公開して、信じてもらうしかない。

なお、HTTPS版も実はあって、 https://packagist.jp が使えるようになっている。平文が信用ならないならこちらをセットしてもよい。(ただし証明書はCloudFlare付属のやつなので、もしかしたら正常に使えないかもしれない。)

最後に

packagist.jpを作ったのは一年ほど前だけど、今まであまり宣伝してこなかった。

この理由は自分が使う分には困っていなかったことと、責任を負いたくなかったからだ。

しかしながら、使ってくれている人もいるようだし、せめて現状を詳らかにすることで多少は信頼を得られるのではないかと思い、ここにまとめた。

今のところ以上である。使ってくれて構わないし、胡散臭いと思ったら使わなければいい。

まあ、自分はcomposer updateの度に10分15分待つとか死んでも嫌だし、本家が速くならないかぎりは使い続けます。

PHPの最新記事