こちらのエントリの続きです。
Spring BootとHibernate Searchで遊ぶ
http://d.hatena.ne.jp/Kazuhira/20141223/1419330401
ここで作成したアプリケーションで持つLuceneのインデックスを、複数Nodeとして起動したアプリケーションで共有してみます。
Luceneのインデックスの保存先は、Infinispanとします。
3.3.1. Infinispan Directory configuration
http://docs.jboss.org/hibernate/search/5.0/reference/en-US/html_single/#infinispan-directories
ここで定義するCacheを、Dist/Replとして各Nodeで共有しようということで。まあ、ほとんどHibernate SearchのInfinispan Integrationが持つデフォルト設定ですが。設定ファイルとしては、明示します。
基本的にはpomやapplication.ymlおよびInfinispan/JGroupsの設定追加・変更のみで、ソースコード自体は変更していません。ソースコード自体は前のエントリを参照してください。
依存関係の定義
pomでのHibernate SearchおよびLuceneの依存関係定義は、今回は以下とします。
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-orm</artifactId> <version>5.0.0.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-infinispan</artifactId> <version>5.0.0.Final</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-kuromoji</artifactId> <version>4.10.2</version> </dependency>
「hibernate-search-infinispan」が増えました。
Infinispan/JGroupsの設定ファイル作成
まず、Infinispanの設定ファイルを作成します。
src/main/resources/infinispan.xml
<?xml version="1.0" encoding="UTF-8"?> <infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:infinispan:config:7.0 http://www.infinispan.org/schemas/infinispan-config-7.0.xsd" xmlns="urn:infinispan:config:7.0"> <jgroups> <stack-file name="udp" path="jgroups.xml" /> </jgroups> <cache-container name="indexingCacheManager" shutdown-hook="DONT_REGISTER"> <transport cluster="cluster" stack="udp" /> <distributed-cache name="LuceneIndexesData" mode="SYNC" remote-timeout="25000"> <transaction mode="NONE"/> <state-transfer enabled="true" timeout="480000" await-initial-transfer="true" /> <indexing index="NONE" /> <locking striping="false" acquire-timeout="10000" concurrency-level="500" write-skew="false" /> <eviction max-entries="-1" strategy="NONE"/> <expiration max-idle="-1"/> </distributed-cache> <replicated-cache name="LuceneIndexesMetadata" mode="SYNC" remote-timeout="25000"> <transaction mode="NONE"/> <state-transfer enabled="true" timeout="480000" await-initial-transfer="true" /> <indexing index="NONE" /> <locking striping="false" acquire-timeout="10000" concurrency-level="500" write-skew="false" /> <eviction max-entries="-1" strategy="NONE"/> <expiration max-idle="-1"/> </replicated-cache> <replicated-cache name="LuceneIndexesLocking" mode="SYNC" remote-timeout="25000"> <transaction mode="NONE"/> <state-transfer enabled="true" timeout="480000" await-initial-transfer="true" /> <indexing index="NONE" /> <locking striping="false" acquire-timeout="10000" concurrency-level="500" write-skew="false" /> <eviction max-entries="-1" strategy="NONE"/> <expiration max-idle="-1"/> </replicated-cache> </cache-container> </infinispan>
それぞれインデックスのデータ用、メタデータ用、ロック用のCacheの定義です。まあ、Hibernate Searchのデフォルトのままです。
Hibernate Searchに含まれる、デフォルトのInfinispanの設定
https://github.com/hibernate/hibernate-search/blob/5.0.0.Final/infinispan/src/main/resources/default-hibernatesearch-infinispan.xml
JGroupsの設定は、Infinispan 7.0.2.Finalのデフォルトの設定をベースに、こんな感じにしました。うちはOSのネットワーク関連の設定は、ほぼいじっていないので絞っています。
src/main/resources/jgroups.xml
<?xml version="1.0" encoding="UTF-8"?> <config xmlns="urn:org:jgroups" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/JGroups-3.4.xsd"> <UDP mcast_addr="${jgroups.udp.mcast_addr:228.6.7.8}" mcast_port="${jgroups.udp.mcast_port:46655}" tos="8" ucast_recv_buf_size="150k" ucast_send_buf_size="130k" mcast_recv_buf_size="150k" mcast_send_buf_size="130k" max_bundle_size="31k" ip_ttl="${jgroups.udp.ip_ttl:0}" enable_diagnostics="false" bundler_type="sender-sends-with-timer" thread_naming_pattern="pl" thread_pool.enabled="true" thread_pool.min_threads="2" thread_pool.max_threads="30" thread_pool.keep_alive_time="60000" thread_pool.queue_enabled="true" thread_pool.queue_max_size="100" thread_pool.rejection_policy="Discard" oob_thread_pool.enabled="true" oob_thread_pool.min_threads="2" oob_thread_pool.max_threads="30" oob_thread_pool.keep_alive_time="60000" oob_thread_pool.queue_enabled="false" oob_thread_pool.queue_max_size="100" oob_thread_pool.rejection_policy="Discard" internal_thread_pool.enabled="true" internal_thread_pool.min_threads="2" internal_thread_pool.max_threads="4" internal_thread_pool.keep_alive_time="60000" internal_thread_pool.queue_enabled="true" internal_thread_pool.queue_max_size="100" internal_thread_pool.rejection_policy="Discard" /> <PING timeout="3000" num_initial_members="3"/> <MERGE3/> <FD_SOCK/> <FD_ALL timeout="15000" interval="3000"/> <VERIFY_SUSPECT timeout="1500"/> <pbcast.NAKACK2 xmit_interval="1000" xmit_table_num_rows="100" xmit_table_msgs_per_row="10000" xmit_table_max_compaction_time="10000" max_msg_batch_size="100"/> <UNICAST3 xmit_interval="500" xmit_table_num_rows="20" xmit_table_msgs_per_row="10000" xmit_table_max_compaction_time="10000" max_msg_batch_size="100" conn_expiry_timeout="0"/> <pbcast.STABLE stability_delay="500" desired_avg_gossip="5000" max_bytes="1m"/> <pbcast.GMS print_local_addr="true" join_timeout="3000" view_bundling="true"/> <tom.TOA/> <!-- the TOA is only needed for total order transactions--> <UFC max_credits="2m" min_threshold="0.40"/> <MFC max_credits="2m" min_threshold="0.40"/> <FRAG2 frag_size="30k" /> <RSVP timeout="60000" resend_interval="500" ack_on_delivery="false" /> </config>
Infinispanに含まれる、デフォルトのJGroups(UDP)の設定
https://github.com/infinispan/infinispan/blob/7.0.2.Final/core/src/main/resources/default-configs/default-jgroups-udp.xml
application.ymlの変更
InfinispanをLuceneのDirectoryとして使うに伴い、Hibernate Searchの設定も変更します。
src/main/resources/application.yml
spring: datasource: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/practice?useUnicode=true&characterEncoding=utf-8&characterSetResults=utf-8&useServerPrepStmts=true&useLocalSessionState=true&elideSetAutoCommits=true&alwaysSendSetIsolation=false username: kazuhira password: password jpa: hibernate.ddl-auto: none properties: hibernate: show_sql: true format_sql: true search: default: directory_provider: infinispan infinispan.configuration_resourcename: infinispan.xml analyzer: org.apache.lucene.analysis.ja.JapaneseAnalyzer lucene_version: LUCENE_4_10_2
まず、複数Nodeが上がるのでHibernateのddl-autoはオフにしました。先にDDLは実行済みの前提とします。
あとはInfinispanの設定。先ほど作成した設定ファイルを参照するように「hibernate.search.infinispan.configuration_resourcename」を設定します。
これでお終いです。
実行
それでは、まずはパッケージング。
$ mvn package
2つNodeを起動します。
## Node1 $ java -jar target/spring-boot-hibernate-search-integration-0.0.1-SNAPSHOT.jar --server.port=8080 ## Node2 $ java -jar target/spring-boot-hibernate-search-integration-0.0.1-SNAPSHOT.jar --server.port=8180
うちだと、2Nodeが限界ギリギリでした…。
起動すると、こんな感じで2つのNodeがクラスタを構成してくれます。
2014-12-23 23:46:41.214 INFO 53740 --- [IndexesMetadata] o.i.r.t.jgroups.JGroupsTransport : ISPN000094: Received new cluster view for channel cluster: [xxxxx-16900|1] (2) [xxxxx-16900, xxxxx-48328]
では、データを登録します。こちらは、Node1に対して実行。
$ curl -X POST -H "Content-Type: application/json;" -d@books.json http://localhost:8080/book/
続いて、Node2に対して全文検索を実行してみます。
「Spring Java」
$ curl -X GET -H 'Content-Type: application/json;' -d '{ "query": "Spring Java"}' http://localhost:8180/book/search | perl -wp -e 's!{!\n{!g {"fullTextQuery":"+(title:spring summary:spring) +(title:java summary:java)","hits":1,"books":[ {"isbn":"978-4777518654","title":"はじめてのSpring Boot","price":2700,"summary":"「Spring Framework」で簡単Javaアプリ開発"}]}
「全文検索 Solr」
$ curl -X GET -H 'Content-Type: application/json;' -d '{ "query": "全文検索 Solr"}' http://localhost:8180/book/search | perl -wp -e 's!{!\n{!g' {"fullTextQuery":"+((title:全文 title:検索) (summary:全文 summary:検索)) +(title:solr summary:solr)","hits":2,"books":[ {"isbn":"978-4048662024","title":"高速スケーラブル検索エンジン ElasticSearch Server","price":3024,"summary":"Apache Solrを超える全文検索エンジンとして注目を集めるElasticSearch Serverの日本初の解説書です。多くのサンプルを用いた実践的入門書になっています。"}, {"isbn":"978-4774161631","title":"[改訂新版] Apache Solr入門 オープンソース全文検索エンジン","price":3780,"summary":"最新版Apaceh Solr Ver.4.5.1に対応するため大幅な書き直しと原稿の追加を行い、現在の開発環境に合わせて完全にアップデートしました。Apache Solrは多様なプログラミング言語に対応した全文検索エンジンです。"}]}
もちろん、Node1からも検索可能です。
OKそうですね。