折腾 Quickwit,Rust 编写的分布式搜索引擎-官方教程
快速上手
在本快速入门指南中,我们将安装 Quickwit,创建一个索引,添加文档,最后执行搜索查询。本指南中使用的所有 Quickwit 命令都在 CLI 参考文档 中进行了记录。
使用 Quickwit 安装程序安装 Quickwit
Quickwit 安装程序会自动为您的环境选择正确的二进制归档文件,然后在您的工作目录中下载并解压它。
此方法仅适用于 某些操作系统/架构,并且您还需要安装一些 外部依赖项。
- https://quickwit.io/docs/get-started/installation#download
- https://quickwit.io/docs/get-started/installation#note-on-external-dependencies
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
索引配置定义了三个字段:title
、body
和 creationDate
。title
和 body
是 索引化和分词 的,并且它们也被用作默认搜索字段,这意味着如果您的查询不针对特定字段,它们将用于搜索。creationDate
作为每条记录的时间戳。没有更多的显式字段定义,因为我们使用默认的动态 模式:未声明的字段仍然会被索引,默认情况下启用了快速字段以支持聚合查询,并且使用 raw
分词器处理文本。
- https://quickwit.io/docs/configuration/index-config#text-type
- https://quickwit.io/docs/main-branch/configuration/index-config#mode
以下是完整的配置:
#
# 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 格式并对其进行索引。
- https://quickwit.io/docs/main-branch/configuration/source-config
- http://ndjson.org/
- https://quickwit-datasets-public.s3.amazonaws.com/stackoverflow.posts.transformed-10000.json
# 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 编译为一个单一的二进制文件,我们提供了多种安装方法:
- Linux/MacOS 二进制文件,您可以 手动下载 或使用 安装脚本
- Docker image
- Helm chart
- Glasskube
先决条件
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 服务。
- https://github.com/quickwit-oss/quickwit-datasource
- https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/#run-grafana-via-docker-compose
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
保存并测试,您应该会收到确认消息,表明数据源已正确设置。
您还可以设置一个新的 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
- Query:
span_name:tantivy_search
- Metric:Count
- Group by:Date Histogram :
span_start_timestamp_nanos
: 间隔 1 小时
- 一个柱状图,展示过去 6 小时内每小时 ERROR 日志的数量:
- Panel type:Bar Chart
- Query:
service_name:quickwit AND events.event_attributes.level:ERROR
- Metric:Count
- Group by:Terms :
span_start_timestamp_nanos
: 间隔 1 小时
- 在同一个柱状图上再添加一个查询,展示 WARN 日志的数量
结果
这是您的第一个仪表板可能的样子:
使用 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 时生成。- ...
以下是搜索和跟踪视图的截图:
使用 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
索引配置定义了五个字段:timestamp
、tenant_id
、severity_text
、body
,以及一个 JSON 字段用于嵌套值 resource.service
。我们本可以在这里使用对象字段并维护一个固定的模式,但为了方便起见,我们将使用 JSON 字段。
它还设置了 default_search_fields
、tag_fields
和 timestamp_field
。
timestamp_field
和 tag_fields
由 Quickwit 用于查询时的 分片剪枝,以提高搜索速度。
有关更多详细信息,请参阅 索引配置文档。
- https://quickwit.io/docs/overview/concepts/querying#time-sharding
- https://quickwit.io/docs/configuration/index-config
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_timestamp
和 end_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 或 查询语言。
- https://quickwit.io/docs/get-started/tutorials/tutorial-hdfs-logs-distributed-search-aws-s3
- https://quickwit.io/docs/reference/rest-api
- https://quickwit.io/docs/reference/query-language
使用 AWS Lambda 进行搜索
在本教程中,我们将使用 Quickwit Lambda 对位于 AWS S3 上的大约 2000 万条日志条目(解压缩后 7 GB)进行索引和搜索。
具体来说,我们将部署一个包含 Quickwit Lambda 的 AWS CloudFormation 栈,以及两个存储桶:一个暂存存储桶用于存放待索引的 gzip 压缩的新行分隔 JSON 文件,另一个存储桶用于存放索引数据。暂存存储桶是可选的,因为 Quickwit 索引器可以从它有访问权限的任何 S3 文件读取数据。
安装
安装 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 上搜索日志服务,该文章覆盖了一个端到端的应用案例。
基于 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 上部署的 建议,以避免月底出现一些不愉快的意外。
首先,让我们创建一个 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_ID
和AWS_SECRET_ACCESS_KEY
环境变量来完成,或者通过 AWS 凭证文件。通常位于~/.aws/credentials
。
更多信息请参阅 我们的 AWS 配置指南
现在我们可以创建一个 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
索引配置定义了五个字段:timestamp
、tenant_id
、severity_text
、body
,以及一个 JSON 字段用于嵌套值 resource.service
。我们本可以在这里使用对象字段并维护一个固定的模式,但为了方便起见,我们将使用 JSON 字段。
它还设置了 default_search_fields
、tag_fields
和 timestamp_field
。timestamp_field
和 tag_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
例如,当搜索包含 tantivy
的 app_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 |
查询
结合查询
可以使用布尔运算符 AND
和 OR
来组合子句,从而创建更复杂的搜索表达式。
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)
更深入了解
如果您想了解更多关于查询语言的内容,请参阅 查询语言参考。