fess-crawlerにPostScriptテキスト抽出機能を追加

fess-crawlerに、PostScript(.ps)ファイルからテキストを抽出するPsExtractorを追加しました。これにより、Fessのクロール対象としてPostScriptファイルも扱えるようになります。

PostScriptとは

PostScriptはAdobe Systemsが開発したページ記述言語で、印刷やDTPの分野で広く使われてきたフォーマットです。PostScriptファイルにはテキスト描画命令が含まれていますが、プログラミング言語としての側面もあり、テキストの抽出は単純ではありません。

PsExtractorの仕組み

PsExtractorは、PostScriptのshow系オペレータを解析してテキストを抽出します。対応しているオペレータは以下の通りです。

オペレータ説明
show基本的なテキスト描画
ashow文字間隔調整付きテキスト描画
widthshow特定文字の幅調整付きテキスト描画
awidthshowashow + widthshow の組み合わせ
kshowカーニングプロシージャ付きテキスト描画
xshow個別X座標指定のテキスト描画
yshow個別Y座標指定のテキスト描画
xyshow個別XY座標指定のテキスト描画

文字列リテラルとしては、括弧形式の文字列((Hello World))と16進文字列(<48656C6C6F>)の両方に対応しています。括弧形式の文字列では、エスケープシーケンス(\n\t、8進数など)やネストされた括弧も正しく処理されます。

DI設定

extractor.xmlpsExtractorコンポーネントを登録し、application/postscript MIMEタイプにマッピングしています。

制限事項

現在の実装では以下のケースには対応していません。

  • ループやプロシージャによる動的なテキスト生成
  • フォントエンコーディングの再定義
  • バイナリエンコードされたPostScriptファイル

静的にshow系オペレータで描画されるテキストの抽出に特化した実装となっています。

テスト

12件のテストケースを作成し、基本的なテキスト抽出、16進文字列、エスケープシーケンス、ネストされた括弧、空コンテンツ、各種show系オペレータなどの動作を検証しています。

変更の詳細はPR #140を参照してください。

FessのインデックスエクスポートでJSON形式をサポート

Fessのインデックスエクスポート機能で、従来のHTML形式に加えてJSON形式での出力をサポートしました。Strategyパターンを導入することで、エクスポート形式を柔軟に切り替えられるようになっています。

背景

Fessにはインデックスに保存されたドキュメントをファイルとしてエクスポートする IndexExportJob があります。これまではHTML形式でのみエクスポートが可能でしたが、データ連携や後処理の用途ではJSON形式の方が扱いやすいケースがあります。そこで、エクスポート形式を選択できるように拡張しました。

変更内容

Strategyパターンの導入

エクスポート形式の処理をStrategyパターンで設計し、IndexExportFormatterインターフェースを導入しました。

public interface IndexExportFormatter {
    String getFileExtension();
    String getIndexFileName();
    String format(Map<String, Object> source, Set<String> excludeFields);
}

このインターフェースを実装する形で、HTML用の HtmlIndexExportFormatter とJSON用の JsonIndexExportFormatter を用意しています。

HTML形式(既存)

HtmlIndexExportFormatter は従来の動作と同じく、ドキュメントをHTML形式で出力します。タイトルやコンテンツはHTMLの構造に配置され、その他のフィールドは <meta> タグとして出力されます。

JSON形式(新規)

JsonIndexExportFormatter はドキュメントをJSONオブジェクトとして出力します。ネストされたコレクションやマップにも対応しており、適切なJSONエスケープ処理が行われます。

設定方法

fess_config.properties に以下の設定を追加します。

index.export.format=html

デフォルトはHTML形式です。JSON形式に変更するには以下のように設定します。

index.export.format=json

また、ジョブのスクリプトで format() メソッドを使って指定することもできます。

return container.getComponent("indexExportJob")
    .format("json")
    .execute();

format() メソッドで指定した場合は、設定ファイルの値よりも優先されます。

出力例

同じドキュメントをそれぞれの形式でエクスポートした場合の例です。

HTML形式

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>サンプルページ</title>
<meta name="fess:url" content="https://example.com/page">
<meta name="fess:host" content="example.com">
</head>
<body>
ページの本文テキスト
</body>
</html>

JSON形式

{
  "title": "サンプルページ",
  "content": "ページの本文テキスト",
  "lang": "ja",
  "url": "https://example.com/page",
  "host": "example.com"
}

ファイルの拡張子

エクスポートされるファイルの拡張子も、選択したフォーマッターに応じて自動的に切り替わります。

形式拡張子インデックスファイル名
HTML.htmlindex.html
JSON.jsonindex.json

まとめ

Strategyパターンの導入により、エクスポート形式の追加が容易になりました。既存のHTML形式はデフォルトとしてそのまま利用でき、JSON形式が必要な場合は設定を変更するだけで切り替えられます。この変更はFess 15.5.0で利用可能になる予定です。

FessにCPU負荷ベースのリクエスト制御機能を追加

以前の記事でFessにIPベースのリクエスト制限機能を追加したことを紹介しましたが、今回はOpenSearchのCPU使用率に基づいてリクエストを制御する機能を追加しました。OpenSearchの負荷が高い場合にHTTP 429(Too Many Requests)を返すことで、過負荷状態でのサービス品質の低下を防ぎます。

概要

この機能は、OpenSearchクラスタのCPU使用率を定期的に監視し、設定した閾値を超えた場合にリクエストを拒否するサーブレットフィルター(LoadControlFilter)として実装されています。Web画面へのリクエストとAPIリクエストで独立した閾値を設定でき、デフォルトでは無効(閾値100%)になっています。

仕組み

監視の流れ

  1. バックグラウンドの監視タスク(LoadControlMonitorTarget)がOpenSearchのノード統計APIを定期的に呼び出し、各ノードのCPU使用率を取得
  2. 全ノードの中で最大のCPU使用率をSystemHelperに記録
  3. リクエストが来た際に、LoadControlFilterが現在のCPU使用率と閾値を比較
  4. 閾値を超えている場合はリクエストを拒否

制御対象外のリクエスト

以下のリクエストは制御対象外となります。

  • 管理画面(/admin)へのアクセス
  • エラーページ(/error)へのアクセス
  • ログインページ(/login)へのアクセス
  • 静的リソース(CSS、JS、画像、フォントなど)

リクエスト拒否時の動作

  • Web画面: ビジーエラーページにリダイレクトし、「サーバーが現在高負荷です」というメッセージを表示
  • API: ステータスコード429のJSONレスポンスを返却(Retry-After: 60ヘッダー付き)

APIのレスポンス例:

{
  "response": {
    "status": 9,
    "message": "Server is busy. Please retry after 60 seconds.",
    "retry_after": 60
  }
}

設定方法

fess_config.propertiesに以下の設定を追加します。

# Web画面のCPU閾値(%)。CPU使用率がこの値以上のときに429を返す(100: 無効)
web.load.control=100

# APIのCPU閾値(%)。CPU使用率がこの値以上のときに429を返す(100: 無効)
api.load.control=100

# OpenSearch CPU監視の間隔(秒)
load.control.monitor.interval=1

たとえば、APIに対してCPU使用率80%以上でリクエスト制御を有効にする場合は以下のように設定します。

api.load.control=80

Web画面とAPIで異なる閾値を設定することもできます。

web.load.control=90
api.load.control=70

IPベースの制限との違い

以前追加したIPベースのリクエスト制限とは異なるアプローチの機能です。

項目IPベースの制限CPU負荷ベースの制御
制限の基準特定IPからのリクエスト数OpenSearchのCPU使用率
目的特定クライアントの過剰アクセス防止サーバー全体の過負荷防止
設定レート制限、ブラックリスト/ホワイトリストCPU閾値(Web/API独立)

両方の機能を組み合わせることで、より効果的にサーバーを保護できます。

まとめ

CPU負荷ベースのリクエスト制御機能により、OpenSearchが高負荷状態のときにFessが自動的にリクエストを制限できるようになりました。デフォルトでは無効になっているため、必要に応じて閾値を設定してください。