Solr 5.1.0 を GlassFish 4.1 で動かす、ZooKeeprで冗長構成も取る

## Solrインストール

```shell-session:
$ wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache/lucene/solr/5.1.0/solr-5.1.0.tgz
$ tar zxvf solr-5.1.0.tgz
$ chown -R userid.groupid solr-5.1.0 -- 必要ならグループとユーザ変更
```

なければバージョン上げても問題ないと思う。
或いは別のサイトから探す。

## ZooKeeprインストール

SolrのEmbeddedモードでZookeeperを動かすと
SolrとZooKeeperのプロセスが同居してしまうため、別プロセスで動作させる。

```shell-session:
$ wget http://ftp.jaist.ac.jp/pub/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz
$ tar zookeeper-3.4.6.tar.gz
$ chown -R userid.groupid zookeeper-3.4.6 -- 必要ならグループとユーザ変更
```

Solr-5.1.0 が内包しているZooKeeperが3.4.6なのでそれに合わせる。
別のバージョンの時は内容しているZooKeeperを合わせる。

## Solrを設定

Solrホームを/data/solr-5.1.0/server/solr/と仮定
まずはSolr設定ファイルを編集する

```shell-session:
$ cd /data/solr-5.1.0/server/solr/
$ vi solr.xml
```

通常のGlassFishのポートは8080なのでそれに合わせる

```diff:solr.xml
<solr>

  <solrcloud>

    <str name="host">${host:}</str>
+    <int name="hostPort">${jetty.port:8080}</int>
    <str name="hostContext">${hostContext:solr}</str>

    <bool name="genericCoreNodeNames">${genericCoreNodeNames:true}</bool>

    <int name="zkClientTimeout">${zkClientTimeout:30000}</int>
    <int name="distribUpdateSoTimeout">${distribUpdateSoTimeout:600000}</int>
    <int name="distribUpdateConnTimeout">${distribUpdateConnTimeout:60000}</int>

  </solrcloud>

  <shardHandlerFactory name="shardHandlerFactory"
    class="HttpShardHandlerFactory">
    <int name="socketTimeout">${socketTimeout:600000}</int>
    <int name="connTimeout">${connTimeout:60000}</int>
  </shardHandlerFactory>

</solr>
```

## Zookeeperを設定して起動する

今回は冗長構成のみでシャーディングは行わない。
ZooKeeperは多数決でリーダを決定するため最小３台構成になるので注意。
まずは、zoo_sample.cfgをコピーしてzoo.confgを作成して編集する

```shell-session:
$ cd /data/zookeeper-3.4.6/conf
$ cp zoo_sample.cfg zoo.cfg
$ vi zoo.conf
```

Solrのデータディレクトリ、クライアントポート
ZooKeeperサーバのIPアドレスとポートを設定する

今回は３台用意したが、仮に同一サーバに複数ZooKeeperを設定する場合は
ポート番号が被らないように注意すること。

```diff:zoo.cfg
$ cp zoo_sample.cfg zoo.cfg
$ vi zoo.cfg

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5

# the directory where the snapshot is stored.
# dataDir=/opt/zookeeper/data
# NOTE: Solr defaults the dataDir to <solrHome>/zoo_data
+ # Solrのインデックスデータ等を格納するディレクトリを指定
+ dataDir=/data/solr-5.1.0/server/solr/zoo_data

# the port at which the clients will connect
+ clientPort=2181

# NOTE: Solr sets this based on zkRun / zkHost params
+ # 各サーバのIPアドレスを設定
+ server.1=xx.xx.xx.xx:2888:3888
+ server.2=xx.xx.xx.xx:2888:3888
+ server.3=xx.xx.xx.xx:2888:3888
```

myidファイルを作成する
server.1 / server.2 / server.3 で指定した各サーバに作成する。

```shell-session:
$ cd  /data/solr-5.1.0/server/solr/zoo_data/
$ echo 1 > myid -- server.2 なら 2、server.3 なら 3 でファイルを作成
```

これでデータフォルダの同期設定は済んだため、先にZooKeerを上げておく。
各サーバで実行すること。

実行時にログでリーダは分かるが
ZooKeeperの仕組み的にどれがリーダかを全く意識する必要はない。
また、後述するSolrの管理画面でもリーダは分かる。

```shell-session:
$ cd /data/zookeeper-3.4.6/
$ bin/zkServer.sh start
```
**Solr組込のZooKeeperは利用するとハマる**
**必ず自身がセットアップしたものを起動**

## GlassFish に Solr をデプロイする

まずは設定。
管理コンソールからでも良いし、domain.xmlを直接編集しても良い。

要点だけ纏めると

```diff:システムプロパティ
server(Admin Server)
 → Propertiesタブ

+ solr.home = /data/solr-5.1.0/server/solr
+ solr.install.dir = /data/solr-5.1.0
```

```diff:JVM設定
Configulation	
 →server-config	
  →JVM Settings	

+ -DzkHost=xx.xx.xx.xx:2181,xx.xx.xx.xx:2181,xx.xx.xx.xx:2181
+ -Dbootstrap_confdir=${solr.solr.home}/(solrのコア名)/conf
+ -DnumShards=1
+ -Dcollection.configName=myconf
```

こんな感じ。
solrのコア名はこの後で作成する。

で、Solrをデプロイ。
GlassFish 4.1 というか CDI 1.1にて
beans.xmlを含めていないアーカイブで勝手にCDI登録されてしまうのを防ぐため
implicitCdiEnabled=falseを設定しているのがポイント。

```shell-session:
$ asadmin deploy --property implicitCdiEnabled=false solr.war
```
で、下記にアクセスすれば、Solr管理画面が表示される。
３台ともにデプロイしておくこと。

```shell-session:
http://xx.xx.xx.xx:8080/solr/
```

## Solrのコアファイルを作成

ここからは１台の何れかのサーバで設定を行う。

１．Solr Home に設定ファイルを作成

```shell-session:
$ cd /data/solr-5.1.0/server/solr/
$ mkdir anyCoreName
$ cp -rp configsets/data_driven_schema_configs/conf/anyCoreName/
-- anyCoreNameは実際にはCore名を指定すること。
```

２．スキーマファイルを配置

スキーマファイルは各自で作成したもの。
内容に関しては、ここでは省略。

```shell-session:
$ cp /tmp/schema.xml /data/solr-5.1.0/server/solr/im-news/conf/
```

３．設定ファイルをZooKeeperに伝搬登録させる

今度はSolr側のスクリプトを使う。
これで残りの２台にも設定が伝搬されるので楽。

```shell-session:
$ cd /data/solr-5.1.0/server/scripts/cloud-scripts
$ sh zkcli.sh -cmd upconfig -zkhost localhost:2181 -confdir /data02/solr-5.1.0/server/solr/im-news/conf -confname myconf
```

## Solrを起動してコアファイルを登録

何れかのサーバで、Solrコンソール画面を表示して
メニューの「Core Admin」画面を表示し、「Add Core」ボタンをクリック

![image](https://qiita-image-store.s3.amazonaws.com/0/101086/3d97ff6d-508a-bc22-72a2-bcb658b07a73.png)

| items        | value          | explain      |
|:------------:|:--------------:|:-------------|
| name         | anyCoreName    |  コア名 |
| instanceDir  | anyCoreName    |  コア名を保存するディレクトリ名 |
| dataDir      |        data    |  そのまま |
| config       | solrconfig.xml |  そのまま |
| schema       |  schema.xml    |  そのまま |
| collection   |  myconf        |  ZooKeeperに登録した時のSolr設定ファイル名 |
| shard        |      shard1    |  シャード名（今回はシャード構成なし）|

これでＯＫ。

![image](https://qiita-image-store.s3.amazonaws.com/0/101086/32046568-ee6e-6dd7-c60b-c100aa157349.png)

うまくいかない時は

１．Solrを、順番に全部落とす (asadmin stop-domain)
２．ZooKeeperを、順番に全部落とす
３．ZooKeeperを、順番に１つずつ立ち上げる
４．Solrを、順番に１ドメインずつ立ち上げる (asadmin start-domain)

必要に応じて

設定ファイルの再アップと反映を行うと良い。

```shell-session:
$ zkcli.sh -cmd upconfig -zkhost localhost:2181 -confdir /data/solr-5.1.0/server/solr/anyCoreName/conf/ -confname myconf
$ curl "http://localhost:8080/solr/admin/collections?action=RELOAD&name=anyCoreName&indent=on"
```