Elasticsearch Query DsL查询


Query DsL查询

一 Elasticsearch简介

Elasticsearch 是一个开源的搜索引擎,Elasticsearch 使用 Java 编写的,它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单, 通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。

  • 一个分布式的实时文档存储,每个字段 可以被索引与搜索
  • 一个分布式实时分析搜索引擎
  • 能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据

 

二 安装并运行

已经在其他文档中详细介绍,此次仅做简单步骤介绍

# 安装:
$   wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.13.3-linux-x86_64.tar.gz
$   tar -xzf elasticsearch-7.13.3-linux-x86_64.tar.gz 
$   cd elasticsearch-7.13.3/
# 运行
sh bin/elasticsearch

# 访问
$ curl http://192.168.3.14:9200/ 
{
  "name" : "87DNZWU",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "e3A3l85MSZuZlRhxj6IB2w",
  "version" : {
    "number" : "6.7.0",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "8453f77",
    "build_date" : "2019-03-21T15:32:29.844721Z",
    "build_snapshot" : false,
    "lucene_version" : "7.7.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

 

三 Query DSL 基本结构

查询表达式(Query DSL)是一种非常灵活又富有表现力的查询语言, Elasticsearch 使用它可以以简单的 JSON 接口来展现 Lucene 功能的绝大部分

// 查询
GET /_search  // 查找整个ES中所有索引的内容
{
  "query": {}, //具体的查询语句对象
  "from": 0,   //从第几条数据开始返回
  "size": 100, //返回的条数 默认ES最多返回10000条
  "highlight": { //高亮
    "pre_tags": {}, //高亮内容的前面标签 一般都是html比如<b> <p>这种
    "post_tags": {},//高亮内容的后面标签 一般都是html比如</b> </p>这种
    "fields": { //需要高亮的字段
    }
  },
  "sort": [{ //排序
    "FIELD": { //排序的字段(需要填上具体的字段名)
      "order": "desc"
    }
  }],
  "_source": "{field}" //指定返回的字段
}

// 结果
{
    "took": 350,  // 整个搜索请求消耗了多少毫秒
    "timed_out": false, // 表示本次查询是否超时,如果为true也会返回结果,只是数据可能不完整
    "_shards": { //  显示查询中参与的分片信息,成功多少分片失败多少分片等
        "total": 5, 
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 5, // 匹配到的文档总数
        "max_score": 1, // 为文档中所有_score的最大值
        "hits": [
            {
                "_index": "mysql-shop_trades-order_item_label_binds",
                "_type": "doc",
                "_id": "591935",
                "_score": 1,
                "_source": {
                    "id": 591935,
                    "updated_at": "2021-05-20T06:26:09.000Z",
                    "@version": "1",
                    "bind_item_label_id": 729,
                    "label_type": "brand",
                    "created_at": "2021-05-20T06:26:09.000Z",
                    "@timestamp": "2021-07-07T07:31:36.262Z",
                    "is_deleted": 0,
                    "table_name": "order_item_label_binds",
                    "bar_code": "6907925004486"
                }
            }
        ]
    }
}

 

四 指定索引搜索

 

上述查询会搜索ES中的所有索引,但通常只需要去固定一个或几个索引中搜索,搜索全部无疑会造成资源的浪费,在ES中可以通过以下几种方法来指定索引

  1. 指定一个固定的索引,ops-coffee-nginx-2019.05.15为索引名字
GET /mysql-shop_trades-order_statics/_search

以上表示在mysql-shop_trades-order_statics索引下查找数据

  1. 指定多个固定索引,多个索引名字用逗号分割
GET /mysql-shop_trades-order_statics,mysql-shop_trades-order_item_labels/_search

  1. 用*号匹配,在匹配到的所有索引下查找数据
GET /mysql-shop_trades-*/_search

这里也可以用逗号分割多个匹配索引

五 DSL查询

1、筛选字段

// 筛选_source的数据,单个字段
GET /_search
{
  "_source": "bar_code",  
  "query": {}
}

// 筛选_source的数据,多个字段
{
  "_source": {
    "includes": ["store_id", "sku_id"]
  },
  "query": {}
}

// 对字段进行转换
{
  "docvalue_fields": [
    {
      "field": "updated_at",
      "format": "yyyy-MM-dd HH:mm:ss"
    },
    {
      "field": "num",
      "format": "long" // 没有作用,懵逼...
    }
  ], 
  "query": {}
}

 

2、多条件查询 (where)

  1. constant_score:装另一个查询的查询,固定分数查询,支持filter查询,不支持match查询:
    {
        "constant_score": {
            "filter": {
                "match": {
                    "name": "小米"
                }
            },
            "boost": 10
        }
    }
    

     

  2. bool:主要与其他关键字组合使用,多条件的查询必须要用bool包在外层,然后再根据具体的业务来拼接。

{
  "query": {
    "bool": {
      "should": [{}], //满足其中一个对象查询条件就行 像sql里的or
      "must": [{}],   //必须满足所有对象的查询条件 就像sql里的and
      "must_not": [{}] //必须不满足所有对象的查询条件 就像sql里的and !=
    }
  }
}

 

  1. must: 类似于SQL中的AND,必须包含
  2. must_not: 类似于SQL中的NOT,必须不包含
  3. should: 满足这些条件中的任何条件都会增加评分_score,不满足也不影响,should只会影响查询结果的_score值,并不会影响结果的内容
  4. filter: 与must相似,但不会对结果进行相关性评分_score,大多数情况下我们对于日志的需求都无相关性的要求,所以建议查询的过程中多用filter

3、group by:

ES本身没有group关键词搜索,但支持聚合查询,,需要使用关键字aggs

// 单个字段 group by
{
  "query":{},//这里省略你的查询条件
  "aggs": {
    "age_group": {//这个是指你要返回字段名
      "terms": { //这里还可以用其它关键词 这里terms才能实现group by效果
        "field": "age",//groupby的字段
        "size":1 //返回的条数 相当于group by limit
      }
    }
  }
}

// 多字段group by (如 group by sku_id,store_id)
// 方法一:script
{
  "query":{},
  "aggs": {
    "age_group": {
      "terms": {
        "script":{
          "source": """ 's' + doc['store_id'] + '_s' + doc['sku_id'] """,
          "lang": "painless"
        },
        "size": 10
      }
    }
  }
}

// 方法二:copy to
1. 设置mapping中的多个字段,copy_to 为同一个字段(skuId_storeId)
2. 搜索新字段
{
  "query":{},
  "aggs": {
    "list": {
      "terms": { 
        "field": "skuId_storeId
        "size":1
      }
    }
  }
}

// 方法三:multi_terms (使用高版本,目前6.7不支持)
{
  "aggs": {
    "genres_and_products": {
      "multi_terms": {
        "terms": [{
          "field": "genre" 
        }, {
          "field": "product"
        }]
      }
    }
  }
}

4、order by

order by:注意日期格式和数值格式才支持排序;文本不支持,如果要排序, 需把字段设置为not analysis

// 单排序
{
    "query": {
        "sort": {
            "id": "desc"
        }
    }
}

// avg按照平均值排序
{
    "query": {
        "sort": [
            {
                "id": "desc"
            },
            {
                "price": {
                    "order": "asc",
                    "mode": "avg"
                }
            }
        ]
    }
}

5、count(distinct)

{
  "query":{},
  "aggs": {
    "total_sku_id": {
      "cardinality":{ "field": "sku_id"}
    },
     "total_entity_store_id": { // 非数字类型,无法使用field排序,可以对field增加fieldData = true,或者对field.keyword排序,建议使用后者,高效内存消耗低
      "cardinality":{ "field": "entity_store_id.keyword"}
    }
  }
}

 

6、SUM

{
  "query":{},
  "aggs": {
    "total_pay_num": {
      "sum": {"field": "num"}
    },
     "total_cost_fee": {
      "sum": {"field": "cost_fee"}
    }
  }
}

 

7、distinct :

select distinct(id) from table

{
  "query":{},
  "collapse": {
      "field": "id" //你需要distinct的字段
   }, 
}

 

8、limit

1. 分页:
    1. form:从第几个开始查询,最开始是0
    2. size:即limit
    3. 使用size,size最大可获取数量是xx个
2. 获取所有数据的三种方式
    1. scroll深度滚动需要根据scroll_id和循环取,取完后,需删除scroll,减小内存开销(深度滚动高效,用于处理大量数据,不适合实时获取)
    2.调整索引index.max_result_window的大小,默认10000 (大小与堆内存成正比,这个限制内存)
    3.search_after:请求需增加前一个结果的排序,(实时游标,可根据索引更新和删除而改变 )
    4。 如果是group by查询获取所有数据, 获取需要使用到cardinality查询预估总数,再使用partition、num_partitions分区依次获取数据

9、搜索关键字

  1. match:自定字段,根据字段关键字进行搜索,会分割关键词,匹配到含有一个多多个词的匹配
  2. query_string:全文搜索
  3. match_phrase:不分割关键词 {"match_phrase": {"name":"婴幼儿奶粉"}}
  4. term: 类似SQL where field = x,主要用于数字匹配;如果要匹配文本,会自动分词,不能精准查询,需把字段设置成not analysis
    {
      "query": {
        "term": {"bind_item_label_id": 729}
      }
    }
    

     

  5. terms: 类似SQL where field in (x,x),主要用于数字匹配,
    {
      "query": {
        "terms": {"bind_item_label_id": [703,729]}
      }
    }
    

     

  6. range:: 查询价格在1000-2000的商品
{
    "query": {
        "range": {
            "price": {
                "gte": 1000,
                "lte": 2000
            }
        }
    }
}

 

  1. filter:判断文档是否满足条件
{
    "query": {
        "bool": {
            "filter": {
                "term": {
                    "price": 1999
                }
            }
        }
    }
}

Elasticsearch:Aggregation

  1. metric:度量聚合,主要针对number类型的数据,需要es做较多的计算工作(类似SQL的SUM、MAX、AVG、MIN、Cardinality、stats<属于多值分析>等)
  2. bucket:桶聚合,划分不同步的桶,将数据分配到不同的桶,(类似SQL中的group by)
  3. Pipeline Aggregation:管道分析类型,对其他聚合结果进行二次聚合
  4. Matrix Aggregation:矩阵分析类型,支持对多个字段的操作并提供一个结果矩阵

term aggregation

  • size 可以通过size返回top size的文档,该术语聚合针对顶层术语(不包含嵌套词根),其搜索过程是将请求向所有分点发送请求,每个分片节点返回size条数据,然后聚合所有分片的结果(会对各分片返回的同样词根的数数值进行相加),最终从中挑选size条记录返回给客户端。从这个过程也可以看出,其结果并不是准确的,而是一个近似值。
  • Shard Size 为了提高该聚合的精确度,可以通过shard_size参数设置协调节点向各个分片请求的词根个数,然后在协调节点进行聚合,最后只返回size个词根给到客户端,shard_size >= size,如果shard_size设置小于size,ES会自动将其设置为size,默认情况下shard_size建议设置为(1.5 * size + 10)。
// 单个字段 group by
{
  "query":{},//这里省略你的查询条件
  "aggs": {
    "age_group": {//这个是指你要返回字段名
      "terms": { //这里还可以用其它关键词 这里terms才能实现group by效果
        "field": "age",//groupby的字段
        "size":1 //返回的条数 相当于group by limit
      }
    }
  }
}

// 返回结果格式
{
  ...
  "aggregations" : {
      "list" : {
        "doc_count_error_upper_bound" : 0, // 该值表示未进入最终术语列表的术语的最大潜在文档计数
        "sum_other_doc_count" : 90 // 该值表示未进入最终术语列表的术语的最大潜在文档计数
        "buckets" : [ // 返回doc_count排名最前的10个,受size参数的影响
          {
            "key" : "1",
            "doc_count" : 24,
            "total_refund_fee" : {
              "value" : 0.0
            },
            "total_cost_fee" : {
              "value" : -14976.0
            },
          }
        ]
      }
    }
    }
}

 

 

match_phrase :查询分析文本,创建词组查询

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html#query-dsl-match-query-phrase

 

 

举例子

GET mysql-shop_trades-order_item_label_binds/_search/?scroll=1m
{
  "docvalue_fields": [
    {
      "field": "updated_at",
      "format": "yyyy-MM-dd HH:mm:ss"
    }
  ], 
  "size": 1000,
  "sort": {"id":"desc"},
  "query": {
    "bool": {
      "must": [
        {"match": {"is_deleted": 0}},
        {"match": {"label_type": "brand"}},
        {
          "constant_score": {
            "filter": {
              "terms": {
                "bind_item_label_id": [703, 2, 729]
                }
              }
            }
        }
      ]
    }
    }
}




GET mysql-shop_trades-order_item_label_binds/_search/?scroll=1m
{
  "_source": "bar_code", 
  "query": {
    "bool": {
      "filter": [
        {"match": {"is_deleted": 0}},
        {"match_phrase": {"label_type": "brand"}},
        {"terms": {"bind_item_label_id": [703, 2, 729]}}
      ]
    }
  },
  "aggs": {
    "bar_code_group": {
      "terms": {
        "field": "bar_code.keyword",
        "size": 10 
      }
    }
  }
}


GET mysql-shop_trades-order_item_label_binds,mysql-shop_trades-order_statics/_search
{
  "query": {
    "bool": {
      "filter": [
        {"match_phrase": {"sys_name": "yiqigou"}},
        {"range": {"num": {"lte": 2000}}},
        {"range": {"return_num": {"gte": -1000}}},
        {"range": {"total_price": {"lte": 1000000}}},
          {"match": {"id": 60}},
        {"term": {"order_type": 0}},
        {"term": {"item_type": 0}},
        {"range": {"date": {
          "gte": "2020-01-21 00:00:00",
          "lte": "2021-07-22 00:00:00",
          "format": "yyyy-MM-dd HH:mm:ss",
          "time_zone": "+08:00"
        }}}
      ],
      "must_not": [
        {"terms": {"store_id": [165]}}
      ]
    }
  }
}

 

 

设置fieldData

// 第一步,创建索引 (如果已经有索引,直接看第二步)
PUT mysql-shop_trades-order_statics2
{
  "mappings": {
    "_doc": {
      "properties": {
        "entity_store_id": { 
          "type": "text",
          "fields": {
            "keyword": { 
              "type": "keyword"
            }
          }
        }
      }
    }
  }
}

// 第二步 设置fieldData为true
PUT mysql-shop_trades-order_statics/_mapping/_doc
{
  "properties": {
    "entity_store_id": {
      "type":     "text",
      "fielddata": true
    }
  }
}

// 第三步 可以查看该索引的Mapping结构,fieldData是否加上去
{
  "mapping": {
    "doc": {
      "properties": {
        "entity_store_id": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          },
          "fielddata": true
        }
      }
    }
  }
}

延伸

 

 

设置 max_result_window

PUT /mysql-shop_trades-order_statics/_settings
{
  "index": {
    "max_result_window": 100000
  }
}

 

Elasticsearch SQL

介绍

ES SQL 是x-pack的一个组件,它提供了一个到Elasticsearch的SQL接口,可以针对ES索引执行实时的SQL查询,轻松实时大规模的查询和处理数据,并以表格格式返回结果。它相当于一种翻译器,使用将sql语句转换为DSL语句,再搜索elasticsearch数据

SQL与Elasticsearch的映射关系

(只列常用的)

在 Elasticsearch 中,可用的索引集被分组在一个cluster,一个实例只有一个目录 |

SELECT语法

​ 同sql语法基本一致,基本所有的sql语法都支持

# select
SELECT [TOP [ count ] ] select_expr [, ...]
[ FROM table_name ]
[ WHERE condition ]
[ GROUP BY grouping_element [, ...] ]
[ HAVING condition]
[ ORDER BY expression [ ASC | DESC ] [, ...] ]
[ LIMIT [ count ] ]
[ PIVOT ( aggregation_expr FOR column IN ( value [ [ AS ] alias ] [, ...] ) ) ]

注意:

  1. FROM :目前只支持一张表,不支持连表查询,table_name可以是一个索引,也可以是一个模式(子语句、正则匹配的索引)
  2. WHERE: 从查询中过滤行,如果指定了子句,所有不满足条件的都将从输出中删除
  3. GROUP BY:如果指定了子句或者存在聚合函数调用,则输出将组合成匹配一个或多个值的行组,并计算聚合函数的结果,如果该HAVING子句存在,它将消除不满足给定条件的组
  4. 使用SELECT每个选定行或行组的输出表达式计算实际输出行,可以使用通配符*返回所有的列
  5. 如果ORDER BY指定了子句,则返回的行按指定的顺序排序。如果ORDER BY未给出,则以系统发现最快生成的任何顺序返回行
  6. 如果指定了LIMITor TOP(不能在同一个查询中同时使用两者),则该SELECT语句仅返回结果行的一个子集

缺点:

  1. 不支持复杂的sql: select count(distinct(field1, field2)),可以使用group by替代
  2. 但不支持连表查询,需分表查询

ES SQL 执行方式

  1. 在kabana console 面板中执行sql语句(经常用于调试)
// 方式一:直接搜索sql
GET _sql?format=json
{
"query": """
SELECT *  FROM "mysql-shop_trades-order_statics" where store_id = 165
"""
}

// 方式二:先将sql转换为DSL语句,再通过DSL语句查询结果,这样得到的数据格式比较清晰
// sql转换成DSL语句
GET _sql/translate
{
"query": """
SELECT *  FROM "mysql-shop_trades-order_statics" where store_id = 165
"""
}

// 使用DSL语句查询

GET /mysql-shop_trades-order_statics/_search
{
"size" : 100,
"query" : {
"term" : {
"store_id" : {
"value" : 165,
"boost" : 1.0
}
}
},
"sort" : [
{
"_doc" : {
"order" : "asc"
}
}
]
}

上述是查询一个简单的数据

  1. format:返回数据的格式,支持csv、json、tsv、text、yaml、cbor、smile
  2. sql搜索, 不支持 - .等特殊字符,因此需要转移,包裹sql使用""" 会自动转移特殊字符
  3. 在客户端使用SQL CLI执行
$ ./bin/elasticsearch-sql-cli http://192.168.3.53:9200
sql> select id from "mysql-shop_trades-order_statics" order by id asc limit 2;
  1. 使用 elasticsearch-PHP插件执行 (在业务中使用)
// 读取sql语句,不执行
$where = [
'is_deleted' => 0,
'label_type' => $type,
];
$this->dblink_trade_slave->select('bar_code')->where($where);
if ($is_having) {
$this->dblink_trade_slave->having($having);
}
if ($label_ids) {
$this->dblink_trade_slave->where_in('bind_item_label_id', $label_ids);
}
$sql = $this->dblink_trade_slave->limit(1)->get_compiled_select($index);

// 使用es搜索
$index = '"mysql-shop_trades-order_item_label_binds"'; // 索引需要加引号来转义特殊字符
$params = [
'body' => [
'query' => $sql,
'fetch_size' => 20 // 返回数据条数
]
];
$result = EsClient::sql($params);
// todo 处理结果

Elasticsearch6.3+后,开始支持SQL查询语言,但6.7之前SQL都是实验性质的,6.6进入beta特性,6.7后官方正常正式支持,因此elasticsearch-php 7.0+版本才支持查询x-pack sql,低版本不支持sql查询

需服务器手动安装elasticsearch-sql插件

./bin/elasticsearch-plugin install https://github.com/NLPchina/elasticsearch-sql/releases/download/6.7.0.0/elasticsearch-sql-6.7.0.0.zip

[Logstash] Jdbc input plugin


Jdbc input 插件

一 简介

目的:

需要定时将大量数据从mysql采集到ElasticSearch,这里使用Logstash作为数据采集器,使用Jdbc input plugin插件来提取数据到logstash

Jdbc input plugin作用

  • 将具有JDBC接口的任何数据库中的数据提取到Logstash中
  • 可以使用cront语法定期查询或者一次性的将数据加载到Logstash中
  • 结果集中的每一行都成为一个事件,结果集中的列被转换为事件中的字段

 

二 安装

是jdcb集成插件的一个组件,只需安装logstash即可,由于此插件没有和JDBC驱动程序库一起打包,因此需要使用jdbc_driver_library配置选项将所有的jdbc驱动程序传递给插件

环境要求:

  1. elasticsearch-7.13.2
  2. kibana-7.13.2-darwin-x86_64
  3. logstash-7.13.2
  4. logstash-input-jdbc 插件
  5. mysql-connector-java-8.0.25 (驱动)
  6. mysql数据库

 

三 使用

用法

编写logstash-mysql.conf

input{
     jdbc {
        # 驱动类名
        jdbc_driver_library => "/Users/www/elk/7.13.2/mysql-connector-java-8.0.25/mysql-connector-java-8.0.25.jar"
        jdbc_driver_class => "com.mysql.cj.jdbc.Driver" 
        jdbc_default_timezone => "Asia/Shanghai"
         # mysql 数据库链接,shop_trades为数据库名,zeroDateTimeBehaviro防止因时间格式为00-00导致报错
         jdbc_connection_string => "jdbc:mysql://192.168.3.53:3355/shop_trades?zeroDateTimeBehaviro=convertToNull"
         # 连接数据库用户名
         jdbc_user => "cishop"
         # 连接数据库密码
         jdbc_password => "*****"
         # 是否启用分页读取
         jdbc_paging_enabled => "true"
         jdbc_page_size => "1000" 
         # 设置监听间隔  各字段含义(由左至右) 分、时、天、月、年,全部为*默认含义为每分钟都更新
         schedule => "* * * * *"
         # 是否记录上次执行的结果
         record_last_run => "true"
        # 使用其它字段追踪,而不是用时间
         use_column_value => "true"
         tracking_column => "id"
         last_run_metadata_path => "/Users/www/elk/7.13.2/logstash-7.13.2/log-record/order_statics.txt"
         # 是否清除 last_run_metadata_path 的记录,如果为真那么每次都相当于从头开始查询所有的数据库记录
         clean_run => false
         # 直接写sql语句用这个
         statement => "SELECT * FROM `leiyuan` WHERE id > :sql_last_value"
         type => "order_statics" # 如果数据库字段含有type,此数据会被替换掉,不建议这么使用
         add_field => {table_name => "order_statics"}
       }
}
filter {
  json {
    source => "message"
    remove_field => ["message"]
  }
}

output {
  # stdout {codec => rubydebug }
  stdout {codec => json_lines }
  elasticsearch {
    hosts => ["http://192.168.3.132:9200"]
    index => "mysql-shop_trades-order_statics"
    document_id => "%{id}"
  }
}

执行单个配置文件

# 校验是否有语法错误
bin/logstash -f config/logstash-mysql.conf --config.test_and_exit // 第一次校验配置是否正确

# 执行
bin/logstash -f config/logstash-mysql.conf

# 启动多个logstash文件:需要配置pipelines.yml

 

对多配置文件的引用


[root@VM235 config]# less pipelines.yml |grep -v "#"

 - pipeline.id: mysql
   pipeline.workers: 1
   pipeline.batch.size: 125
   path.config: "/opt/ci123/elk/logstash-6.7.0/config/config.d/mysql.d/*.conf"

 - pipeline.id: application
   pipeline.workers: 1
   pipeline.batch.size: 125
   path.config: "/opt/ci123/elk/logstash-6.7.0/config/config.d/application.conf"
   

 

# 校验
1. 开启config/logstash.yml中的 config.test_and_exit: true
2. bin/logstash
# (画外音:pipelines.yml启动不成功,或找不到pipelines.yml时,很有可能是语法错误,yml对语法邀请非常严格,需仔细检查)

# 启动
bin/logstash  --config.reload.automatic

 

显示以下结果说明,数据正在通过定时脚本导入

[2021-07-05T16:43:00,041][INFO ][logstash.inputs.jdbc     ][main][leiyuan] (0.001561s) SELECT * FROM `leiyuan` WHERE id > 0
{"@timestamp":"2021-07-05T08:43:00.213Z","dated":"2021-07-05T01:28:30.000Z","@version":"1","type":"jdbc","name":"第一名","id":1}
[2021-07-05T16:44:00,063][INFO ][logstash.inputs.jdbc     ][main][leiyuan] (0.002067s) SELECT * FROM `leiyuan` WHERE id > 1
[2021-07-05T16:45:00,066][INFO ][logstash.inputs.jdbc     ][main][leiyuan] (0.001203s) 
{"@timestamp":"2021-07-05T08:52:00.286Z","dated":"2021-07-03T23:19:18.000Z","@version":"1","type":"jdbc","name":"第二名","id":2}
{"@timestamp":"2021-07-05T08:52:00.299Z","dated":"2021-06-30T23:15:00.000Z","@version":"1","type":"jdbc","name":"第三名","id":3}
[2021-07-05T16:53:00,312][INFO ][logstash.inputs.jdbc     ][main][leiyuan] (0.002697s) SELECT * FROM `leiyuan` WHERE id > 3
[2021-07-05T16:53:00,312][INFO ][logstash.inputs.jdbc     ][main][leiyuan] (0.002697s) SELECT * FROM `leiyuan` WHERE id > 3

 

 

 


其他文件:

ELK安装使用手册


elk安装

一、为什么使用elk

一般大型系统是一个分布式部署的架构,不同的服务模块在不同的服务器上,出问题时,需要根据问题暴露的关键信息定位到具体的服务器和模块,构建一套集中式的日志系统,可以提高定位问题的效率
很多时候对于业务关键逻辑,通过file_put_content存储请求数据或者debug,数据量大的时候,对服务器和访问性能都具有不小的影响
一个完整的集中式日志系统包含的主要特点:

  • 收集 - 能够采集多种来源的日志数据
  • 传输 - 能够稳定的吧日志数据传输到中央系统
  • 存储 - 如何存储日志数据
  • 分析 - 可以支持UI分析
  • 警告 - 能够提供错误报告、监控机制

二、elk介绍

elk是三个开源软件的缩写:Elasticsearch , Logstash, Kibana

  • elasticsearch: 开源的日志搜索引擎,可搜集、分析、存储数据
  • kibana:web面板,可以为logstash和els提供的日志分析展示在web界面,
  • logstash:日志的搜索、分析、过滤日志的工具,支持大量的数据获取方式,工作方式是c/s架构,client端安装在需要收集日志的主机上,service端负责收集各个节点日志,并对日志进行过滤和修改等操作,并将其发往elasticsearch上
  • FileBeat:轻量级的日志收集处理工具,使用具在各个服务器上搜集日志后传输给logstash
  • filebeat数据beat,目前beat包含四种工具:
    • Packetbeat(搜集网络流量数据)
    • Topbeat (搜集系统、进程和文件系统级别低的CPU和内存使用情况等数据)
    • filebeat (搜集文件数据)
    • Winlogbeat (搜集windows事件日志数据)

一、安装elasticsearch

# 安装:
$   wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.13.3-linux-x86_64.tar.gz
$   wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.13.3-linux-x86_64.tar.gz.sha512
$   shasum -a 512 -c elasticsearch-7.13.3-linux-x86_64.tar.gz.sha512 
$   tar -xzf elasticsearch-7.13.3-linux-x86_64.tar.gz 
$   cd elasticsearch-7.13.3/ 
 

# 创建es用户 (不能使用root权限执行)
# 1、创建用户:elasticsearch
$ adduser elasticsearch
# 2、创建用户密码,需要输入两次
$ passwd elasticsearch
#3、将对应的文件夹权限赋给该用户
$ chown -R elasticsearch elasticsearch-7.17.3
#4、切换至elasticsearch用户
$ su elasticsearch

 
# config配置
$ less elasticsearch.yml  |grep '#' -v
network.host: 192.168.3.14
http.port: 9200
discovery.seed_hosts: ["192.168.3.14"]
cluster.initial_master_nodes: ["node-1"]
bootstrap.memory_lock: false  # 因运行时报错bootstrap checks failed,此处开启修复这个报错
bootstrap.system_call_filter: false # 因运行时报错bootstrap checks failed,此处开启修复这个报错
# xpack.security.transport.ssl.enabled: true # 开启安全验证,需要设置账号密码时可以开启
# xpack.security.enabled: true  # 开启安全验证,需要设置账号密码时可以开启

# 配置内存大小 (根据服务器内存大小设置适当的值)
$ less ./elasticsearch-7.13.3/config/jvm.options |grep '#' -v
-Xms4g
-Xmx4g
...


# 运行
$   su elasticsearch
$   sh bin/elasticsearch

# 后台运行
$ su elasticsearch
$ nohup bin/elasticsearch &

# 访问请求是否正常启动 (出现下列信息,则正常启动)
$ curl http://192.168.3.14:9200/ 
{
  "name" : "87DNZWU",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "e3A3l85MSZuZlRhxj6IB2w",
  "version" : {
    "number" : "6.7.0",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "8453f77",
    "build_date" : "2019-03-21T15:32:29.844721Z",
    "build_snapshot" : false,
    "lucene_version" : "7.7.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

二、安装kibana

# 安装
$   curl -O https://artifacts.elastic.co/downloads/kibana/kibana-7.13.3-linux-x86_64.tar.gz
$   curl https://artifacts.elastic.co/downloads/kibana/kibana-7.13.3-linux-x86_64.tar.gz.sha512 | shasum -a 512 -c - 
$   tar -xzf kibana-7.13.3-linux-x86_64.tar.gz
$   mv  kibana-7.13.3-linux-x86_64/  kibana-7.13.3/ 


# config配置 其中xpack 需要执行 (bin/kibana-encryption-keys generate)
$ less kibana.yml |grep '#' -v
server.port: 5602
server.host: "192.168.3.14"
elasticsearch.hosts: ["http://192.168.3.14:9200"]
i18n.locale: "zh-CN"

xpack.encryptedSavedObjects.encryptionKey: 58d5e678bf21278edeed84433f905663
xpack.reporting.encryptionKey: d0b608215432fc28ab1b17ed3906c95a
xpack.security.encryptionKey: 59819c05503d1364e3ec17c34839e6a1

monitoring.cluster_alerts.email_notifications.email_address: leiyuan@corp-ci.com

xpack.reporting.capture.browser.chromium.disableSandbox: true


# 运行
$   sh bin/kibana

# 后台运行
$   nohup bin/kibana &

# 查看是否正常启动
# 网页访问 http://192.168.3.53:5601/, 如果正常访问,则启动成功 

kibana 启动报错ersion GLIBC_2.14 not found 
https://blog.csdn.net/xinjing2015/article/details/93746179

三、安装JAVA

# 官方包内有自带的java环境,可以不用安装,如果想要自己配置的java环境,可以按照下放操作 (根据官方文档按照相应版本的java)
$ yum install java-1.8.0-openjdk.x86_64
$ java -version
openjdk version "1.8.0_275"
OpenJDK Runtime Environment (build 1.8.0_275-b01)


四、安装logstash

# 下载 mysql-connector-java (用于连接数据库)
$   wget  http://search.maven.org/remotecontent?filepath=mysql/mysql-\
connector-java/5.1.32/mysql-connector-java-5.1.32.jar


# 官网下载安装包
$   wget https://artifacts.elastic.co/downloads/logstash/logstash-7.13.3-linux-x86_64.tar.gz
$ tar -xzf logstash-7.13.3-linux-x86_64.tar.gz  logstash-7.13.3



# 查询是否可以正常使用  (方式一)
$ bin/logstash -e 'input { stdin {} } output { stdout {} }'
#(画外音:选项 -e 的意思是允许你从命令行指定配置)
# 启动后 输入hello world,可返回json数据,即启动成功



# 接受redis数据   (方法二)
$ less application.conf  |grep -v '#'
input {
    redis {
        data_type => "list"
        key => "logstash-list"
        host => "192.168.3.53"
        port => 8003
        threads => 5
    }
}
output {
  elasticsearch {
    hosts => ["http://192.168.3.53:9200"]
    index => "application_log_%{+YYYY.MM.dd}"
  }
}

# 接受filebeat数据 (暂时不写,自行查询)   (方式三)
$   less  logstash-sample.conf | grep  -v '#'
input {
  beats {
    port => 5044
  }
}

output {
    stdout {codec => rubydebug } # 输出到页面
    elasticsearch {
        hosts => ["http://192.168.3.53:9200"] # 存储的elasticsearch
        index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}"
  }
}

# 接受mysq 数据库数据 (具体写在Mysql>ElasticSearch.md文档中) (方式四)



# 启动单个配置
$ bin/logstash -f config/logstash-sample.conf --config.test_and_exit // 第一次校验配置是否正确
$ bin/logstash -e 'input { stdin { } } output { stdout {} }' // 普通输出
$ bin/logstash -f config/logstash-sample.conf --config.reload.automatic # 执行某个配置文件

# 同时启动多个配置文件 (需配置管道pipelines.yml)
1. 需配置管道pipelines.yml
$ less pipelines.yml |grep -v "#"

 - pipeline.id: mysql
   pipeline.workers: 1
   pipeline.batch.size: 125
   path.config: "/opt/ci123/elk/logstash-6.7.0/config/config.d/mysql.d/*.conf"

 - pipeline.id: application
   pipeline.workers: 1
   pipeline.batch.size: 125
   path.config: "/opt/ci123/elk/logstash-6.7.0/config/config.d/application.conf"

2. 校验
    开启config/logstash.yml中的 config.test_and_exit: true
3. 启动
    bin/logstash # (画外音:pipelines.yml启动不成功,或找不到pipelines.yml时,很有可能是语法错误,yml对语法邀请非常严格,需仔细检查)
    bin/logstash  --config.reload.automatic # 启动并自动加载修改的配置文件

 

五、安全设置

1. 为elk设置用户名和密码

注意:elastic 相当于超级管理员的账号,任何连接都可以使用此账号,但风险较高,建议为各自的模块设置自己的账号和权限

# step1 停止运行kibana和elasticsearch
# step2 在elasticsearch下增加配置 config/elasticsearch.yml
xpack.security.transport.ssl.enabled: true
xpack.security.enabled: true

# step3 启动elasticsearch
./bin/elasticsearch
# step4 设置密码 (可选择 自动设置,也可以手动设置)
    # (画外音,设置的密码比较多,如果想设置不一样,需提前记录下)
./bin/elasticsearch-setup-passwords auto  #
./bin/elasticsearch-setup-passwords interactive # 手动设置 (注意,此命令有且只能操作一次)


# 修改某个账号密码
$ curl -H "Content-Type:application/json" -XPOST -u {user} 'http://192.168.1.123:9227/_xpack/security/user/{user}/_password' -d '{ "password" : "new_password" }'
Enter host password for user 'elastic':
{}

tip:
    elastic: 需要修改的账号名称
    new_password:新密码


elastic一个内置的超级用户,可用于连接elasticsearch、kibana

kibana_systemKibana 用于连接 Elasticsearch 并与之通信的用户。

logstash_systemLogstash 在 Elasticsearch 中存储监控信息时使用的用户。

beats_systemBeats 在 Elasticsearch 中存储监控信息时使用的用户。

apm_systemAPM 服务器在 Elasticsearch 中存储监控信息时使用的用户。

remote_monitoring_user在 Elasticsearch 中收集和存储监控信息时使用的用户 Metricbeat。它具有remote_monitoring_agentremote_monitoring_collector内置角色。

 

2. 访问elasticsearch

# 测试访问
es@ts_web_123 elasticsearch-7.13.3]$ curl http://192.168.1.123:9227 -u elastic 
Enter host password for user 'elastic': xxx
{
  "name" : "node-1",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "faDVR0zoS5CGGhDcm6TkIg",
  "version" : {
    "number" : "7.13.3",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "5d21bea28db1e89ecc1f66311ebdec9dc3aa7d64",
    "build_date" : "2021-07-02T12:06:10.804015202Z",
    "build_snapshot" : false,
    "lucene_version" : "8.8.2",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}


3. kibana项目

#kibana: config/kibana
elasticsearch.username: "kibana_system"
elasticsearch.password: "你的密码"
(画外音:kibana密码需要与elastic密码一致,否则启动异常 待解决)

4. logstash 管道连接

为logstash配置的账号

  1. 使用Kibana 中的Management > Roles UI 或roleAPI 创建 logstash_writer角色。对于集群权限,添加manage_index_templates和monitor。对于指数的权限,添加write,create和create_index。
  2. 创建logstash_internal用户并为其分配logstash_writer角色。可以从Kibana 中的Management > Users UI中创建用户

 

output {
  elasticsearch {
    hosts => ["http://192.168.1.14:9200"]
    index => "application_log_%{+YYYY.MM.dd}"
    user => "logstash_internal"
    password => "xxx"
  }
}

 

5. kibana 后台 可设置各类用户角色

可通过内置角色,设置不同的账户

 

六、遇到的常见报错

1.【elasticsearch启动】sh bin/elasticsearch报错:can not run elasticsearch as root
# 创建es用户 (不能使用root权限执行)
# 1、创建用户:elasticsearch
$ adduser elasticsearch
# 2、创建用户密码,需要输入两次
$ passwd elasticsearch
#3、将对应的文件夹权限赋给该用户
$ chown -R elasticsearch elasticsearch-7.17.3
#4、切换至elasticsearch用户
$ su elasticsearch

 

2.【elasticsearch启动】bootstrap checks failed :

问题原因:因为Centos6不支持SecComp,而ES5.2.1默认bootstrap.system_call_filter为true进行检测,所以导致检测失败,失败后直接导致ES不能启动。详见 :https://github.com/elastic/elasticsearch/issues/22899

解决方法:

在elasticsearch.yml中配置bootstrap.system_call_filter为false,注意要在Memory下面:
bootstrap.memory_lock: false
bootstrap.system_call_filter: false

 

3.【elasticsearch启动】 max number of threads [1024] for user [elasticsearch] is too low, increase to at least [4096]

修改max user processes

错误说明: Linux系统为每个用户都设置了一个最大进程数, 这个特性可以让我们控制服务器上现有用户可以创建的进程数量.

(2) 查看max user processes:

# 与查看max open files类似, 可使用 ulimit -u查看max user processes:
ulimit -u

(3) 修改max user processes:

① 方案一: 修改/etc/security/limits.conf文件, 在文件最后添加下述内容:

*  soft      nproc      131072
*  hard      nproc      131072

② 方案二: 修改/etc/security/limits.d/90-nproc.conf文件, 在文件最后添加下述内容:

# 用户进程数的默认限制, 下面这个是对root外的其他用户限制max user processes, 要注释掉: 
# *          soft    nproc     1024
root       soft    nproc     131072

 

4.【elasticsearch启动】max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]**

修改虚拟内存大小

[root@localhost ~]# sysctl -w vm.max_map_count=262144

查看修改结果

[root@localhost ~]# sysctl -a|grep vm.max_map_countvm.max_map_count = 262144

 

5.【kibana启动】Index .kibana_7.13.2_001 belongs to a version of Kibana that cannot be automatically migrated. Reset it or use the X-Pack upgrade assistant.

原因:
遗留了旧版的es后,kibana还存放着原es数据索引。
解决方法:
修改kibana.yml里的,index.kibana 为index.kibana6.7
重启kibana

6. logstash报错:

本地出现报错,无法连接elasticsearch:9200时,关闭本地翻墙软件代理,再尝试。