折腾 Quickwit,Rust 编写的分布式搜索引擎-官方教程

image

快速上手

在本快速入门指南中,我们将安装 Quickwit,创建一个索引,添加文档,最后执行搜索查询。本指南中使用的所有 Quickwit 命令都在 CLI 参考文档 中进行了记录。

使用 Quickwit 安装程序安装 Quickwit

Quickwit 安装程序会自动为您的环境选择正确的二进制归档文件,然后在您的工作目录中下载并解压它。
此方法仅适用于 某些操作系统/架构,并且您还需要安装一些 外部依赖项

curl -L https://install.quickwit.io | sh
cd ./quickwit-v*/
./quickwit --version

现在您可以根据您的环境将这个可执行文件目录移动到合适的位置,并可能将其添加到您的 PATH 环境变量中。

使用 Quickwit 的 Docker 镜像

您还可以在隔离的 Docker 容器中拉取和运行 Quickwit 二进制文件。

# Create first the data directory.
mkdir qwdata
docker run --rm quickwit/quickwit --version

如果您使用的是基于 Apple Silicon 的 macOS 系统,您可能需要指定平台。您也可以安全地忽略 jemalloc 的警告。

docker run --rm --platform linux/amd64 quickwit/quickwit --version

Start Quickwit server

CLI

./quickwit run

Docker

docker run --rm -v $(pwd)/qwdata:/quickwit/qwdata -p 127.0.0.1:7280:7280 quickwit/quickwit run

提示:您可以使用环境变量 RUST_LOG 来控制 Quickwit 的详细程度。

通过访问 UI 地址 http://localhost:7280 或使用 cURL 发送简单的 GET 请求来检查其是否正常工作:

curl http://localhost:7280/api/v1/version

创建您的第一个索引

在向 Quickwit 添加文档之前,您需要使用一个 YAML 配置文件创建一个索引。此配置文件特别允许您定义如何将输入文档映射到索引字段以及这些字段是否应该被存储和索引。请参阅 索引配置文档

让我们创建一个配置为接收 Stackoverflow 帖子(问题和答案)的索引。

# First, download the stackoverflow dataset config from Quickwit repository.
curl -o stackoverflow-index-config.yaml https://raw.githubusercontent.com/quickwit-oss/quickwit/main/config/tutorials/stackoverflow/index-config.yaml

索引配置定义了三个字段:titlebodycreationDatetitlebody索引化和分词 的,并且它们也被用作默认搜索字段,这意味着如果您的查询不针对特定字段,它们将用于搜索。creationDate 作为每条记录的时间戳。没有更多的显式字段定义,因为我们使用默认的动态 模式:未声明的字段仍然会被索引,默认情况下启用了快速字段以支持聚合查询,并且使用 raw 分词器处理文本。

以下是完整的配置:

#
# Index config file for stackoverflow dataset.
#
version: 0.7

index_id: stackoverflow

doc_mapping:
  field_mappings:
    - name: title
      type: text
      tokenizer: default
      record: position
      stored: true
    - name: body
      type: text
      tokenizer: default
      record: position
      stored: true
    - name: creationDate
      type: datetime
      fast: true
      input_formats:
        - rfc3339
      fast_precision: seconds
  timestamp_field: creationDate

search_settings:
  default_search_fields: [title, body]

indexing_settings:
  commit_timeout_secs: 30

现在我们可以使用以下命令创建索引:

CLI

./quickwit index create --index-config ./stackoverflow-index-config.yaml

CURL

curl -XPOST http://127.0.0.1:7280/api/v1/indexes --header "content-type: application/yaml" --data-binary @./stackoverflow-index-config.yaml

检查是否已创建目录 ./qwdata/indexes/stackoverflow,Quickwit 将在此处写入索引文件和包含 索引元数据metastore.json 文件。
现在您已经准备好填充索引了。

让我们添加一些文档

Quickwit 可以从许多 来源 索引数据。我们将使用新行分隔的 JSON NDJSON 数据集作为我们的数据源。
让我们下载 一批 Stackoverflow 帖子(10,000条)NDJSON 格式并对其进行索引。

# Download the first 10_000 Stackoverflow posts articles.
curl -O https://quickwit-datasets-public.s3.amazonaws.com/stackoverflow.posts.transformed-10000.json

CLI

# Index our 10k documents.
./quickwit index ingest --index stackoverflow --input-path stackoverflow.posts.transformed-10000.json --force

CURL

# Index our 10k documents.
curl -XPOST "http://127.0.0.1:7280/api/v1/stackoverflow/ingest?commit=force" --data-binary @stackoverflow.posts.transformed-10000.json

一旦 ingest 命令完成,您就可以开始使用以下 search 命令查询数据:

CLI

./quickwit index search --index stackoverflow --query "search AND engine"

CURL

curl "http://127.0.0.1:7280/api/v1/stackoverflow/search?query=search+AND+engine"

它应该返回 10 条结果。现在您已经准备好使用搜索 API 进行操作了。

执行搜索查询

让我们从对字段 title 的查询开始:title:search AND engine

curl "http://127.0.0.1:7280/api/v1/stackoverflow/search?query=title:search+AND+engine"

相同的请求可以用 JSON 查询表达:

curl -XPOST "http://localhost:7280/api/v1/stackoverflow/search" -H 'Content-Type: application/json' -d '{
    "query": "title:search AND engine"
}'

这种格式更冗长,但它允许您使用更多高级功能,例如聚合。以下查询查找此数据集中问题中最常用的标签:

curl -XPOST "http://localhost:7280/api/v1/stackoverflow/search" -H 'Content-Type: application/json' -d '{
    "query": "type:question",
    "max_hits": 0,
    "aggs": {
        "foo": {
            "terms":{
                "field":"tags",
                "size": 10
            }
        }
    }
}'

在尝试不同的查询时,请查看服务器日志以了解发生了什么。

不要忘记正确编码查询参数以避免出现错误请求(状态码 400)。

清理

让我们通过删除索引来做一些清理工作:

CLI

./quickwit index delete --index stackoverflow

REST

curl -XDELETE http://127.0.0.1:7280/api/v1/indexes/stackoverflow

恭喜!您可以继续以下教程来探索 Quickwit 的所有特性。

TLDR

在 Quickwit 的安装目录中运行以下命令。

curl -o stackoverflow-index-config.yaml https://raw.githubusercontent.com/quickwit-oss/quickwit/main/config/tutorials/stackoverflow/index-config.yaml
./quickwit index create --index-config ./stackoverflow-index-config.yaml
curl -O https://quickwit-datasets-public.s3.amazonaws.com/stackoverflow.posts.transformed-10000.json
./quickwit index ingest --index stackoverflow --input-path ./stackoverflow.posts.transformed-10000.json --force
./quickwit index search --index stackoverflow --query "search AND engine"
./quickwit index delete --index stackoverflow

下一步教程

安装

Quickwit 编译为一个单一的二进制文件,我们提供了多种安装方法:

先决条件

Quickwit 官方仅支持 Linux。FreeBSD 和 MacOS 虽然不是官方支持的,但应该也能正常工作。

Quickwit 提供了 x86-64 和 aarch64 的二进制文件。不需要特殊指令集,但在 x86-64 上推荐使用 SSE3。
对于 aarch64 的支持目前还是实验性的。

下载

version: 0.8.1 - Release notes - Changelog
License: AGPL V3
Downloads .tar.gz:

GitHub 上详细了解可用的构建版本。

注意外部依赖

Quickwit 正常工作依赖于以下外部库:

  • libssl:行业标准加密库。
    这些库可以通过本机包管理器安装在您的系统上。
    您可以使用以下命令安装这些依赖项:

Ubuntu

apt-get -y update && apt-get -y install libssl

AWS Linux

yum -y update && yum -y install openssl

Arch Linux

pacman -S openssl

另外,编译它还需要一些额外的依赖项。这些依赖项在生产系统上不是必需的:

  • clang:用于编译某些依赖项。
  • protobuf-compiler:用于编译 protobuf 定义。
  • libssl-dev:libssl 的头文件。
  • pkg-config:用于定位 libssl。
  • cmake:用于构建 librdkafka,以支持 kafka。
    这些依赖项也可以通过本机包管理器安装在您的系统上。
    您可以使用以下命令安装这些依赖项:

Ubuntu

apt install -y clang protobuf-compiler libssl-dev pkg-config cmake

AWS Linux

yum -y update && yum -y install clang openssl-devel pkgconfig cmake3
# amazonlinux only has protobuf-compiler 2.5, we need something much more up to date.
wget https://github.com/protocolbuffers/protobuf/releases/download/v21.9/protoc-21.9-linux-x86_64.zip
sudo unzip protoc-21.9-linux-x86_64.zip -d /usr/local
# amazonlinux use cmake2 as cmake, we need cmake3
ln -s /usr/bin/cmake3 /usr/bin/cmake

Arch Linux

pacman -S clang protobuf openssl pkg-config cmake make

安装脚本

要在您的机器上轻松安装 Quickwit,只需从您首选的 shell 运行以下命令。
该脚本会检测架构,然后为机器下载正确的二进制存档。

curl -L https://install.quickwit.io | sh

此脚本所做的只是下载适用于您机器的正确二进制存档,并将其提取到当前工作目录中。这意味着您可以从 GitHub 下载与您的操作系统架构匹配的任何所需的存档,并手动将其提取到任何位置。

安装或解压后,所有 Quickwit 的安装文件都可以在一个名为 quickwit-{version} 的目录中找到,其中 version 是对应的 Quickwit 版本。此目录具有以下布局:

quickwit-{version}
    ├── config
    │   └── quickwit.yaml
    ├── LICENSE_AGPLv3.0.txt
    ├── quickwit
    └── qwdata
  • config/quickwit.yaml: 默认配置文件。
  • LICENSE_AGPLv3.0.txt: 许可证文件。
  • quickwit: Quickwit 可执行二进制文件。
  • qwdata/: 默认的数据目录。

使用 Docker 镜像

如果您使用 Docker,这可能是最快捷的启动方式之一。
以下命令将从 Docker Hub 拉取镜像并启动一个容器,准备执行 Quickwit 命令。

docker run --rm quickwit/quickwit --version

# If you are using Apple silicon based macOS system you might need to specify the platform.
# You can also safely ignore jemalloc warnings.
docker run --rm --platform linux/amd64 quickwit/quickwit --version

要全面了解这一点,请参阅 快速入门指南

使用 Grafana 查看 Logs 和 Traces

在本教程中,我们将使用 Docker Compose 设置一个展示 Quickwit 追踪信息的 Grafana 仪表板。

只需几分钟时间即可让 Grafana 与 Quickwit 配合工作并构建有意义的仪表板。

创建 Docker Compose 配方

让我们添加一个启用了 OTLP 服务的 Quickwit 实例

version: '3.0'
services:
  quickwit:
    image: quickwit/quickwit
    environment:
      QW_ENABLE_OPENTELEMETRY_OTLP_EXPORTER: "true"
      OTEL_EXPORTER_OTLP_ENDPOINT: "http://localhost:7281"
    ports:
      - 7280:7280
    command: ["run"]

然后我们创建一个带有 Quickwit 数据源插件的 Grafana 服务。

  grafana:
    image: grafana/grafana-oss
    container_name: grafana
    ports:
      - "${MAP_HOST_GRAFANA:-127.0.0.1}:3000:3000"
    environment:
      GF_INSTALL_PLUGINS: https://github.com/quickwit-oss/quickwit-datasource/releases/download/v0.3.1/quickwit-quickwit-datasource-0.3.1.zip;quickwit-quickwit-datasource
      GF_AUTH_DISABLE_LOGIN_FORM: "true"
      GF_AUTH_ANONYMOUS_ENABLED: "true"
      GF_AUTH_ANONYMOUS_ORG_ROLE: Admin

保存并运行配方:

$ docker compose up

您应该能够通过 http://localhost:7280/ 访问 Quickwit 的用户界面,以及通过 http://localhost:3000/ 访问 Grafana 的用户界面。

配置数据源

在 Grafana 中,前往 数据源。如果插件安装正确,您应该能够在列表中找到 Quickwit。

我们将设置一个新的 Quickwit 数据源,用于查看 Quickwit 自身的 OpenTelemetry 追踪信息,让我们使用以下参数配置数据源:

  • URL: http://quickwit:7280/api/v1 这使用了 Docker 服务名称作为主机
  • 索引 ID: otel-traces-v0_7

保存并测试,您应该会收到确认消息,表明数据源已正确设置。

image

您还可以设置一个新的 Quickwit 数据源,用于查看 Quickwit 自身的 OpenTelemetry 日志(或您自己的日志索引),让我们使用以下参数配置数据源:

  • URL: http://quickwit:7280/api/v1 这使用了 Docker 服务名称作为主机
  • 索引 ID: otel-logs-v0_7

创建仪表板

然后您可以 创建一个新的仪表板 并添加可视化组件:在这里您应该可以选择追踪信息的 Quickwit 数据源。

Quickwit 会发送自身的追踪信息,因此您应该已经有数据可供显示。让我们配置一些面板!

  • 一个表格,统计 span_name 的数量
    • Panel type:Table
    • Query
    • Metric:Count
    • Group by:Terms : span_name : 按 Count 排序
  • 一个柱状图,展示每小时 tantivy 搜索的数量:
    • Panel type:Time Series
    • Queryspan_name:tantivy_search
    • Metric:Count
    • Group by:Date Histogram : span_start_timestamp_nanos : 间隔 1 小时
  • 一个柱状图,展示过去 6 小时内每小时 ERROR 日志的数量:
    • Panel type:Bar Chart
    • Queryservice_name:quickwit AND events.event_attributes.level:ERROR
    • Metric:Count
    • Group by:Terms : span_start_timestamp_nanos : 间隔 1 小时
  • 在同一个柱状图上再添加一个查询,展示 WARN 日志的数量

结果

这是您的第一个仪表板可能的样子:

image

使用 Jaeger 查看 Traces

在这个快速入门指南中,我们将使用 Docker Compose 设置一个 Quickwit 实例,并使用 Jaeger 分析其自身的跟踪记录。

您只需要一分钟就能让 Jaeger 与 Quickwit 存储后端一起工作。

启动 Quickwit 和 Jaeger

让我们使用 docker compose 并采用以下配置:

version: "3"

services:
  quickwit:
    image: quickwit/quickwit:${QW_VERSION:-0.8.1}
    volumes:
      - ./qwdata:/quickwit/qwdata
    ports:
      - 7280:7280
    environment:
      - QW_ENABLE_OPENTELEMETRY_OTLP_EXPORTER=true
      - OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:7281
    command: ["run"]

  jaeger-query:
    image: jaegertracing/jaeger-query:1.52
    ports:
      - 16686:16686
    environment:
      - SPAN_STORAGE_TYPE=grpc-plugin
      - GRPC_STORAGE_SERVER=quickwit:7281
      - GRPC_STORAGE_TLS=false

如您在 docker compose 文件中所见,Quickwit 被配置为将其自身的跟踪记录 OTEL_EXPORTER_OTLP_ENDPOINT 发送到自身 http://localhost:7281
另一方面,Jaeger 被配置为使用 gRPC 存储服务器 quickwit:7281

保存并运行配置:

$ docker compose up

您应该能够在 http://localhost:7280/ 访问 Quickwit 的 UI,并在 http://localhost:16686/ 访问 Jaeger 的 UI。

在 Jaeger 中搜索和查看跟踪记录

Quickwit 生成了许多跟踪记录,让我们来看看其中的一些:

  • find_traces:由 Jaeger “查找跟踪记录” 按钮生成。
  • get_operations:由 Jaeger 在获取操作列表时生成。
  • get_services:由 Jaeger 在获取服务列表时生成。
  • ingest-spans:当 Quickwit 通过 gRPC OTLP API 接收 span 时生成。
  • ...

以下是搜索和跟踪视图的截图:

image

image

使用 Quickwit UI 搜索跟踪记录

您还可以使用位于 http://localhost:7280 的 Quickwit UI 来搜索跟踪记录。

这里有一些查询示例:

  • service_name:quickwit AND events.event_attributes.level:INFO
  • span_duration_millis:>100
  • resource_attributes.service.version:v0.8.1
  • service_name:quickwit

就这样!您可以通过以下教程深入了解所有 Quickwit 功能。

下一步教程

本地索引日志数据集

在本指南中,我们将在本地机器上对大约 2000 万条日志条目(解压缩后 7 GB)进行索引。如果您想在 AWS S3 上启动带有多个搜索节点的服务器,请参阅 分布式搜索教程

这里是一个日志条目的示例:

{
  "timestamp": 1460530013,
  "severity_text": "INFO",
  "body": "PacketResponder: BP-108841162-10.10.34.11-1440074360971:blk_1074072698_331874, type=HAS_DOWNSTREAM_IN_PIPELINE terminating",
  "resource": {
    "service": "datanode/01"
  },
  "attributes": {
    "class": "org.apache.hadoop.hdfs.server.datanode.DataNode"
  },
  "tenant_id": 58
}

安装

让我们下载并安装 Quickwit。

curl -L https://install.quickwit.io | sh
cd quickwit-v*/

或者在隔离的 Docker 容器中拉取并运行 Quickwit 二进制文件。

docker run quickwit/quickwit --version

启动 Quickwit 服务器

CLI

./quickwit run

Docker

docker run --rm -v $(pwd)/qwdata:/quickwit/qwdata -p 127.0.0.1:7280:7280 quickwit/quickwit run

如果您使用的是基于 Apple silicon 的 macOS 系统,可能需要指定平台,使用 --platform linux/amd64 标志。您也可以安全地忽略 jemalloc 的警告。

创建索引

让我们创建一个配置好的索引来接收这些日志。

# First, download the hdfs logs config from Quickwit repository.
curl -o hdfs_logs_index_config.yaml https://raw.githubusercontent.com/quickwit-oss/quickwit/main/config/tutorials/hdfs-logs/index-config.yaml

索引配置定义了五个字段:timestamptenant_idseverity_textbody,以及一个 JSON 字段用于嵌套值 resource.service。我们本可以在这里使用对象字段并维护一个固定的模式,但为了方便起见,我们将使用 JSON 字段。
它还设置了 default_search_fieldstag_fieldstimestamp_field
timestamp_fieldtag_fields 由 Quickwit 用于查询时的 分片剪枝,以提高搜索速度。
有关更多详细信息,请参阅 索引配置文档

version: 0.7

index_id: hdfs-logs

doc_mapping:
  field_mappings:
    - name: timestamp
      type: datetime
      input_formats:
        - unix_timestamp
      output_format: unix_timestamp_secs
      fast_precision: seconds
      fast: true
    - name: tenant_id
      type: u64
    - name: severity_text
      type: text
      tokenizer: raw
    - name: body
      type: text
      tokenizer: default
      record: position
    - name: resource
      type: json
      tokenizer: raw
  tag_fields: [tenant_id]
  timestamp_field: timestamp

search_settings:
  default_search_fields: [severity_text, body]

现在让我们使用 create 子命令创建索引(假设您位于 Quickwit 安装目录内):

CLI

./quickwit index create --index-config hdfs_logs_index_config.yaml

cURL

curl -XPOST http://localhost:7280/api/v1/indexes -H "content-type: application/yaml" --data-binary @hdfs_logs_index_config.yaml

现在您可以填充索引了。

索引日志

数据集是一个压缩的 NDJSON 文件
我们不是先下载再索引数据,而是使用管道直接将解压缩的流发送给 Quickwit。
这可能需要长达 10 分钟的时间,正好适合休息一下喝杯咖啡。

CLI

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants.json.gz | gunzip | ./quickwit index ingest --index hdfs-logs

Docker

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants.json.gz | gunzip | docker run -v $(pwd)/qwdata:/quickwit/qwdata -i quickwit/quickwit index ingest --index hdfs-logs

如果您赶时间,可以使用包含 10,000 条文档的样本数据集,我们将使用这个数据集进行示例查询:

CLI

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants-10000.json | ./quickwit index ingest --index hdfs-logs

Docker

在 macOS 或 Windows 上:

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants-10000.json | docker run -v $(pwd)/qwdata:/quickwit/qwdata -i quickwit/quickwit index ingest --index hdfs-logs --endpoint http://host.docker.internal:7280

在 Linux 上:

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants-10000.json | docker run --network=host -v $(pwd)/qwdata:/quickwit/qwdata -i quickwit/quickwit index ingest --index hdfs-logs --endpoint http://127.0.0.1:7280

cURL

wget https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants-10000.json
curl -XPOST http://localhost:7280/api/v1/hdfs-logs/ingest -H "content-type: application/json" --data-binary @hdfs-logs-multitenants-10000.json

您可以检查是否正在工作,方法是在 severity_text 字段中搜索 INFO

CLI

./quickwit index search --index hdfs-logs  --query "severity_text:INFO"

Docker

在 macOS 或 Windows 上:

docker run -v $(pwd)/qwdata:/quickwit/qwdata quickwit/quickwit index search --index hdfs-logs  --query "severity_text:INFO" --endpoint http://host.docker.internal:7280

在 Linux 上:

docker run --network=host -v $(pwd)/qwdata:/quickwit/qwdata quickwit/quickwit index search --index hdfs-logs  --query "severity_text:INFO" --endpoint http://127.0.0.1:7280

ingest 子命令会生成包含 500 万条文档的 分片。每个分片是一个小型索引的表示,其中保存了索引文件和元数据文件。 https://quickwit.io/docs/overview/architecture

查询返回的 JSON 结果:

{
  "num_hits": 10000,
  "hits": [
    {
      "body": "Receiving BP-108841162-10.10.34.11-1440074360971:blk_1073836032_95208 src: /10.10.34.20:60300 dest: /10.10.34.13:50010",
      "resource": {
        "service": "datanode/03"
      },
      "severity_text": "INFO",
      "tenant_id": 58,
      "timestamp": 1440670490
    }
    ...
  ],
  "elapsed_time_micros": 2490
}

索引配置显示我们可以使用时间戳字段参数 start_timestampend_timestamp 并从中受益于时间剪枝。
在幕后,Quickwit 只会查询包含在这个时间范围内的日志的 分片

让我们使用这些参数与以下查询:

curl 'http://127.0.0.1:7280/api/v1/hdfs-logs/search?query=severity_text:INFO&start_timestamp=1440670490&end_timestamp=1450670490'

清理

让我们做一些清理工作,删除索引:

CLI

./quickwit index delete --index hdfs-logs

cURL

curl -XDELETE http://127.0.0.1:7280/api/v1/indexes/hdfs-logs

恭喜!您完成了这个教程!

要继续您的 Quickwit 之旅,请参阅 分布式搜索教程 或深入研究 搜索 REST API查询语言

使用 AWS Lambda 进行搜索

在本教程中,我们将使用 Quickwit Lambda 对位于 AWS S3 上的大约 2000 万条日志条目(解压缩后 7 GB)进行索引和搜索。

具体来说,我们将部署一个包含 Quickwit Lambda 的 AWS CloudFormation 栈,以及两个存储桶:一个暂存存储桶用于存放待索引的 gzip 压缩的新行分隔 JSON 文件,另一个存储桶用于存放索引数据。暂存存储桶是可选的,因为 Quickwit 索引器可以从它有访问权限的任何 S3 文件读取数据。

image

安装

安装 AWS CDK

我们将使用 AWS CDK 来编写基础设施自动化脚本。使用 npm 安装它:

npm install -g aws-cdk

您还需要在 shell 中正确配置 AWS 凭证。一种方法是使用 凭证文件

最后,克隆 Quickwit 仓库:

git clone https://github.com/quickwit-oss/tutorials.git
cd tutorials/simple-lambda-stack

设置 Python 环境

我们使用 Python 3.10 来定义需要部署的 AWS CloudFormation 栈,并使用 Python CLI 调用 Lambda 函数。
让我们安装这些必要的包(boto3, aws-cdk-lib, click, pyyaml)。

# Install pipenv if needed.
pip install --user pipenv
pipenv shell
pipenv install

下载 Quickwit Lambda 函数

mkdir -p cdk.out
wget -P cdk.out https://github.com/quickwit-oss/quickwit/releases/download/aws-lambda-beta-01/quickwit-lambda-indexer-beta-01-x86_64.zip
wget -P cdk.out https://github.com/quickwit-oss/quickwit/releases/download/aws-lambda-beta-01/quickwit-lambda-searcher-beta-01-x86_64.zip

初始化并部署

配置您想要部署栈的 AWS 区域和 账户 ID

export CDK_ACCOUNT=123456789
# us-east-1 is where the Quickwit public dataset bucket is located
export CDK_REGION=us-east-1

如果此区域/账户对尚未通过 CDK 初始化,则运行:

cdk bootstrap aws://$CDK_ACCOUNT/$CDK_REGION

这将初始化一些基本资源以托管 Lambda 包等工件。现在我们可以部署栈:

cdk deploy -a cdk/app.py

索引 HDFS 日志数据集

这里是一个数据集中日志条目的示例:

{
  "timestamp": 1460530013,
  "severity_text": "INFO",
  "body": "PacketResponder: BP-108841162-10.10.34.11-1440074360971:blk_1074072698_331874, type=HAS_DOWNSTREAM_IN_PIPELINE terminating",
  "resource": {
    "service": "datanode/01"
  },
  "attributes": {
    "class": "org.apache.hadoop.hdfs.server.datanode.DataNode"
  },
  "tenant_id": 58
}

如果您有 5 分钟的时间,您可以索引整个数据集,该数据集可在我们的公共 S3 存储桶上获取。

python cli.py index s3://quickwit-datasets-public/hdfs-logs-multitenants.json.gz

一旦启动索引 Lambda 函数,您就不能手动停止它。键盘中断只会停止客户端而不会停止函数。如果您尝试再次运行它,可能会遇到 TooManyRequestsException 错误。这是因为索引器的并发数被设置为 1,以避免在元存储上出现竞态条件。

如果您不想等待,只需索引包含 10,000 个文档的数据集:

python cli.py index s3://quickwit-datasets-public/hdfs-logs-multitenants-10000.json

执行搜索查询

让我们从对字段 severity_text 的查询开始,查找错误:severity_text:ERROR

python cli.py search '{"query":"severity_text:ERROR"}'

如果索引了整个数据集,它应在不到 1 秒内响应并返回 345 条中的 10 条结果。如果您索引了前 10,000 个文档,则不会有结果,尝试查询 INFO 级别的日志。

现在我们执行一个更高级的查询:一个日期直方图,同时对 severity_text 字段进行术语聚合:

python cli.py search '{ "query": "*", "max_hits": 0, "aggs": { "events": { "date_histogram": { "field": "timestamp", "fixed_interval": "30d" }, "aggs": { "log_level": { "terms": { "size": 10, "field": "severity_text", "order": { "_count": "desc" } } } } } } }'

它应在不到 2 秒内响应并返回每 30 天的日志级别排名。

清理

首先,您需要删除在 S3 存储桶上创建的文件。
完成后,您可以删除栈。

cdk destroy -a cdk/app.py
rm -rf cdk.out

恭喜!您完成了这个教程!您可以继续深入学习以下教程,了解 Quickwit 的所有功能。

下一步

基于 AWS S3 的分布式搜索

在本指南中,我们将使用 EC2 实例对位于 AWS S3 上的大约 4000 万条日志条目(解压缩后 13 GB)进行索引,并启动一个三节点分布式搜索集群。

日志条目示例:

{
  "timestamp": 1460530013,
  "severity_text": "INFO",
  "body": "PacketResponder: BP-108841162-10.10.34.11-1440074360971:blk_1074072698_331874, type=HAS_DOWNSTREAM_IN_PIPELINE terminating",
  "resource": {
    "service": "datanode/01"
  },
  "attributes": {
    "class": "org.apache.hadoop.hdfs.server.datanode.DataNode"
  }
}

在使用 Quickwit 和对象存储之前,请查看我们关于在 AWS S3 上部署的 建议,以避免月底出现一些不愉快的意外。

https://quickwit.io/docs/operating/aws-costs

首先,让我们创建一个 EC2 实例,安装 Quickwit 二进制文件,并按照 配置指南 配置它,以便 Quickwit 可以访问您的 S3 存储桶。此实例将用于索引我们的数据集(请注意,如果您的本地机器有权在 AWS S3 上读写,您也可以从本地机器索引数据集)。

安装

curl -L https://install.quickwit.io | sh
cd quickwit-v*/

使用 S3 配置 Quickwit

让我们定义想要存储索引的 S3 路径。

export S3_PATH=s3://{path/to/bucket}/indexes

您需要为给定的存储桶包含必要的授权,这可以通过设置 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 环境变量来完成,或者通过 AWS 凭证文件。通常位于 ~/.aws/credentials

更多信息请参阅 我们的 AWS 配置指南

https://quickwit.io/docs/guides/aws-setup

现在我们可以创建一个 Quickwit 配置文件。

# Create Quickwit config file.
echo "version: 0.7
node_id: searcher-1
listen_address: 0.0.0.0
metastore_uri: ${S3_PATH}
default_index_root_uri: ${S3_PATH}
" > config.yaml

您也可以直接传递环境变量:

# config.yaml
node_id: searcher-1
listen_address: 0.0.0.0
version: 0.7
metastore_uri: ${S3_PATH}
default_index_root_uri: ${S3_PATH}

现在我们准备好启动 Quickwit 了。

./quickwit run --config config.yaml

创建索引

# First, download the hdfs logs config from Quickwit repository.
curl -o hdfs_logs_index_config.yaml https://raw.githubusercontent.com/quickwit-oss/quickwit/main/config/tutorials/hdfs-logs/index-config.yaml

索引配置定义了五个字段:timestamptenant_idseverity_textbody,以及一个 JSON 字段用于嵌套值 resource.service。我们本可以在这里使用对象字段并维护一个固定的模式,但为了方便起见,我们将使用 JSON 字段。
它还设置了 default_search_fieldstag_fieldstimestamp_fieldtimestamp_fieldtag_fields 由 Quickwit 用于查询时的 分片剪枝,以提高搜索速度。
有关更多详细信息,请参阅 索引配置文档

version: 0.7

index_id: hdfs-logs

doc_mapping:
  field_mappings:
    - name: timestamp
      type: datetime
      input_formats:
        - unix_timestamp
      output_format: unix_timestamp_secs
      fast_precision: seconds
      fast: true
    - name: tenant_id
      type: u64
    - name: severity_text
      type: text
      tokenizer: raw
    - name: body
      type: text
      tokenizer: default
      record: position
    - name: resource
      type: json
      tokenizer: raw
  tag_fields: [tenant_id]
  timestamp_field: timestamp

search_settings:
  default_search_fields: [severity_text, body]

我们现在可以使用 create 子命令创建索引。

./quickwit index create --index-config hdfs_logs_index_config.yaml

此步骤也可以在您的本地机器上执行。create 命令会在本地创建索引,然后将 json 文件 metastore.json 上传到您的存储桶 s3://path-to-your-bucket/hdfs-logs/metastore.json

索引日志

数据集是一个压缩的 NDJSON 文件
我们不是分别下载和索引数据,而是使用管道将解压缩的流直接发送给 Quickwit。

wget https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants.json.gz
gunzip -c hdfs-logs-multitenants.json.gz | ./quickwit index ingest --index hdfs-logs

8GB 的内存足以索引这个数据集;像 t4g.large 这样的实例,具有 8GB 内存和 2 个 vCPU,在不到 10 分钟内就索引了这个数据集(前提是您有一些 CPU 信用)。

此步骤也可以在您的本地机器上完成。
ingest 子命令会本地生成每个包含 1000 万条文档的 分片,并将它们上传到您的存储桶。具体来说,每个分片是一组索引文件和元数据文件。

您可以使用 search 子命令检查是否正在工作,并在 severity_text 字段中查找 ERROR

./quickwit index search --index hdfs-logs --query "severity_text:ERROR"

这将返回 JSON 结果:

{
  "num_hits": 345,
  "hits": [
    {
      "attributes": {
        "class": "org.apache.hadoop.hdfs.server.datanode.DataNode"
      },
      "body": "RECEIVED SIGNAL 15: SIGTERM",
      "resource": {
        "service": "datanode/16"
      },
      "severity_text": "ERROR",
      "tenant_id": 51,
      "timestamp": 1469687755
    },
    ...
  ],
  "elapsed_time_micros": 522542
}

您可以看到此查询有 345 个命中。在这种情况下,第一次运行时服务器在 523 毫秒内响应。
后续运行使用缓存的元存储,并可以在不到 100 毫秒内解决。

既然我们已经索引了日志并且可以从一个实例进行搜索,现在是时候配置并启动另外两个实例以形成集群了。

启动另外两个实例

Quickwit 需要一个端口 rest.listen_port 用于通过 TCP 提供 HTTP REST API 服务以及通过 UDP 维护集群形成。
此外,它还需要 {rest.listen_port} + 1 用于实例之间的 gRPC 通信。

在 AWS 中,您可以创建一个安全组来分组这些入站规则。请参阅我们 AWS 配置指南的 网络部分

为了简化操作,让我们创建一个安全组,打开 TCP/UDP 端口范围 [7200-7300]。
接下来,使用之前创建的安全组创建三个 EC2 实例。记下每个实例的公共 IP 地址。

现在 ssh 登录到第一个 EC2 实例,安装 Quickwit,并按照 环境配置 让 Quickwit 访问索引 S3 存储桶。

让我们在第二个和第三个 EC2 实例上安装 Quickwit。

curl -L https://install.quickwit.io | sh
cd quickwit-v*/

并配置环境,使实例能够形成集群:

export S3_PATH=s3://{path/to/bucket}/indexes
export IP_NODE_1={first-ec2-instance-public-ip}
# configuration for our second node
echo "version: 0.7
node_id: searcher-2
metastore_uri: ${S3_PATH}
default_index_root_uri: ${S3_PATH}
listen_address: 0.0.0.0
peer_seeds:
  - ${IP_NODE_1} # searcher-1
" > config.yaml

# Start a Quickwit searcher.
./quickwit run --service searcher --config config.yaml
# configuration for our third node
echo "version: 0.7
node_id: searcher-3
listen_address: 0.0.0.0
peer_seeds:
  - ${IP_NODE_1} # searcher-1
metastore_uri: ${S3_PATH}
default_index_root_uri: ${S3_PATH}
" > config.yaml

# Start a Quickwit searcher.
./quickwit run --service searcher --config config.yaml

您将在终端看到确认实例已加入现有集群的信息。例如这样的日志:

2023-03-19T16:44:56.918Z  INFO quickwit_cluster::cluster: Joining cluster. cluster_id=quickwit-default-cluster node_id=searcher-2 enabled_services={Searcher} gossip_listen_addr=0.0.0.0:7280 gossip_advertise_addr=172.31.30.168:7280 grpc_advertise_addr=172.31.30.168:7281 peer_seed_addrs=172.31.91.203:7280

现在我们可以直接向其中一个实例发出 http 请求,查询节点的 REST API 端点。

curl -v "http://0.0.0.0:7280/api/v1/hdfs-logs/search?query=severity_text:ERROR"

检查所有实例的日志,您会看到所有节点都在工作。

负载均衡传入请求

现在您有了一个搜索集群,理想情况下,您希望负载均衡外部请求。
这可以通过添加 AWS 负载均衡器来快速实现,使其监听传入的 HTTP 或 HTTPS 流量并转发到目标组。
现在您可以随意操作您的集群,随机终止进程,添加/移除新实例,并保持冷静。

清理

让我们做一些清理工作,删除索引:

./quickwit index delete --index hdfs-logs

同时记得删除安全组以保护您的 EC2 实例。如果您不再需要这些实例,可以直接删除它们。

恭喜!您完成了这个教程!

要继续您的 Quickwit 之旅,请查阅 搜索 REST API 参考查询语言参考

介绍 Quickwit 的查询语言

Quickwit 允许您使用一种简单的查询语言在已索引的文档上进行搜索。下面是一个快速概述。

子句

这种语言的主要概念是子句,它表示一个可以针对文档进行测试的简单条件。

查询字段

一个子句作用于您的文档的字段上。它的语法如下:

field:condition

例如,当搜索包含 tantivyapp_name 字段的文档时,您可以写出如下子句:

app_name:tantivy

在许多情况下,字段名称可以省略,这时 Quickwit 会使用为索引配置的 default_search_fields

条件子句速查表

Quickwit 支持多种类型的子句来表达不同种类的条件。这里有一个快速概述:

type syntax examples description default_search_field
term field:token app_name:tantivy
process_id:1234
word
term 子句检测字段中的某个值是否存在 yes
term prefix field:prefix* app_name:tant*
quick*
term 子句检测字段中的某个令牌是否以提供的值开头 yes
term set field:IN [token token ..] severity:IN [error warn] term 集合子句检测字段中的令牌集合中是否包含任何一个提供的值 yes
phrase field:"sequence of tokens" full_name:"john doe" phrase 子句检测提供的令牌序列是否存在于字段中 yes
phrase prefix field:"sequence of tokens"* title:"how to m"* phrase 前缀子句检测一个令牌序列是否存在,其中最后一个令牌的匹配方式与前缀子句相同 yes
all * * 匹配所有子句将匹配所有文档 no
exist field:* error:* 存在子句检测字段是否存在任何值,只有当字段存在时才会匹配 no
range field:bounds duration:[0 TO 1000}
last_name:[banner TO miller]
range 子句检测字段中的某个令牌是否在提供的范围内 no

查询

结合查询

可以使用布尔运算符 ANDOR 来组合子句,从而创建更复杂的搜索表达式。
AND 查询仅在运算符两侧的条件都满足时才匹配。

type:rose AND color:red

OR 查询在运算符两侧任一条件或两个条件都满足时匹配。

weekday:6 OR weekday:7

如果没有提供运算符,默认隐含为 AND

type:violet color:blue

组合查询

可以通过使用括号来组合子句构建复杂的表达式。

(type:rose AND color:red) OR (type:violet AND color:blue)

当没有使用括号时,AND 的优先级高于 OR,这意味着下面的查询等同于上面的查询。

type:rose AND color:red OR type:violet AND color:blue

否定查询

可以通过使用运算符 NOT 或者在查询前加上破折号 - 来否定一个表达式。

NOT- 的优先级高于其他运算符,因此 -a AND b 意味着 (-a) AND b,而不是 -(a AND b)

NOT severity:debug

or

type:proposal -(status:rejected OR status:pending)

更深入了解

如果您想了解更多关于查询语言的内容,请参阅 查询语言参考

更多

1. Binance 如何使用 Quickwit 构建 100PB 日志服务(Quickwit 博客)

posted @ 2024-08-26 10:09  为少  阅读(387)  评论(0编辑  收藏  举报