はじめに
先日6月1日、OSSクローラーであるApache ManifoldCFの新しいリリースApache ManifoldCF 2.25が発表されました。
今回リリースの目玉機能はクロールの性能改善で、弊社がOSSコミュニティにコントリビュートしたパッチ2点を取り込んでいただきました。
このブログ記事では、性能改善の内容およびユースケースや適用方法をご説明いたします。
Apache ManifoldCFとは
Apache ManifoldCFは、インターネットやイントラネットの様々なサーバに保管されている文書ファイルやWebページなどコンテンツを収集し、それを検索エンジンに送るためのJavaで書かれたOSSクローラーです。
Apache ManifoldCFはファイルパーミッションなどセキュリティ情報もきめ細かく取得できるため、企業内検索システムでは不可欠な役職や所属部署によるセキュリティを考慮した検索機能が実現可能です。
Apache ManifoldCFのアーキテクチャをドキュメントから抜粋します。
Apache ManifoCFは以下のコンポーネントから構成されています。
- 管理データベース: ManifoldCFのすべての設定およびステータス情報を保持する場所です。通常は PostgreSQLを使用します。
- 同期ディレクトリ: ManifoldCFのさまざまなプロセス間のアクティビティを調整する場所です。
- エージェントプロセス: 実際ドキュメントをクロールして取り込むプロセスです。
- クローラーUI: ユーザーがクローラーを設定および制御するための操作を行うUIです。
- 権限サービス: 指定されたユーザー名の認可トークンを取得するためのサービスです。
- APIサービス: REST APIリクエストに応答するためのサービスです。
ManifoldCFのインストール・設定・クロール実行など詳細に関しては、弊社の別のブログ記事Apache ManifoldCF -オープンソースクローラのご紹介-をご参照ください。
Apache ManifoldCF 2.25の性能改善1: ホップカウントを完全無効化できるように機能拡張
ホップフィルターを使用しない環境において、本機能を使用するとホップカウント情報をManifoldCFの管理データベースに記録しないため、クロール性能が向上しかつデータベースのディスク使用量を削減できます。
JIRAチケット
https://issues.apache.org/jira/browse/CONNECTORS-1747
GitHubコミット
https://github.com/apache/manifoldcf/commit/510e6b862b5a0454d578825bd8f04089956b736b
何が問題だったか
ManifoldCFはクロール対象のWebサイトに対して、サイト内のページ同士をつなぐ内部リンクを辿りながら関連ページをクロールしてくれます。
ドキュメントのホップカウントとは、該当ページからシードベージ(一番先頭の開始ページ)までの距離を指しており、ManifoldCFではホップフィルター機能を使って、ホップカウントによるクロール対象ページの絞り込みが可能です。
ホップカウントによる制限を設けず、全ての内部リンクを辿りながらドキュメントを収集することも可能です。ジョブの設定画面の"Hop Filters"タブで、ホップカウントモードを"keep unreachable documents, forever" に設定すると、ホップフィルターによる絞り込みは行われません。
ただし、今まではホップフィルターを使用しない場合でも、管理データベースには内部リンクによるホップカウント情報が全て記録されていました。内部リンクが大量に存在するサイトにおいて、クロール時にデータベースへホップカウント書き込みが頻繁に発生するため、データベース負荷が高くなったり、データベースが肥大化する場合がありました。
どのように解決したか
弊社提供のパッチでは、ホップカウント処理を完全無効化できるように機能拡張しました。
設定方法は、ManifoldCF設定ファイルproperties.xmlでプロパティstorehopcountをfalseに指定します。デフォルトの設定値はtrueで、ホップカウントをデータベースに記録します。プロパティ設定を反映させるためManifoldCFの再起動が必要です。
設定例(ホップカウントをデータベースに記録しません):
<property name="org.apache.manifoldcf.crawler.jobs.storehopcount" value="false"/>
この設定により、ジョブの設定画面に"Hop Filters"タブは表示されず、クロール時にホップカウント情報がintrinsiclinkテーブルやhopcountテーブルに記録されることはありません。
パフォーマンス検証結果
内部リンクが大量に含まれているサイトに対してWebクロールを行うジョブを作成し、storehopcount=trueとstorehopcount=falseの二つの設定値それぞれに対し、ジョブの実行時間とデータベースのディスク使用量を計測・比較しました。その結果, ジョブの実行時間は半分に短縮し、データベースのディスク使用量は半分以下に削減できました。なお、二つの設定においてクロールされたドキュメント数は同じでした。
Apache ManifoldCF 2.25の性能改善2: 管理データベースPostgreSQLのクエリ最適化をよりスマートに行うように機能拡張
ManifoldCFの管理データベースとしてPostgreSQLを使用する環境において、本機能を使用するとジョブ実行途中にクロールの停滞が発生する事象を回避できる場合があります。
JIRAチケット
https://issues.apache.org/jira/browse/CONNECTORS-1746
GitHubコミット
https://github.com/apache/manifoldcf/commit/234d2f1495e83ad24415b98610fead90d90582af
何が問題だったか
ManifoldCFの管理データベースとしてPostgreSQLを使用する環境において、実行時間が1時間を超えるような長いジョブの実行途中に、クロール処理が10分以上停滞しドキュメントをまったくクロールできない事象が発生する場合がありました。この場合、ログファイルに停滞原因に関する情報は出力されませんでした。
事象発生時に、試しにPostgreSQLのANALYZEコマンドを実行しテーブルの内容に関する統計情報を更新すると、クロール性能が回復する場合がありました。よって、クロール時ManifoldCF内部で実行されるPostgreSQLのクエリが最適化されていなかったのが、パフォーマンス劣化の原因と判断しました。
どのように解決したか
弊社提供のパッチでは、よりスマートにPostgreSQLのクエリ最適化を行うように機能拡張しました。PostgreSQLプランナが最も効率の良いクエリ実行計画を決定する際に使用される統計情報を更新するため、ANALYZEの実行条件を二つ追加しました。
設定方法は、ManifoldCFの設定ファイルproperties.xmlにプロパティanalyzeatstartとanalyzeratethresholdを追加します。プロパティ設定を反映させるためManifoldCFの再起動が必要です。
- analyzeatstartプロパティ
ジョブ開始時にPostgreSQLのANALYZEを実行します。具体的には、ジョブ開始後ドキュメント処理イベントが100回発行された時点でANALYZEが発行されます。デフォルトの設定値はfalseで、ジョブ開始時ANALYZEを実行しません。
設定例(ジョブ開始時ANALYZEを実行します):
<property name="org.apache.manifoldcf.db.postgres.analyzeatstart" value="true"/>
- analyzeratethresholdプロパティ
クロール性能が低下した場合のみ、PostgreSQLのクエリ最適化を試みます。具体的には、ドキュメントの処理性能(秒間処理されるイベント数)が設定された閾値を下回ったら、ANALYZEが発行されます。デフォルトの設定値は0で、クロール性能のチェックは行われず、従来のanalyzeプロパティにより設定されたANALYZE実行頻度に従って、対象テーブルに対してANALYZEが発行されます。
設定例(秒間処理されるイベント数が10を下回るとANALYZEが発行されます):
<property name="org.apache.manifoldcf.db.postgres.analyzeratethreshold" value="10"/>
[注意] 上記二つのプロパティの前提として、従来のanalyzeプロパティを使って対象テーブルにANALYZEの実行頻度を指定する必要があります。analyzeプロパティで設定されたテーブルのみ、新しく追加された上記プロパティの対象となります。設定方法は、ManifoldCFの設定ファイルproperties.xmlにanalyzeプロパティを追加します。
設定例(ドキュメント処理イベントが2000回発行されるたびにANALYZEが実行されます):
<property name="org.apache.manifoldcf.db.postgres.analyze.intrinsiclink" value="2000"/>
<property name="org.apache.manifoldcf.db.postgres.analyze.hopcount" value="2000"/>
<property name="org.apache.manifoldcf.db.postgres.analyze.repohistory" value="2000"/>
<property name="org.apache.manifoldcf.db.postgres.analyze.carrydown" value="2000"/>
<property name="org.apache.manifoldcf.db.postgres.analyze.jobqueue" value="2000"/>
<property name="org.apache.manifoldcf.db.postgres.analyze.prereqevents" value="2000"/>
パフォーマンス検証結果
実行時間が長いジョブが実行途中に突然クロールが止まる事象は発生しませんでした。なお、クロール性能が一時的に低下した場合、PostgreSQLのクエリ最適化が行われクロール性能が回復することを確認できました。
おわりに
Apache ManifoldCF 2.25における性能改善について説明しました。ManifoldCFを使ってWebサイトをクロールする際、性能が気になる方はぜひ新しい機能をお試しください。本機能が皆様のご業務の一助となり、Apache ManifoldCFコミュニティに少しでも貢献できたら幸いです。