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 操作.
二, 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 https://elasticsearch.cn//article/35
3, 修改 kibana 的默认主页
https://elasticsearch.cn/article/6335
四, 社区文章精选
Elasticsearch 6.6 Index Lifecycle Management 尝鲜 https://mp.weixin.qq.com/s/Xj8J7FEO-TpOdE0fjirrOw
Hive 与 Elasticsearch 的数据交互 https://mp.weixin.qq.com/s/HR2lCtlcKpDQYmVDnZpeug
Any Code,Code Any!
来源: https://juejin.im/post/5c6e0ccee51d45578d376a04