パッケージマネージャーの内部構造

パッケージマネージャー (CLI) は、内部的にさまざまな Solr API を使用して、パッケージのインストール、デプロイ、および更新を行います。このドキュメントでは、これらの API の概要について説明します。

主な機能

  • 中断のないデプロイ (ホットデプロイ): ノードの再起動やコアのリロードなしでパッケージをインストールおよび更新できる必要があるため、デプロイは迅速であり、リクエストの失敗や古いキャッシュなしに行われる必要があります。

  • 簡単なパッケージング

    • クエリパーサー、検索コンポーネント、リクエストハンドラー、URP などの標準プラグインの概念は、特別なコード/パッケージの変更なしにサポートされる必要があります。

    • ユーザーがすでにデプロイしている (および本番環境で使用している) アーティファクト (カスタムプラグインを含む jar) は、再コンパイルや再パッケージングをしなくても、より多くの採用のために互換性がある必要があります。

    • 単一の jar パッケージと複数の jar パッケージの両方をサポートする必要があります。

    • 使い慣れた/標準的な命名を使用する

    • apt、dnf、homebrew などのようなパッケージマネージャーに関する業界標準の概念と用語を使用します。

クラスローダー

システムの中心には、クラスローダーの分離があります。これを実現するために、システムは 2 層のクラスローダーに単純化されています。

  • Solr クラスパスのすべての jar を持つルートクラスローダー。これを変更するには、Solr ノードの再起動が必要です。

  • ルートクラスローダーから継承する名前付きクラスローダーのセット。名前付きクラスローダーのライフサイクルは、ZooKeeper のパッケージ構成に結び付けられています。構成が変更されるとすぐに、対応するクラスローダーがリロードされ、コンポーネントがリロードを求められます。

パッケージのロードセキュリティ

パッケージはデフォルトで無効になっています。この機能を使用するには、システムプロパティ -Denable.packages=true を指定してすべてのノードを起動します。

bin/solr -c -Denable.packages=true

キーのアップロード

パッケージのバイナリは、プライベートキーで署名する必要があり、公開キーがパッケージストアの信頼できるストアに公開されていることを確認してください。

openssl genrsa -out my_key.pem 512
# create the public key in .der format
openssl rsa -in my_key.pem -pubout -outform DER -out my_key.der
# upload key to package store
bin/solr package add-key my_key.der

パッケージストア

パッケージストアは、ファイルシステムに任意のファイルを保存できる分散ファイルストアです。

  • これは、完全にレプリケートされたファイルシステムベースのリポジトリです。

  • 各Solrノードの<solr.home>/filestoreに存在します。

  • 各エントリは、ファイルとメタデータで構成されます。メタデータは.<filename>.jsonという名前です。

  • メタデータファイルには、ファイルのsha256、署名が含まれます。

  • ユーザーはピリオド(.)で始まるファイルを作成できません。

  • ファイルのコンテンツタイプには依存しません。jarファイルだけでなく、他のファイルも保存できます。

パッケージストアの仕組み

ファイルがパッケージストアにアップロードされると、次のようになります。

  • ローカルファイルシステムに保存されます。

  • メタデータとともに保存されます。メタデータファイルには、jarファイルのsha512と署名も保存されます。

  • クラスタ内のすべての稼働中のノードにも、ダウンロードするように要求されます。

パッケージストアAPI

エンドポイントは以下のとおりです。

  • 各ノードのPUT /api/cluster/files/{フル/パス/ファイルへ}

  • ファイルのダウンロードにはGET /api/node/files/{フル/パス/ファイルへ}

  • ファイルのメタデータ取得にはGET /api/node/files/{フル/パス/ファイルへ}?meta=true

  • /フル/パス/へにあるファイルの一覧取得にはGET /api/node/files/{フル/パス/へ}

アーティファクトの署名

公開鍵で署名されたjarをアップロードするには、次の手順に従います。

  1. プラグインを含むjarファイルがない場合は、GitHubからサンプルをダウンロードしてください。

    curl -o runtimelibs.jar   -LO https://github.com/apache/solr/blob/releases/solr/9.5.0/solr/core/src/test-files/runtimecode/runtimelibs.jar.bin?raw=true
  2. 秘密鍵でjarに署名します。

    openssl dgst -sha1 -sign my_key.pem runtimelibs.jar | openssl enc -base64 | sed 's/+/%2B/g' | tr -d \\n | sed
  3. 署名付きjarをアップロードし、sigパラメータを前のコマンドの出力で置き換えます。

    curl --data-binary @runtimelibs.jar -X PUT  https://127.0.0.1:8983/api/cluster/files/mypkg/1.0/myplugins.jar?sig=<signature-of-jar>
  4. jarのアップロードを検証します。

    curl https://127.0.0.1:8983/api/node/files/mypkg/1.0?omitHeader=true
    {
      "files":{"/mypkg/1.0":[{
      "name":"myplugins.jar",
      "timestamp":"2019-11-11T07:36:17.354Z",
      "sha512":"d01b51de67ae1680a84a813983b1de3b592fc32f1a22b662fc9057da5953abd1b72476388ba342cad21671cd0b805503c78ab9075ff2f3951fdf75fa16981420",
      "sig":["elNjhmWIOgTgbAzeZ+OcwR42N7vqL6Ig9eAqn4YoP2thT7FJuhiaZuCPivjMkD682EBo9gveSCTyXIsZKjOCbQ=="]}]}}

パッケージ

パッケージには次の属性があります。

  • 一意の名前

  • 次の属性を持つ1つ以上のバージョン

    • version:バージョン文字列

    • files:パッケージストアからのファイルの配列

パッケージ定義内のすべてのパッケージ/バージョンに対して、一意のSolrResourceLoaderインスタンスが存在します。これはCoreContainerリソースローダーの子です。

Solrは、バージョン文字列が特定の形式に従うことを要求しません。任意の文字列、または空の文字列でも構いません。

packages.json

パッケージ構成は、ZooKeeper内のpackages.jsonというファイルに存在します。任意の時点で、パッケージ構成内に特定のパッケージの複数のバージョンを持つことができます。システムは常に最新バージョンを使用します。バージョンは、それらの値を辞書式順序でソートされ、最大の文字列が最新と見なされます。

バージョン文字列の辞書式順序とは、バージョンが1.2.01.9.01.11.0のパッケージの場合、Solrは1.9.0を最新バージョンとして選択することを意味します。

例:

{
 "packages" : {
   "mypkg" : {
     "name": "mypkg",
     "versions": [
       {"version" : "0.1",
       "files" : ["/path/to/myplugin/1.1/plugin.jar"]
       },
       {"version" :  "0.2",
       "files" : ["/path/to/myplugin/1.0/plugin.jar"]
       }]}}}

APIエンドポイント

  • GET /api/cluster/package パッケージの一覧を取得

  • POST /api/cluster/package パッケージを編集

    • addコマンド:パッケージのバージョンを追加

    • deleteコマンド:パッケージのバージョンを削除

アップグレード方法

addコマンドを使用して、現在のバージョンよりも高いバージョンを追加します。

ダウングレード方法

deleteコマンドを使用して、最も高いバージョンを削除し、次に高いバージョンを選択します。

複数のバージョンを並行して使用する

コレクション構成のparams.jsonを使用して、使用するパッケージのバージョンを保存します。デフォルトでは、$LATESTです。

{"params":{
 "PKG_VERSIONS": {
   "mypkg": "0.1", (1)
   "pkg2" : "$LATEST", (2)
 }}}
1 mypkgの場合、新しいバージョンが利用可能かどうかに関係なく、バージョン0.1を使用します。
2 pkg2の場合、最新のものを使用します。これはオプションです。デフォルトは$LATESTです。

params.jsonのパッケージバージョンは、実際には、提供された値以下の最大バージョンを持つパッケージを選択するようにSolrに指示します。

したがって、上記の例では、mypkgで利用可能なバージョンが0.010.2のみの場合、バージョン0.01が使用されます。

ワークフロー

  • パッケージの新しいバージョンが追加されます。

  • パッケージローダーはクラスをロードし、新しいバージョンの可用性をすべてのプラグインホルダーに通知します。

  • 特定のバージョンを使用することになっているかどうかを確認し、更新を無視します。

  • そうでない場合は、プラグインをリロードします。

プラグインでのパッケージの使用

任意のクラス名の前にパッケージ名を付けることができます(例:mypkg:fully.qualified.ClassName)。Solrは、最新バージョンのパッケージを使用してクラスをロードします。パッケージからロードされたプラグインは、コアレベルのクラスに依存することはできません。

solrconfig.xmlでのプラグイン宣言
<requestHandler name="/myhandler" class="mypkg:full.path.to.MyClass">
</requestHandler>

完全な動作例

  1. パッケージを作成します。

    curl  https://127.0.0.1:8983/api/cluster/package -H 'Content-type:application/json' -d  '
    {"add": {
             "package" : "mypkg",
             "version":"1.0",
             "files" :["/mypkg/1.0/myplugins.jar"]}}'
  2. 作成したパッケージを検証します。

    curl https://127.0.0.1:8983/api/cluster/package?omitHeader=true
      {"result":{
        "znodeVersion":0,
        "packages":{"mypkg":[{
              "version":"1.0",
              "files":["/mypkg/1.0/myplugins.jar"]}]}}}
  3. この時点で、パッケージは使用できるようになっているはずです。次に、パッケージからコレクションにプラグインを登録します。class属性に適用されたmypkg:プレフィックスに注意してください。同じ結果は、solrconfig.xmlを編集することでも実現できます。

    curl https://127.0.0.1:8983/solr/gettingstarted/config -H 'Content-type:application/json' -d  '{
              "create-requesthandler": { "name": "/test",
              "class": "mypkg:org.apache.solr.core.RuntimeLibReqHandler" }}'
  4. コンポーネントが作成され、パッケージの正しいバージョンを使用してクラスをロードしていることを確認します。

    curl https://127.0.0.1:8983/solr/gettingstarted/config/requestHandler?componentName=/test&meta=true&omitHeader=true
    {
      "config":{"requestHandler":{"/test":{
            "name":"/test",
            "class":"mypkg:org.apache.solr.core.RuntimeLibReqHandler",
            "_packageinfo_":{
              "package":"mypkg",
              "version":"1.0",
              "files":["/mypkg/1.0/myplugins.jar"]}}}}}
  5. リクエストハンドラーをテストします。

    curl https://127.0.0.1:8983/solr/gettingstarted/test?omitHeader=true
    {
      "params":{
        "omitHeader":"true"},
      "context":{
        "webapp":"/solr",
        "path":"/test",
        "httpMethod":"GET"},
      "class":"org.apache.solr.core.RuntimeLibReqHandler",
      "loader":"java.net.FactoryURLClassLoader"}
  6. コンポーネントのバージョンを更新します。新しいバージョンのjarを取得し、署名してアップロードします。

    curl -o runtimelibs3.jar   -LO https://github.com/apache/solr/blob/releases/solr/9.5.0/solr/core/src/test-files/runtimecode/runtimelibs_v3.jar.bin?raw=true
    
    openssl dgst -sha1 -sign my_key.pem runtimelibs.jar | openssl enc -base64 | sed 's/+/%2B/g' | tr -d \\n | sed
    
    curl --data-binary @runtimelibs3.jar -X PUT  https://127.0.0.1:8983/api/cluster/files/mypkg/2.0/myplugins.jar?sig=
  7. 検証します。

    curl https://127.0.0.1:8983/api/node/files/mypkg/2.0?omitHeader=true
    {
      "files":{"/mypkg/2.0":[{
            "name":"myplugins.jar",
            "timestamp":"2019-11-11T11:46:14.771Z",
            "sha512":"60ec88c2a2e9b409f7afc309273383810a0d07a078b482434eda9674f7e25b8adafa8a67c9913c996cbfb78a7f6ad2b9db26dbd4fe0ca4068f248d5db563f922",
            "sig":["ICkC+nGE+AqiANM0ajhVPNCQsbPbHLSWlIe5ETV5835e5HqndWrFHiV2R6nLVjDCxov/wLPo1uK0VzvAPIioUQ=="]}]}}
  8. パッケージの新しいバージョンを追加します。

    curl  https://127.0.0.1:8983/api/cluster/package -H 'Content-type:application/json' -d  '
    {"add": {
             "package" : "mypkg",
             "version":"2.0",
             "files" :["/mypkg/2.0/myplugins.jar"]}}'
  9. プラグインを検証して、パッケージの正しいバージョンが使用されているかどうかを確認します。

    curl https://127.0.0.1:8983/solr/gettingstarted/config/requestHandler?componentName=/test&meta=true&omitHeader=true
    {
      "config": {
        "requestHandler": {
          "/test": {
            "name": "/test",
            "class": "mypkg:org.apache.solr.core.RuntimeLibReqHandler",
            "_packageinfo_": {
              "package": "mypkg",
              "version": "2.0",
              "files": [
                "/mypkg/2.0/myplugins.jar"
              ]
            }}}}}
  10. プラグインをテストします。

    curl https://127.0.0.1:8983/solr/gettingstarted/test?omitHeader=true
    {
      "params": {
        "omitHeader": "true"
      },
      "context": {
        "webapp": "/solr",
        "path": "/test",
        "httpMethod": "GET"
      },
      "class": "org.apache.solr.core.RuntimeLibReqHandler",
      "loader": "java.net.FactoryURLClassLoader",
      "Version": "2"
    }

    Versionの値が"2"であることに注意してください。これは、プラグインが更新されたことを意味します。

自動アップグレードを回避する方法

任意のコレクションで使用されるデフォルトのバージョンは常に最新です。ただし、params.jsonにコレクションごとのプロパティを設定すると、コレクションは、後でSolrに追加される可能性のある2.0よりも後のバージョンに関係なく、同じパッケージバージョン(つまり、バージョン2.0)を使用することが保証されます。

curl https://127.0.0.1:8983/solr/gettingstarted/config/params -H 'Content-type:application/json'  -d '{
  "set":{
    "PKG_VERSIONS":{
      "mypkg":"2.0"
      }
  }}'