ELK Tips 主要介绍一些 ELK 使用过程中的小技巧,内容主要来源为 Elastic 中文社区。
一、Logstash
1、Logstash 性能调优主要参数
pipeline.workers
:设置启动多少个线程执行 fliter 和 output;当 input 的内容出现堆积而 CPU 使用率还比较充足时,可以考虑增加该参数的大小;pipeline.batch.size
:设置单个工作线程在执行过滤器和输出之前收集的最大事件数,较大的批量大小通常更高效,但会增加内存开销。输出插件会将每个批处理作为一个输出单元。;例如,ES 输出会为收到的每个批次发出批量请求;调整pipeline.batch.size
可调整发送到 ES 的批量请求(Bulk)的大小;pipeline.batch.delay
:设置 Logstash 管道的延迟时间, 管道批处理延迟是 Logstash 在当前管道工作线程中接收事件后等待新消息的最长时间(以毫秒为单位);简单来说,当pipeline.batch.size
不满足时,会等待pipeline.batch.delay
设置的时间,超时后便开始执行 filter 和 output 操作。
2、'reader' unacceptable character ' ' (0x0)
logstash 执行使用 Jdbc input plugin
后报错:
[main]-pipeline-manager] ERROR logstash.agent - Pipeline aborted due to error {
:exception=>#<Psych::SyntaxError: (): 'reader' unacceptable character ' ' (0x0) special characters are not allowed in "'reader'",
position 0 at line 0 column 0>, :backtrace=>["org/jruby/ext/psych/PsychParser.java:232:in parse'"
解决方案:删除 $USER_HOME/.logstash_jdbc_last_run
文件即可。
二、Elasticsearch
1、TermsQuery 与多个 TermQuery 的区别
当 terms 的个数较少的时候,TermsQuery 等效为 ConstantScoreQuery 内部包含多个 TermQuery:
Query q1 = new TermInSetQuery(new Term("field", "foo"), new Term("field", "bar"));
// 等效为下面的语句
BooleanQuery bq = new BooleanQuery();
bq.add(new TermQuery(new Term("field", "foo")), Occur.SHOULD);
bq.add(new TermQuery(new Term("field", "bar")), Occur.SHOULD);
Query q2 = new ConstantScoreQuery(bq);
当 terms 较多的时候,它将使用匹配的文档组合成一个位集,并在该位集上进行评分;此时查询效率比普通的 Bool 合并要更加高效。
当 terms 的个数较多时,TermsQuery 比多个 TermQuery 组合的查询效率更高。
2、ES 借助 nginx 配置域名
upstream /data/ {
server 192.168.187.xxx:9200;
keepalive 300 ;
}
server {
listen 80;
server_name testelk.xx.com;
keepalive_timeout 120s 120s;
location /data {
proxy_pass http://data/;
proxy_http_version 1.1;
proxy_set_header Connection "Keep-Alive";
proxy_set_header Proxy-Connection "Keep-Alive";
proxy_set_header X-Real-IP $remote_addr;
proxy_pass_header remote_user
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
}
}
3、ES Reindex 时如何不停止写入服务
方案一:kennywu76
ES 的 reindex 在索引有实时的 update/delete 的情况下,即使借助 alias,也没有办法实现真正的 zero down time。
增加新文档比较好办,通过 alias 切换写入到新索引,同时 reindex 做旧->新索引的数据传输即可;但是 update/delete 操作针对的文档如果还未从旧索引传输过来,直接对新索引操作会导致两个索引数据不一致。
我能够想到的(一个未经实际验证)的方案,前提是数据库里的文档有一个类似 last_update_time
字段记录文档最后更新的时间,用作写入 ES 文档的版本号,然后数据写入新索引的时候,url 里带上下面这样的参数:version_type=external_gt&version=xxxxxx
。
其中 version_type=external_gt
表示写入文档的版本号大于已有的文档版本号,或者文档不存在,写入才会成功,否则会抛版本冲突的异常。另外 delete 操作都要转换成 index 操作,index 的内容可以是一个空文档。
这样实时数据写入新索引和 reindex 可以同时进行,实时写入的数据应该具有更高的版本,总是能够成功,reindex 如果遇到版本冲突,说明该文档被实时部分更新过了,已经过时,可以直接放弃跳过。
该方案的缺陷:
- 要求数据源里的数据具有版本信息,可能因为各种局限,不太容易更改;
- delete 操作必须转化为写入一个空文档,delete 实际上是一个标记文档,并且本身也有版本信息。但是如果后端发生了 segment merge,delete 可能会被合并以后物理清除。这样 delete 和对应的版本信息丢失,之后 reindex 如果写入了旧版本的文档,仍然会有一致性问题;但是空文档会增加索引文件的大小,有额外的消耗,一个可能的缓解办法是在 reindex 全部做完以后,再做一次空文档的删除。
改进方案:the_best
重建索引步骤如下:
- 保证 delete 操作都要转换成 index 操作,index 的内容可以是一个空文档;
- 对老索引
old_index
(业务上的别名还是挂在老索引上)进行重索引操作(version_type=external
);curl -X POST 'http://<hostname>:9200/_reindex' { "conflicts": "proceed", "source": { "index": "old_index", "size": 1000 }, "dest": { "index": "new_index", "version_type": "external" } }
- 将别名切到 newIndex;
- 将重索引时间段内
old_index
产生的热数据,再捞一次到new_index
中(conflicts=proceed&version_type=external
);curl -X POST /_reindex { "conflicts": "proceed", "source": { "index": "old_index" "query": { "constant_score" : { "filter" : { "range" : { "data_update_time" : { "gte" : <reindex开始时刻前的毫秒时间戳> } } } } } }, "dest": { "index": "new_index", "version_type": "external" } }
- 手动做一次空文档的删除。
这种方式取决于重索引期间产生的数据量大小(会影响步骤4的用时),不过我们可以视具体业务情况灵活操作。比如说数据量比较大重索引我们用了10个小时(这10个小时内新产生了200多万的数据),在切别名前,我们可以按步骤(4)的调用方式,把近10个小时的数据再捞一遍到新索引中,如此迭代个几次,直到别名切完后,我们能保证最后一次的步骤(4)可以在较短时间内完成。
4、ES 节点通讯配置
http.port: 9200
http.bind_host: 127.0.0.1
transport.tcp.port: 9300
transport.bind_host: 127.0.0.1
5、把 Lucene 的原生 query 传给 ES
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(typeName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.from(0);
sourceBuilder.size(10);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//q为Lucene检索表达式, 直接输入关键词匹配_all或者*字段, 字段匹配user:kimchy,
//多字段匹配user:kimchy AND message:Elasticsearch
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(q);
sourceBuilder.query(queryStringQueryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
SearchHits searchHits = searchResponse.getHits();
6、ES 文档字段个数限制
ES 文档默认不允许文档字段超过 1000,超过 1000 会报如下错误:
failed to put mappings on indices [[[nfvoemspm/srjL3cMMRUqa7DgOrYqX-A]]], type [log]
java.lang.IllegalArgumentException: Limit of total fields [1000] in index [xxx] has been exceeded
可以通过修改索引配置来修改字段个数限制,不过还是推荐从业务上进行优化:
修改settings
{
"index.mapping.total_fields.limit": 2000
}
7、将 DSL 字符串转换为 QueryBuilder
## wrapper 案例
GET /_search
{
"query" : {
"wrapper": {
"query" : "eyJ0ZXJtIiA6IHsgInVzZXIiIDogIktpbWNoeSIgfX0="
}
}
}
## RestClient
QueryBuilders.wrapperQuery("{\"term\": {\"field\":\"value\"}}")
8、ES 集群重启后 Slice Scroll 速度变慢
重启机器之后,pagecache 都没有了,所有数据都要重新从磁盘加载。
9、ES 开启索引新建删除日志
PUT _cluster/settings
{
"persistent": {
"logger.cluster.service": "DEBUG"
}
}
10、慢日志全局级别设定
- 对已经存在的索引可以通过 PUT _settings 做存量设置
- 对之后新增的索引,可以使用类似于下面的template
PUT _template/global-slowlog_template { "order": -1, "version": 0, "template": "*", "settings": { "index.indexing.slowlog.threshold.index.debug" : "10ms", "index.indexing.slowlog.threshold.index.info" : "50ms", "index.indexing.slowlog.threshold.index.warn" : "100ms", "index.search.slowlog.threshold.fetch.debug" : "100ms", "index.search.slowlog.threshold.fetch.info" : "200ms", "index.search.slowlog.threshold.fetch.warn" : "500ms", "index.search.slowlog.threshold.query.debug" : "100ms", "index.search.slowlog.threshold.query.info" : "200ms", "index.search.slowlog.threshold.query.warn" : "1s" } }
11、TCP 设置多个端口的用途
transport.tcp.port
这个参数不写,默认为9300-9399
,开放那么多 端口有用么?
- 如果设置一个端口,假设这个端口占用了程序就无法正常启动;
- 如果设置多个端口,一个端口占用会寻找下一个端口,直至找到可用端口。
12、ES 临时重启,设置分片延迟分配策略
PUT _all/_settings
{
"settings": {
"index.unassigned.node_left.delayed_timeout": "5m"
}
}
三、Kibana
1、kibana 图表自定义标注
可以用 TSVB,支持标注。
Kibana TSVB 注解的使用:https://elasticsearch.cn/article/701
2、Kibana discover 导出 csv 文件
请参考文章:如何快速把 Kibana Discover 页的 Document Table 导出成 CSV
3、修改 kibana 的默认主页
四、社区文章精选
Any Code,Code Any!
扫码关注『AnyCode』,编程路上,一起前行。
本文地址:http://elasticsearch.cn/article/6395