在 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 参考 或 查询语言参考。