加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Elastic遇到过的坑和解决办法

(2017-06-15 16:52:59)
标签:

elastic

分类: NoSql

说明:

本地开发环境下JDK1.7 , Elastic版本为2.1.1, 开发工具Eclipse,编程语言Java;

填坑一:Client获取超时,响应慢

1、场景:使用Jmeter压测一个Elastic查询数据接口时,出现失败请求过多,正常情况下应该是0,

2、debug描述和解决办法: 在实例化Elastic TransportClient客户端访问对象的时,采用了如下办法:

Settings settings = Settings.settingsBuilder()

.put("cluster.name",  es-cluster”) // 中心节点名称

.put("client.transport.sniff", true) // 客户端去嗅探整个cluster的状态

.build();

debug跟踪到代码如下一处时:

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

发现client迟迟无法返回,假死在这个地方,由此判断是这里出了问题,尝试办法去掉客户端嗅探状态这一行代码,再次压测,请求100%成功,问题解决。个人认为是如果启用的话,同一内网Ip段,嗅的方式自己查找,再组成集群供使用,这个过程肯定会耗时的。

 

填坑二:QueryStringQueryBuilder查询字母大小写问题

1、场景: 使用QueryStringQueryBuilder进行字段cname模糊包含查询时,数据是存在为前提,测试发现一个问题,比如输入西溪, 可以找出全部“西溪”相关的记录,但是输入“G193”,却检索不到数据;

2、debug描述和解决办法:

具体实现代码如下:

// 多条件查询

BoolQueryBuilder booleanQuery = QueryBuilders.boolQuery();

// 查询以keywords开头的数据

booleanQuery.must(new QueryStringQueryBuilder("*"+keywords.trim+"*").field("plot_name"));

 经查找相关资料获知,QueryStringQueryBuilder默认是启用把查询关键词中的大写英文字母转成小写字母来查询,所以导致带字母的包含查询查不到数据,解决办法是,QueryStringQueryBuilder提供了QueryStringQueryBuilder.

lowercaseExpandedTerms(boolean lowercaseExpandedTerms)的方法,将启用设置为false即可;

new QueryStringQueryBuilder("*"+

keywords.trim()+ "*").field("plot_name").lowercaseExpandedTerms(false);

 

填坑三:QueryBuilders.rangeQuery范围查询字段数据类型问题

1、场景: 针对价格price字段进行范围内查询,却一直无法查询到有效数据;

2、debug描述和解决办法:

   本人在项目中进行单元测试debug跟踪,发现拼接的查询条件完全没问题,把RequestBuilder生成的script语句放入到head插件中查询也没有检索到相关数据,很奇怪?

测试环境下的Elastic Mapping和数据都是另外一个同事搞的,发生这种怪问题, 我最终是在个人本地Elastic创建了Mapping和导入了几条测试数据,连接到本地Elastic,单元测试一看:数据都正常查询到了,回过头来对比了本地和线下测试的索引信息,竟发现原来价格price字段类型不一样,测试环境是string类型,个人本地是integer类型,这才是根本原因所在,所以在此建议创建索引Mapping的时候,一定要注意字段类型;

 

填坑四: Scroll拉取全部数据SearchContextMissingException

1、场景: 使用scrolls一次性拉取满足条件的全部数据;

2、debug描述和解决办法:

   通过查看Tomcat日志,异常如下:

Caused by: org.elasticsearch.search.SearchContextMissingException: No search context found for id [27419]

at org.elasticsearch.search.SearchService.findContext(SearchService.

at org.elasticsearch.search.SearchService.executeFetchPhase(SearchService.

at org.elasticsearch.search.action.SearchServiceTransportAction$SearchFetchByIdTr

ansportHandler.messageReceived(SearchServiceTransportAction.

at org.elasticsearch.search.action.SearchServiceTransportAction$SearchFetchB

yIdTransportHandler.messageReceived(SearchServiceTransportAction.

 at org.elasticsearch.transport.netty.MessageChannelHandler$RequestHandler

.run(MessageChannelHandler.

at

at

at ;

 

代码如下:

import static org.elasticsearch.index.query.QueryBuilders.*;

 

QueryBuilder qb = termQuery("multi", "test");

 

SearchResponse scrollResp = client.prepareSearch(test)

        .setSearchType(SearchType.SCAN)

        .setScroll(new TimeValue(60000))

        .setQuery(qb)

        .setSize(100).execute().actionGet(); //100 hits per shard will be returned for each scroll

//Scroll until no hits are returned

while (true) {

 

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

        //Handle the hit...

    }

    scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();

    //Break condition: No hits are returned

    if (scrollResp.getHits().getHits().length == 0) {

        break;

    }

}

 

编写代码参照2.1.1 Java API,以上是官网给出的代码,为何执行结果在压测的情况下,会出现以上异常问题?经过对比了elastic 5.1给出的scrolls查询方式,代码如下:

 

import static org.elasticsearch.index.query.QueryBuilders.*;

 

QueryBuilder qb = termQuery("multi", "test");

 

SearchResponse scrollResp = client.prepareSearch(test)

        .addSort(FieldSortBuilder.DOC_FIELD_NAME, SortOrder.ASC)

        .setScroll(new TimeValue(60000))

        .setQuery(qb)

        .setSize(100).get(); //max of 100 hits will be returned for each scroll

//Scroll until no hits are returned

do {

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

        //Handle the hit...

    }

 

    scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();

} while(scrollResp.getHits().getHits().length != 0); // Zero hits mark the end of the scroll and the while loop.

 

通过代码对比发现,2.1.1 API获取游标滚动的scrollResp 是放在while循环外一层,而5.1 API给出的游标滚动是在不停移动位置获取下一次的游标对象的,经过对比可以判断,两者获取完全不一样,将2.1.1代码改成5.1 Scroll方式,再压测发现异常信息不会出现。思考:这个问题,有可能是2.1.1版本存在的一个bug。

 

 

 

 

 

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有