es客户端分为两中模式:
节点客户端(Node client)
节点客户端作为一个非数据节点加入到本地集群中。换句话说,它本身不保存任何数据,但是它持有数据分片的路由表,它知道数据在集群中的哪个节点中,并且可以把请求转发到正确的节点,这种客户端模式下,需要维持一些与集群本身通信的连接,但是使用这种模式数据的查询和索引是最快的。
传输客户端(Transport client)
轻量级的传输客户端可以将请求发送到远程集群。它本身不加入集群,但是它可以将请求转发到集群中的一个节点上,使用这种模式存在“双跳”的现象,就是请求先发给节点A,节点A再将请求转发到数据所在分片的节点B。
如果我们到集群的连接很少,并且需要保持长时间的连接状态那么这个时候可以考虑使用节点客户端。
如果我们到集群的连接数据很多,并且连接的寿命都不长,我们可以考虑使用传输客户端。
这里是elasticsearch-2.1.0 java客户端api的英文文档,文档相对比较简单,建议有疑问的读者可以在这里查询相关api的使用。
elasticsearch-2.1.0 java客户端api英文文档
这里是我的es客户端工具类:
/**
* es客户端工具类
* @author yujie.wang
*
*/
public class GenEsClient {
//节点客户端
private Client nodeClient = null;
//传输客户端
private Client transClient = null;
//es机器列表
private String HOST_IPS = "10.4.30.151,10.4.30.81";
private String ES_HOST_81 = "10.4.30.81";
private String ES_HOST_151 = "10.4.30.151";
//es集群的名称
private String CLUSTER_NAME = "yujie-es-30-151";
public static void main(String [] args){
GenEsClient client = new GenEsClient();
client.genTransportClient();
}
public Client getNodeClient(){
if(nodeClient == null){
synchronized(GenEsClient.class){
if(nodeClient == null){
nodeClient = genNodeClient();
}
}
}
return nodeClient;
}
public Client getTransClient(){
if(transClient == null){
synchronized(GenEsClient.class){
if(transClient == null){
transClient = genTransportClient();
}
}
}
return transClient;
}
/**
* 节点客户端加入es集群,但是通过client(true)设置客户节点不保存数据,也不被选为主节点
* 因为这个客户端加入了集群,所以它持有当前集群的所有索引和分片信息,所有能直接路由到数据所在机器分片
* @return
*/
public Client genNodeClient(){
Settings settings = Settings
.settingsBuilder()//
.put("cluster.name", CLUSTER_NAME)//
.put("action.auto_create_index", false)//
.put("network.host", "10.4.30.151")
.put("discovery.zen.ping.multicast.enabled", false)//禁用多播 防止有机器意外加入集群
.put("discovery.zen.ping.unicast.hosts", HOST_IPS)//提供单播机器列表
.put("transport.tcp.port", "9300-9400")//
.build();
Node node = NodeBuilder.nodeBuilder().client(true).settings(settings).node();
return node.client();
}
/**
* 传输客户端不加入集群,它只是随机跟提供的es集群地址进行通信,因为他不知道数据所在具体机器和分片信息
* 所以使用传输客户端存在“双跳”的信息,意思就是请求先发个集群A机器,A机器再将请求转发给数据所在机器
*/
public Client genTransportClient(){
Client client = null;
try {
Settings settings = Settings.settingsBuilder()
.put("cluster.name", CLUSTER_NAME).build();
client = TransportClient.builder().settings(settings).build()
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByAddress(getByteAddress(ES_HOST_81)), 9300))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByAddress(getByteAddress(ES_HOST_151)), 9300));
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return client;
}
public byte [] getByteAddress(String ip){
byte [] ips = new byte[4];
if(ip != null){
String [] result = ip.split("\\.");
int i = 0;
for(String res : result){
ips[i++] = (byte)(Integer.valueOf(res)&0xff);
}
}
return ips;
}
}
使用上述工具类 来从es中读取一个文档
/**
* es 测试类
* @author yujie.wang3
*
*/
public class EsCDUQOperator {
//es索引
private static String INDEX = "megacorp";
//索引megacorp下的类型
private static String TYPE = "employee";
public static void main(String [] args){
GenEsClient client = new GenEsClient();
EsCDUQOperator es = new EsCDUQOperator();
if(args.length >= 1 && "node".equals(args[0])){
System.out.println("genNodeClient");
es.getDocument(client.getNodeClient(), INDEX, TYPE, "4");
}else {
System.out.println("indexgenTransportClient");
es.getDocument(client.genTransportClient(), INDEX, TYPE, "4");
}
}
/**
* 从索引index中类型为type中获得一个文档 id:id
* @param client
* @param index
* @param type
* @param id
*/
public void getDocument(Client client,String index,String type, String id){
GetResponse response = client.prepareGet(index, type, id).get();
System.out.println(response.getId() + response.getIndex() + response.getType() + response.getVersion()
+ response.getSourceAsString());
}
}
将代码部署到10.4.30.151机器上运行输出如下结果: