こんにちは。
株式会社イージーネット プロダクト&サービス事業部 の久保です。
前回書いたSolrの記事 全文検索サーバ: これからSolrを始める人のためのApache Solr概要と便利なリンク集 はおかげさまで沢山のアクセス/ブックマークをいただきました。
来週火曜日の7/21には、Lucene/Solrで有名なロンウイットの関口さん(参考: 関口宏司のLuceneブログ)などが参加されるSolr勉強会も開催されるようですので、Solr人気は高まっているのかもしれません。
今回は前回から変わって小さなネタになりますが、
Solr/SolrJ1.3のCoreAdmin(マルチコア)機能を用いて動的にCoreを追加する際にはまるSolrJのバグと、その対処方法について書きます。
Solr1.3のマルチコア機能とは
単純に言うと、1つのSolrアプリケーション(サーブレットアプリケーション)の上で、論理的に複数のSolrアプリケーションを動かすことができる機能です。
詳しくは前回の記事の「マルチコア構成」をご覧ください。
Coreを追加するためのURL(Query String)
Coreを追加するのに必要なURL(Query String)は次のようになります。
(参考URL: Solr Wiki – CoreAdmin)
http://server/solr/admin/cores?action=CREATE&name=[name]&instanceDir=[dir]&config=[solrconfig]&schema=[schema] |
(例)
http://testserver:8080/solr/admin/cores?action=CREATE&name=test&instanceDir=test&config=/solr/conf/solrconfig.xml&schema=/solr/conf/schema.xml |
| [name] | coreに付ける名前(例: test) |
|---|---|
| [dir] | coreのディレクトリ名(例: test) |
| [solrconfig] | solrconfig.xmlファイルのパス(例: /solr/conf/solrconfig.xml) |
| [schema] | schema.xmlファイル(例: /solr/conf/schema.xml) |
SolrJを使った場合の問題
SolrJのver1.3において、SolrCoreAdminRequestのcreateCoreメソッドを使った以下のコードは失敗します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package jp.co.eni.solr.test; import java.io.IOException; import java.net.MalformedURLException; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; import org.apache.solr.client.solrj.request.CoreAdminRequest; import org.apache.solr.client.solrj.response.CoreAdminResponse; //失敗する public class FailedCoreCreateTest { public static void main(String[] args) { try { // SolrのURL String url = "http://server/solr/"; // coreの名前 String coreName = "failed"; // coreのディレクトリ名 String instanceDir = "failed"; SolrServer server = new CommonsHttpSolrServer(url); CoreAdminResponse response = CoreAdminRequest.createCore(coreName, instanceDir, server); System.out.println("qtime: " + response.getQTime()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (SolrServerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } |
失敗の原因は、上記コードにより生成されるHTTP RequestのQuery Stringにあります。
エラーのログを見ると、
Exception in thread "main" org.apache.solr.common.SolrException: Internal Server Error Internal Server Error request: http://server/solr/admin/cores?action=CREATE&core=failed&instanceDir=failed&wt=javabin&version=2.2 at org.apache.solr.client.solrj.impl.CommonsHttpSolrServer.request(CommonsHttpSolrServer.java:343) at org.apache.solr.client.solrj.impl.CommonsHttpSolrServer.request(CommonsHttpSolrServer.java:183) at org.apache.solr.client.solrj.request.CoreAdminRequest.process(CoreAdminRequest.java:170) at org.apache.solr.client.solrj.request.CoreAdminRequest.createCore(CoreAdminRequest.java:226) at jp.co.eni.solr.test.FailedCoreCreateTest.main(FailedCoreCreateTest.java:23) |
とあるように、
name=failed
ではなく
core=failed
となっていることが分かります。
これは、SolrJ1.3のorg.apache.solr.client.solrj.request.CoreAdminRequest.Create#getParames(rev:688188)が以下のような実装になっているためです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Override
public SolrParams getParams() {
if( action == null ) {
throw new RuntimeException( "no action specified!" );
}
ModifiableSolrParams params = new ModifiableSolrParams();
params.set( CoreAdminParams.ACTION, action.toString() );
params.set( CoreAdminParams.CORE, core ); //←※ここがおかしい
params.set( CoreAdminParams.INSTANCE_DIR, instanceDir);
if (configName != null) {
params.set( CoreAdminParams.CONFIG, configName);
}
if (schemaName != null) {
params.set( CoreAdminParams.SCHEMA, schemaName);
}
return params;
} |
簡単な解決策
以下のようなCoreAdminRequest.Createの拡張クラスを用意することで、上記の問題を解決することができます。
用意するクラス
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package jp.co.eni.solr.test; import org.apache.solr.client.solrj.request.CoreAdminRequest.Create; import org.apache.solr.common.params.CoreAdminParams; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; public class SolvedCreate extends Create { /** * コンストラクタ * * @param coreName * @param instanceDir * @param configName * @param schemaName */ public SolvedCreate(String coreName, String instanceDir, String configName, String schemaName) { super(); // coreの名前 setCoreName(coreName); // coreのディレクトリ名 setInstanceDir(instanceDir); // solrconfig.xmlのパス setConfigName(configName); // schema.xmlのパス setSchemaName(schemaName); } @Override public SolrParams getParams() { ModifiableSolrParams params = (ModifiableSolrParams) super.getParams(); // coreではなくnameを使う params.set(CoreAdminParams.CORE, (String) null); params.set(CoreAdminParams.NAME, core); return params; } } |
getParamsメソッドは、org.apache.solr.client.solrj.impl.CommonsHttpSolrServer#requestの中で呼ばれます。
CoreAdminParams.COREやCoreAdminParams.NAMEを持つorg.apache.solr.common.params.CoreAdminParamsというのは以下のようなインタフェースになっており、
COREではなくNAMEを用いるのが正しそうだということになります。
1 2 3 4 5 6 7 8 9 10 11 12 | public interface CoreAdminParams { /** What Core are we talking about **/ public final static String CORE = "core"; /** Persistent -- should it save the cores state? **/ public final static String PERSISTENT = "persistent"; /** If you rename something, what is the new name **/ public final static String NAME = "name"; // 後略 |
SolvedCreate利用コード
上記のSolvedCreateクラスを利用したコードは次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | package jp.co.eni.solr.test; import java.io.IOException; import java.net.MalformedURLException; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; import org.apache.solr.client.solrj.response.CoreAdminResponse; // 成功する public class SuccessCoreCreateTest { public static void main(String[] args) { try { // SolrのURL String url = "http://server/solr/"; // coreの名前 String coreName = "name2"; // coreのディレクトリ名 String instanceDir = "dir2"; // solrconfig.xmlのパス String configName = "/solr/conf/solrconfig.xml"; // schema.xmlのパス String schemaName = "/solr/conf/schema.xml"; // Createクラスのバグ対応のため、SolvedCreateクラスを作成して使っている SolvedCreate createRequest = new SolvedCreate(coreName, instanceDir, configName, schemaName); SolrServer server = new CommonsHttpSolrServer(url); CoreAdminResponse response = createRequest.process(server); System.out.println("qtime: " + response.getQTime()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (SolrServerException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } |
1.4では修正される模様
この問題は、Apacheプロジェクトのバグトラックにも登録されています。
SOLR-803: CoreAdminRequest.createCore fails because name parameter isn’t setを見ると、StatusはResolveとなっています。
Solrのレポジトリを直接確認してみたところ、上記の問題はrev.708266の修正で解決されているようです。
SOLR-803: fix CoreAdminRequest.createCore error
コードは確認していませんが、ちゃんとした?修正がされていそうです。
またpache Solr Version 1.4-dev Release Notesを見ると、SOLR-803も含まれていますので、1.4のリリース時にはこのエントリで取り上げた問題は発生しなくなるはずです。
参考URL
使用したソフトウェア
| ソフトウェア | バージョン |
|---|---|
| Solr | 1.3 |
| SolrJ | 1.3 |





7月 19th, 2009 at 03:03
[...] Solr/SolrJ1.3のCoreAdmin(マルチコア)機能を用いて動的にCoreを追加する方法(SolrJ… (4) [...]