elasticsearch 2种客户端的区别

Java连接ElasticSearch详解

Java连接ES有两种连接方式(即获得ES的Client)

1、创建一个node,加入集群中,通过这个node获得client。

2、通过TransportClient来连接集群。

区别

第一种方式,相当于额外启动了一个es的node节点,只是这个node是由我们编码控制的,可以设置成这个node是不存数据的节点(没有特殊原因你就应该这么设置),这个节点的配置和其他的节点没有什么区别,也是通过elasticsearch.yml文件来配置,配置文件放在classpath目录下面,当然你也可以通过编程的方式,在构建node的时候,设置settings参数。

Settings settings = ImmutableSettings.settingsBuilder().put("client.transport.ping_timeout", 1000)
                .put("discovery.zen.ping.multicast.enabled", "false").put("timeout", 1)
                .putArray("discovery.zen.ping.unicast.hosts", "l-flightdev18.f.dev.cn0.qunar.com:9300", "l-flightdev17.f.dev.cn0.qunar.com:9300")
                .build();
        Node node = NodeBuilder.nodeBuilder().clusterName("flight_fuwu_order_index").client(true).settings(settings).node();
        Client client = node.client();

第二种方法,相当于获取了所有node节点的client,发送请求的时候遍历当前可用的client(这里可用指的是可以连接,但是node本身不一定可用,比如node正在恢复中,还没有加入集群,这会产生问题,见下面)。跟方法一相比,方法二会产生双跳(double hop),即当前遍历到node1,但访问的数据在node2,请求先发到node1,又由node1转发到node2。

遍历方式:每次请求通过AtomicInteger进行原子加1(超出最大值后设置成0),按当前可用client数取模。

获取当前可用client的方法:使用线程池,遍历所有client,如果client未连接,尝试一次连接,连接成功加入可用client中,如果client已连接直接加入可用client。

可以通过设置参数client.transport.sniff是否为true,来设置是使用SimpleNodeSampler还是SniffNodesSampler,默认值为false,即使用SimpleNodeSampler。

具体实现在org.elasticsearch.client.transport.TransportClientNodesService类中。

简单的说,SimpleNodeSampler会限制当前可用client一定是在配置中设置的节点中的,而SniffNodesSampler会使用所有发现的client,即使这个client的node,不在配置中。

Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name", clustersName).put(				"client.transport.ping_timeout", 1000).put("discovery.zen.ping.multicast.enabled", "false").put(				"timeout", 1)//				.put("client.transport.sniff", true)				.build();

		TransportClient transportClient = new TransportClient(settings);		for (String cluster : StringUtils.split(clusters,",")) {
			transportClient.addTransportAddress(new InetSocketTransportAddress("host1", 9300))
        .addTransportAddress(new InetSocketTransportAddress("host2", 9300));
		}

方法二有个问题,就是当集群中某个node挂掉之后,重新加入的时候,因为是通过判断client是否可以连接,而不是node是否可用,这会导致这个时候使用这个client发送请求的时候产生异常。而方法一不会,因为还没加入集群的node,对于自己创建的node来说是不可见的。

Elasticsearch本身是JAVA开发的,天生对JAVA的支持能力是最好的,所以用JAVA来开发Elasticsearch应该是一个不错的选择。可以把JAVA开发看出CS模式,客户端请求,服务端响应,所有的操作是完全异步的。此外在客户端上操作,很多的操作可以在客户端上来完成,增加了系统效率。JAVA客户端和服务端都是使用相同的程序。

配置

mvn仓库,在mvn项目中可以在pom.xml增加mvn仓库。

?


1

2

3

4

5

<dependency>

    <groupId>org.elasticsearch</groupId>

    <artifactId>elasticsearch</artifactId>

    <version>${es.version}</version>

</dependency>

打成独立的jar包。如果你想打成独立的jar包,并包含所有的依赖。不能使用mvn的maven-assembly-plugin插件,因为他不能很好的处理 META-INF/services结构。我们可以用 maven-shade-plugin插件来进行打包。例如:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<plugin>

    <groupId>org.apache.maven.plugins</groupId>

    <artifactId>maven-shade-plugin</artifactId>

    <version>2.4.1</version>

    <executions>

        <execution>

            <phase>package</phase>

            <goals><goal>shade</goal></goals>

            <configuration>

                <transformers>

                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>

                </transformers>

            </configuration>

        </execution>

    </executions></plugin>

如果你有一个main函数,可以通过调用java -jar yourjar.jar运行时,只需要在插件配置中加入一句话:例如:

?


1

2

3

<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">

    <mainClass>com.secisland.es.demo.main</mainClass>

</transformer>

可以使用多种方式来调用JAVA客户端。

  • 一种方式是把节点加入集群,不存储数据。
  • 另一种是把节点作为客户端连接到集群。

注意:客户端版本要和集群版本一致,否则有可能出现不可预知的错误。

嵌入式节点客户端

实例化一个基于节点的客户,这是对Elasticsearch执行操作的最简单的方法。例如:

?


1

2

3

4

5

6

import static org.elasticsearch.node.NodeBuilder.*;

// on startup

Node node = nodeBuilder().node();

Client client = node.client();

// on shutdown

node.close();

当你开始一个节点,它加入了一个Elasticsearch集群。你可以通过设置cluster.name来配置不同的集群,或显式使用clusterName方法来创建对象。在项目工程中可以定义cluster.name,配置在/src/main/resources/elasticsearch.yml文件中。只要在classpath中能找到elasticsearch.yml文件,节点启动的时候就会加载此文件。配置文件中定义:

?


1

cluster.name: secilog

或者在java代码中指定:

?


1

2

Node node = nodeBuilder().clusterName("secilog").node();

Client client = node.client();

使用客户端的好处是依赖Elasticsearch服务端的特性吧需要执行的操作自动路由到节点,当加入集群节点作为客户端时,最重要的是不能再此节点上增加数据保存,这可以通过配置来完成。把node.data设置为false或node.client设置true。这都可以通过NodeBuilder的方法来实现。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

import static org.elasticsearch.node.NodeBuilder.*;

// on startup

// 嵌入式节点可以不用打开http端口

Node node =

    nodeBuilder()

        .settings(Settings.settingsBuilder().put("http.enabled"false))

        .client(true)

    .node();

Client client = node.client();

// on shutdown

node.close();

另一个常见的客户端用处是用在单位/集成测试中。在这种情况下,只需要启动一个“本地(local)”节点。这里的local节点的意思是公用一个 Java虚拟机(JVM)。在这种情况下两个服务会互相发现自己并形成一个集群。例如:

?


1

2

3

4

5

6

7

8

import static org.elasticsearch.node.NodeBuilder.*;

// on startup

Node node = nodeBuilder().local(true).node();

Client client = node.client();

// on shutdown

node.close();

嵌入式节点的缺点:

  • 频繁启动和停止一个或多个节点在群集上会创建不必要的噪声。
  • 就像其他节点一样嵌入式节点客户端会响应外部请求。

注意:用eclipse开发的时候有可能会报错。

Exception in thread "main" java.lang.IllegalStateException: path.home is not configured

解决方法:在main方法的类中右键选择run configurations,在Arguments标签页下的vm arguments输入:-Des.path.home=-Des.path.home即可。比如:

?


1

-Des.path.home=D:\elasticsearch-2.2.0

通过连接的客户端

客户端通过TransportClient对象可以使用远程连接的方式连接Elasticsearch集群。这种情况下不用加入集群,比较像传统的CS程序的架构,比如数据库连接。例如:

?


1

2

3

4

5

6

7

// on startup

Client client = TransportClient.builder().build()

        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host1"), 9300))

        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host2"), 9300));

// on shutdown

client.close();

注意:如果群集名称不是“Elasticsearch”,你必须设置集群名称或者使用elasticsearch.yml配置文件在客户端工程中配置。可以连接一个集群中的多个节点。

?


1

2

3

Settings settings = Settings.settingsBuilder()

        .put("cluster.name""secilog").build();

Client client = TransportClient.builder().settings(settings).build();

你可以设置client.transport.sniff为true来使客户端去嗅探整个集群的状态,把集群中其它机器的ip地址加到客户端中,这样做的好处是一般你不用手动设置集群里所有集群的ip到连接客户端,它会自动帮你添加,并且自动发现新加入集群的机器。

?


1

2

3

Settings settings = Settings.settingsBuilder()

        .put("client.transport.sniff"true).build();

TransportClient client = TransportClient.builder().settings(settings).build();

其他参数说明

参数 描述
client.transport.ignore_cluster_name 设置为true的时候忽略连接节点时的群集名称验证。
client.transport.ping_timeout 等待一个节点的ping响应的时间,默认5秒。
client.transport.nodes_sampler_interval 监听和连接节点的频率,默认5秒。
时间: 2024-12-18 18:30:32

elasticsearch 2种客户端的区别的相关文章

虚拟机NetworkAdapter三种方式的区别

虚拟机在安装时默认的有三块网卡,VMnet1和VMnet8,另外还有VMnet0 Vmware 还提供了三种网络连接模式: 分别为: A 桥接bridge  B NAT 网络地址转换 C  主机模式 下面来简单说一下 三种方式的区别  : 1) bridge : 默认使用VMnet0,不提供DHCP服务 在桥接模式下,虚拟机和宿主计算机处于同等地位,虚拟机就像是一台真实主机一样存在于局域网中.因此在桥接模式下,我们就要像对待其他真实计算机一样为其配置IP.网关.子网掩码等等.当我们可以自由分配局

UIImage两种初始化的区别

UIImage可以通过以下两种方式进行初始化: 1 //第一种初始化方式:[注意使用这种初始化的时候如果是png格式的可以不给后缀名,根据屏幕的的分辨率去匹配图片] 2 UIImage *image = [UIImage imageNamed:@"v_red_heart_selected"]; 1 //第二种初始化方式:[必须拼接图片的全名称,否则image的路径为空] 2 NSString *filePath = [[NSBundle mainBundle] pathForResou

PHP中数组合并的两种方法及区别介绍

PHP数组合并两种方法及区别 如果是关联数组,如下: 复制代码代码如下: $a = array( 'where' => 'uid=1', 'order' => 'uid', ); $b = array( 'where' => 'uid=2', 'order' => 'uid desc', ); 1. array_merge,如果两个数组存在相同的key,后面的一个会覆盖前面的 复制代码代码如下: <?php $c = array_merge($a, $b); var_expo

《samba搭建win客户端和linux客户端的区别》

samba服务的搭建 客户的使用系统的不同也导致测试结果的不同. linux系统客户端: security = user or share smbclient -L //192.168.7.113/westos  都是可以看到共享目录的, 二者不同之处在于,   security = user 时 [[email protected] samba]# smbclient //192.168.7.113/westos Enter root's password: Anonymous login s

.NET中的三种Timer的区别和用法(转)

最近正好做一个WEB中定期执行的程序,而.NET中有3个不同的定时器.所以正好研究研究.这3个定时器分别是:  //1.实现按用户定义的时间间隔引发事件的计时器.此计时器最宜用于 Windows 窗体应用程序中,并且必须在窗口中使用.  System.Windows.Forms.Timer  // 2.提供以指定的时间间隔执行方法的机制.无法继承此类.  System.Threading.Timer  //3.在应用程序中生成定期事件.  System.Timers.Timer  这三个定时器位

UIimage两种初始化的区别 广告轮播封装

UIimage两种初始化的区别 第一种初始化: UIImage *image = [UIImage imageNamed:@"xxx"];  注意(这种方法加载的图片如果后缀名是png的,可以不写后缀名,根据屏幕分辨率自己去匹配图片) 第二种初始化: NSString *path = [[NSBundle mainBundle] pathForResource:@"xxx.png" ofType:nil]; UIImage *image = [[UIImage al

Activity的四种启动模式区别

(1) standard 模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中. (2) singleTop 如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例. (3)singleTask 如果在栈中已经有该Activity的实例,就重用该实例.重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈.如果栈中不存在该实例,将会创建新的实例放入栈中. (

定义c/c++全局变量/常量几种方法的区别(转载)

出自:http://www.cnblogs.com/yaozhongxiao/archive/2010/08/08/1795338.html 在讨论全局变量之前我们先要明白几个基本的概念:  1. 编译单元(模块): 在ide开发工具大行其道的今天,对于编译的一些概念很多人已经不再清楚了,很多程序员最怕的就是处理连接错误 (link error)  因为它不像编译错误那样可以给出你程序错误的具体位置,你常常对这种错误感到懊恼,但是如果你经常使用 gcc,makefile等工具在linux或者嵌入

jsp两种include指令区别

[转]:http://www.cnblogs.com/lazycoding/archive/2011/04/04/two_include.html <%@ include file="relativeURI"%> <jsp:include page="relativeURI" flush="true" /> 首先说明这两种都是什么: <%@ include file="relativeURI"%&