はじめに
スタンバイアドベントカレンダー4日目です
スタンバイでは検索エンジンにVespaを利用しています!
Vespaはmulti-node構成をとることで冗長化することができます。
スタンバイでも冗長化構成をとっています。
本記事では冗長化構成であるmulti-nodeの公式サンプルが用意されているので、それを用いて環境構築します。
環境構築後、content cluster
の冗長化について検証していきたいと思います。content cluster
はdocumentを管理しています。
※document:Vespaはデータをドキュメントとしてモデル化しています。本記事でデータの意味を表します。
各clusterの役割
サンプルを実施する前にVespaの各clusterについて簡単に説明をします。
画像出典: Vespa Overview
cluster | 役割 |
---|---|
Admin/Config | 設定の管理や各clusterの制御の役割 |
Stateless Java container | ユーザからの検索リクエストや更新を受け付ける役割 |
Content | indexを保持し検索・ランキングを実行する役割 |
公式サンプル実施!
環境準備
公式サンプルの最初からStart the content cluster:まで実施します。ここまで実施すると動作確認できる状態になっています。
※サンプルの中でstatusの確認をする場面が何度かでてきますが、数十秒待たないと反映されないこともあるのでご注意ください。
このサンプルでは、contaier-cluster
を2つにわけています。feed(更新)
とquery(検索)
を独立して作成しています。
動作確認
feed(更新)
documentAPIを利用してdocumentのfeedをします。このサンプルでは5件feedします。
i=0; (for doc in $(ls ../../../album-recommendation/ext/*.json); \
do \
curl -H Content-Type:application/json -d @$doc \
http://localhost:8080/document/v1/mynamespace/music/docid/$i; \
i=$(($i + 1)); echo; \
done)
query(検索)
feedしたdocumentが検索できることを確認します。
curl --data-urlencode 'yql=select * from sources * where sddocname contains "music"' \
http://localhost:8082/search/
contentの冗長性
contentの冗長性について確認していきます。
デプロイはサンプルにあったコマンドを実行します。
(以降デプロイする時はこのコマンドを実行)
zip -r - . -x "gke/*" "img/*" "scripts/*" "pki/*" "tls/*" README.md .gitignore "*.yaml" | \
curl --header Content-Type:application/zip --data-binary @- \
http://localhost:19071/application/v2/tenant/default/prepareandactivate
content内のドキュメント数
各nodeのドキュメント数を確認するのにVespaが提供するmonitorAPIを利用します。
サンプルだとnode8とnode9がcontent-node
なので対象portにリクエストを投げます。
content-node
を増やす場合はports
を更新してください。
ports=(20100 20101)
for port in "${ports[@]}"; do
curl -s "http://localhost:$port/metrics/v2/values" | \
jq -r '.nodes[] | .hostname as $hostname | .services[] | select(.name == "vespa.searchnode") | .metrics[] | select(.values["content.proton.documentdb.documents.active.last"]) | "\($hostname): \(.values["content.proton.documentdb.documents.active.last"])"'
done
実行するとnode8に2件、node9に3件保持していることがわかります。(node8が3件になることもあるかもしれません)
node8.vespanet: 2
node9.vespanet: 3
min-redundancy
概要
サンプルでは<min-redundancy>2</min-redundancy>
となっています。
min-redundancy
とはdocumentをコピーして保持する数となります。つまり、いずれかのcontentが壊れてもdocumentを保持します。
以下のパターンを検証します。
- 特定nodeにおけるVespaサービスの停止
- コンテナ停止
- コンテナ削除
検証
冗長性あり(min-redundancy:2)
- 特定nodeにおけるVespaサービスの停止
node9のVespaサービスを停止してみます。
docker exec -it node9 /bin/bash
[vespa@node9 /]$ vespa-stop-services
config-sentinel was running with pid 99, sending SIGTERM
Waiting for exit (up to 15 minutes)
.. DONE
configproxy was running with pid 33, sending SIGTERM
Waiting for exit (up to 15 minutes)
. DONE
ドキュメント数を確認してみるとnode8のdocumentが5件になっていることがわかります。なので検索しても5件表示されます。
node8.vespanet: 5
node9のVespaを再開させます
[vespa@node9 /]$ vespa-start-services
Starting config proxy using tcp/node0.vespanet:19070 and tcp/node1.vespanet:19070 and tcp/node2.vespanet:19070 as config source(s)
Waiting for config proxy to start on 'node9.vespanet'
runserver(configproxy) running with pid: 587
config proxy started after 0s (runserver pid 587)
Starting services for VESPA_HOSTNAME='node9.vespanet'
runserver(config-sentinel) running with pid: 653
数秒待つと、ドキュメント数は以前と同じ状態になります。
node8.vespanet: 2
node9.vespanet: 3
- コンテナ停止
docker stop node9
Vespaサービスの停止と同じ動作になります。
- コンテナ削除
docker rm -f node9
削除後にnode9を再度docker run
し、再度デプロイします。
docker run --detach --name node9 --hostname node9.vespanet \
-e VESPA_CONFIGSERVERS=node0.vespanet,node1.vespanet,node2.vespanet \
--network vespanet \
--publish 19108:19107 --publish 20101:19092 \
vespaengine/vespa services
Vespaサービスの停止と同じ動作になります。
冗長性なし(min-redundancy:1)
services.xml
を修正して、デプロイします。
※抜粋
<content id="music" version="1.0">
<min-redundancy>1</min-redundancy>
<documents>
<document type="music" mode="index" />
<document-processing cluster="feed" />
</documents>
<nodes>
<node hostalias="node8" distribution-key="0" />
<node hostalias="node9" distribution-key="1" />
</nodes>
</content>
- 特定nodeにおけるVespaサービスの停止
先ほどと同じようにnode9のVespaサービスを停止して、ドキュメント数を確認します。
node8.vespanet: 2
先ほどと違い冗長化されていないため、node8のdocumentが2件のままとなっています。なので検索しても2件しか返却されません。
-
コンテナ停止
Vespaサービスの停止と同じ動作になります。 -
コンテナ削除
削除後にnode9を再度docker run
し、再度デプロイします。
node8.vespanet: 2
node9.vespanet: 0
冗長化していた時と違い、document数が戻りません。
Vespaのdocument情報はvespa-remove-indexで記載されている通り$VESPA_HOME/var/db/vespa/
に格納されているため、コンテナを削除すると削除されます。
Vespaサービスの停止とコンテナ停止は$VESPA_HOME/var/db/vespa/
の情報が削除されないため、documentが復活するということがわかりました。
group
先ほどはcontent
のnode1台ずつ独立して分散していましたが、
content-node
をグループ化して分散することも可能です。
content用のコンテナを追加で作成します。
docker run --detach --name node10 --hostname node10.vespanet \
-e VESPA_CONFIGSERVERS=node0.vespanet,node1.vespanet,node2.vespanet \
--network vespanet \
--publish 19109:19107 --publish 20102:19092 \
vespaengine/vespa services
docker run --detach --name node11 --hostname node11.vespanet \
-e VESPA_CONFIGSERVERS=node0.vespanet,node1.vespanet,node2.vespanet \
--network vespanet \
--publish 19110:19107 --publish 20103:19092 \
vespaengine/vespa services
hosts.xml
にnode10とnode11を追加します。
※抜粋
<host name="node10.vespanet">
<alias>node10</alias>
</host>
<host name="node11.vespanet">
<alias>node11</alias>
</host>
services.xml
にnode10とnode11を追加します。
※抜粋
<content id="music" version="1.0">
<min-redundancy>2</min-redundancy>
<documents>
<document type="music" mode="index" />
<document-processing cluster="feed" />
</documents>
<group>
<distribution partitions="1|*"/>
<group name="group0" distribution-key="0">
<node hostalias="node8" distribution-key="0"/>
<node hostalias="node9" distribution-key="1"/>
</group>
<group name="group1" distribution-key="1">
<node hostalias="node10" distribution-key="2"/>
<node hostalias="node11" distribution-key="3"/>
</group>
</group>
</content>
この状態でデプロイします。(グループ数とmin-redundancyの数やdistribution partitions
の設定が正しくないとエラーになります)
デプロイ後、各コンテナのdocument数を確認するとグループ単位に冗長化されていることが確認できました。
node8.vespanet: 2
node9.vespanet: 3
node10.vespanet: 3
node11.vespanet: 2
最後に
content cluster
の冗長化について確認し、共有させていただきました。
スタンバイでもcontent cluster
のnode数や冗長化構成は負荷に合わせて試行錯誤しながら調整をしています。
Vespaを利用する側として、今後も学んで最適な構成で利用していきたいです!
最後までお読みいただき、誠にありがとうございました。
参考