Elastic4s 是一个 scala 操作 ElasticSearch 的库,Github 地址为:elastic4s/samples/elastic4s-tcp-client-maven at master · sksamuel/elastic4s · GitHub,文档地址为:Elastic4s。本文记录利用 Elastic4s 将数据写入 ElasticSearch 时遇到的问题和解决方法。
1. 写入方式
1.1 HTTP 方式
import com.sksamuel.elastic4s.ElasticsearchClientUri
import com.sksamuel.elastic4s.http.HttpClient
import com.sksamuel.elastic4s.http.ElasticDsl._
// onComplete 异步支持
import scala.concurrent.ExecutionContext.Implicits.global
class HTTPDemo extends App {
val url = "localhost"
val port = 9200
val client = HttpClient(ElasticsearchClientUri(url, port))
client.execute {
bulk(
indexInto("myindex" / "mytype").fields("country" -> "Mongolia", "capital" -> "Ulaanbaatar"),
indexInto("myindex" / "mytype").fields("country" -> "Namibia", "capital" -> "Windhoek")
)
}.onComplete({
case _ => {
client.close()
}
})
}
1.2 TCP 方式
import com.sksamuel.elastic4s.ElasticsearchClientUri
import com.sksamuel.elastic4s.TcpClient
// 注意该 import 的变动
import com.sksamuel.elastic4s.ElasticDsl._
// onComplete 异步支持
import scala.concurrent.ExecutionContext.Implicits.global
class HTTPDemo extends App {
val url = "localhost"
val port = 9200
val clusterName = "mycluster"
// 主要区别在这里
val client = TcpClient.transport(s"elasticsearch://${url}:${port}?cluster.name=${clusterName}")
client.execute {
bulk(
indexInto("myindex" / "mytype").fields("country" -> "Mongolia", "capital" -> "Ulaanbaatar"),
indexInto("myindex" / "mytype").fields("country" -> "Namibia", "capital" -> "Windhoek")
)
}.onComplete({
case _ => {
client.close()
}
})
}
2. 问题及解决方法
2.1 使用 TCP 方法连接时遇到 available.processors 问题
报错信息为:
Getting availableProcessors is already set to [n], rejecting [n] IllegalStateException exception
解决方案为:
在调用 TCP 连接前,先执行:
System.setProperty("es.set.netty.runtime.available.processors", "false");
2.2 使用 TCP 连接一直超时
解决方案:
ElasticSearch 的配置中,默认会开启端口为 9200 的 HTTP 端口,以及端口范围为 9300~9400 的 TCP 端口。
对于远程连接而言,HTTP 需要增加配置 network.host: 0.0.0.0
;TCP 需要增加配置:transport.host: 0.0.0.0
具体配置可以参考官方文档:[Transport | Elasticsearch Reference [5.6] | Elastic](https://www.elastic.co/guide/...
publish_host
和 bind_host
之间的区别为:networking - What's the difference between bind_host and publish_host in ElasticSearch? - Stack Overflow
2.3 使用 TCP 连接时报错 NoNodeAvailableException
报错信息:
NoNodeAvailableException : None of the configured nodes are available
解决方法:
当我们采用默认集群名称时,即没有改变 cluster.name: xxx
配置时,可以使用如下方法建立 TCP 连接:
val url = "localhost"
val port = 9200
val client = HttpClient(ElasticsearchClientUri(url, port))
但当我们改变了集群名称的配置时,连接方式需要改为:
val url = "localhost"
val port = 9200
val clusterName = "mycluster"
val client = TcpClient.transport(s"elasticsearch://${url}:${port}?cluster.name=${clusterName}")
如果集群有多个节点,也可以配置为( 只配置其中一个节点也可以 ):
elasticsearch://host1:9300,host2:9300,host3:9300?cluster.name=my-cluster
2.4 jackson 方法缺失问题
报错信息:
Exception in thread “main” java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonFactory.xxx
解决方法:
在引用的各种依赖中,可能出现 jackson 各组件版本不匹配的问题。在这种情况下,我们需要在 pom.xml
中显式声明各组件的版本:
<jackson.version>2.8.8</jackson.version>
...
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
2.5 同步异步
在 Elastic4s 中,无论 HTTP 或是 TCP 连接,都可以指定调用方式为同步或是异步:
// 同步方式
client.execute {bulk}.await
// 异步方式
client.execute {bulk}
在同步异步的调用方式上,会导致以下几个问题:
2.5.1 异步调用是提示缺少引入
报错信息:
Cannot find an implicit ExecutionContext. You might pass an (implicit ec: ExecutionContext) parameter to your method or import scala.concurrent.ExecutionContext.Implicits.global.
解决方法:
import scala.concurrent.ExecutionContext.Implicits.global
2.5.2 在异步调用后立刻关闭连接导致数据没有写入
如果我们在使用异步方式时这么做:
client.execute {bulk}
client.close
会导致接口调用在未完成时就中断了,使得虽然没有报错或提示信息,但数据确实没有写入到 ES 中。
解决方案:
类似 ajax,我们可以使用如下方式完成接口调用完成后的资源回收:
client.execute {bulk}
.onComplete({
case _ => {
client.close()
}
})
2.6 日期格式问题
就查阅的资料,index 会将格式为:yyyy-MM-dd HH:mm:ss Z
或 yyyy-MM-dd Z
的字符串自动识别为日期格式,但就我在 5.6 版本的实验而言,在默认情况下,能够被识别为日期的字符串格式为:yyyy-MM-dd HH:mm:ss
或 yyyy-MM-dd
。
参考链接
- [Getting availableProcessors is already set to [1], rejecting [1] IllegalStateException exception - Elasticsearch - Discuss the Elastic Stack](https://discuss.elastic.co/t/...
- Elasticsearch 5.4.1 - availableProcessors is already set - Elasticsearch - Discuss the Elastic Stack
- How do I enable remote access/request in Elasticsearch 2.0? - Stack Overflow
- networking - What's the difference between bind_host and publish_host in ElasticSearch? - Stack Overflow
- NoNodeAvailableException None of the configured nodes are available: {127.0.0.1:9300} · Issue 972 · sksamuel/elastic4s · GitHub
- java - NoNodeAvailableException : None of the configured nodes are available - Stack Overflow
- elasticsearch 5.5使用TransportClient初始化抛异常 - CSDN博客
- Exception in thread "main" java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonFactory.requiresPropertyOrdering()Z - Stack Overflow
- Date datatype | Elasticsearch Reference 5.6 | Elastic
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。