仓库分析 API
分析一个仓库,报告其性能特征以及发现的任何错误行为。
POST /_snapshot/<repository>/_analyze
前置条件
- 如果启用了 Elasticsearch 安全功能,你必须具有
manage集群权限。
描述
此 API 分析仓库,报告其性能特征以及发现的任何不正确行为。它旨在检测第三方存储系统是否适合用作快照仓库。
推荐的测试方法:
- 从默认参数开始,以发现简单的问题。
- 然后运行规模越来越大的分析,直到至少达到:
blob_count为 2000、max_blob_size为 2gb、max_total_data_size为 1tb、register_operation_count为 100。 - 使用充裕的
timeout,可能为 1 小时或更长。 - 使用与生产环境规模相似的多节点集群,因为有些问题只在多个节点并发访问时才会出现。
如果分析失败,则说明仓库的行为不符合预期 — 通常是存储 API 的实现不正确或不兼容,使其不适合用于快照。向此类存储进行快照可能看似正常工作,但数据存在风险。为确认这一点,请验证针对该存储协议的参考实现(例如真实的 AWS S3)是否也会出现相同的故障。除非你能证明在参考实现上也存在相同的问题,否则不要报告涉及第三方存储的 Elasticsearch 问题。
如果分析成功,它会返回测试细节(可选地包含每次操作的计时信息)。但成功的分析不能保证仓库能正确工作,因为它不会测试:
- 持久写入(blob 必须在断电后仍然存在,直到被删除)。
- 静默数据损坏(blob 内容在被修改或删除之前必须保持不变)。
- 连接中断时的正确行为(读写可能失败,但不能返回不正确的结果)。
此 API 会写入大量数据并将其读回;它会消耗网络、存储和 IO 带宽。它遵循 max_snapshot_bytes_per_sec、max_restore_bytes_per_sec 和 indices.recovery.max_bytes_per_sec 的限流设置。
如果在等待期间客户端连接关闭,测试将被取消。遗留的数据路径会记录在 Elasticsearch 日志中;请验证并手动清理。
此 API 旨在供人类以探索方式使用。其参数和响应格式可能会发生变化。较新的 Elasticsearch 版本可能会更严格(通过某个版本测试的存储系统可能会在另一个版本中失败)。在混合版本的集群中,此 API 可能无法正确工作。
实现细节
该分析包含 blob 级任务(由 blob_count 控制)和对可线性化寄存器(linearizable registers)的比较交换操作(由 register_operation_count 控制),分布在具备数据节点资格和主节点资格的节点上:
- 写后读任务:一个节点写入一个 blob(大小在
max_blob_size和max_total_data_size限制内随机),然后其他节点尝试读取它。读取失败意味着缺少写后读(read-after-write)语义。 - 早期读取:其他节点在写入仍在进行时进行读取 — 读取可能失败,但不能返回部分数据(测试原子性)。
- 覆盖测试:当其他节点正在读取 blob 时该 blob 被覆盖 — 读取可以返回任一版本,但不能返回部分数据或两个 blob 的混合。
- 多种读写方法:例如,单部分和多部分上传;完整读取或部分范围读取。
- 中止写入:一个节点在写入过程中途中止写入;其他节点对 blob 的读取必须失败(找不到该 blob)。
- 可线性化寄存器:通过原子比较交换操作操纵 blob。该分析验证:
- 无竞争的比较交换操作总是成功。
- 有竞争的操作要么成功,要么报告竞争,绝不会返回不正确的结果(竞争会触发重试)。
- 大多数操作会原子地递增一个 8 字节的计数器 blob;一些操作会验证其他 blob 大小上的行为。
路径参数
<repository>
(必需,字符串)要测试的快照仓库的名称。
查询参数
blob_count
(可选,整数)默认为 100。要写入的 blob 总数。要进行符合实际的实验,应至少设置为 2000。
max_blob_size
(可选,字节单位)默认为 10mb。单个 blob 的最大大小。要进行符合实际的实验,应至少设置为 2gb。
max_total_data_size
(可选,字节单位)默认为 1gb。所有 blob 总大小的上限。要进行符合实际的实验,应至少设置为 1tb。
register_operation_count
(可选,整数)默认为 10。要执行的可线性化寄存器操作的最小数量。要进行符合实际的实验,应至少设置为 100。
timeout
(可选,时间单位)默认为 30s。等待测试完成的期限;如果超过此期限,测试将被取消并返回错误。
高级查询参数
concurrency
(可选,整数)默认为 10。并发写入操作的数量。
read_node_count
(可选,整数)默认为 10。每次写入 blob 后执行读取的节点数量。
early_read_node_count
(可选,整数)默认为 2。执行早期读取(即在写入仍在进行时读取)的节点数量。早期读取很少被执行。
rare_action_probability
(可选,双精度浮点数)默认为 0.02。针对每个 blob 执行罕见操作(早期读取、覆盖或中止写入)的概率。
seed
(可选,整数)用于生成操作列表的伪随机数生成器(PRNG)种子。相同的种子会重现相同的操作(尽管并发执行的顺序可能会有所不同)。
detailed
(可选,布尔值)默认为 false。返回包含每次操作计时信息的详细结果。
rarely_abort_writes
(可选,布尔值)默认为 true。是否偶尔中止一些写入请求。
响应体
响应中包含实现细节,其格式在不同版本之间不稳定。
coordinating_node
协调分析并执行最终清理的节点,包含:
id:节点的 ID。name:节点的名称。
repository
被分析的仓库的名称。
blob_count
写入的 blob 数量(等于 blob_count 查询参数)。
concurrency
并发写入操作的数量(等于 concurrency 查询参数)。
read_node_count
读取节点限制(等于 read_node_count 查询参数)。
early_read_node_count
早期读取节点限制(等于 early_read_node_count 查询参数)。
max_blob_size / max_blob_size_bytes
单个 blob 的最大大小限制(人类可读格式 / 字节数)。
max_total_data_size / max_total_data_size_bytes
所有数据总大小的限制(人类可读格式 / 字节数)。
seed
使用的 PRNG 种子(如果设置则等于 seed 查询参数)。
rare_action_probability
罕见操作的概率(等于 rare_action_probability 查询参数)。
blob_path
写入所有测试 blob 时所在的仓库路径。
issues_detected
检测到的正确性问题列表;如果 API 成功则为空。包含此字段是为了强调:即使成功,也不能保证将来的行为是正确的。
summary 对象
summary.write
写入操作的摘要,包含:
count:写入操作的数量。total_size/total_size_bytes:写入的 blob 总大小(人类可读格式 / 字节数)。total_throttled/total_throttled_nanos:由于max_snapshot_bytes_per_sec限流而等待的时间。total_elapsed/total_elapsed_nanos:写入的总耗时。
summary.read
读取操作的摘要,包含:
count:读取操作的数量。total_size/total_size_bytes:读取的 blob(或 blob 的部分内容)总大小。total_wait/total_wait_nanos:等待每次读取第一个字节的总时间。max_wait/max_wait_nanos:任一读取的最大首字节等待时间。total_throttled/total_throttled_nanos:由于max_restore_bytes_per_sec或indices.recovery.max_bytes_per_sec限流而等待的时间。total_elapsed/total_elapsed_nanos:读取的总耗时。
summary.details
每次读写操作的详细信息;仅在 detailed 为 true 时返回。每一项包含:
blob(对象)被操作的 blob,包含:name(名称)、size/size_bytes(大小)、read_start/read_end(读取的时间范围)、read_early(布尔值 — 读取是否在写入完成之前开始)、overwritten(布尔值 — blob 是否在读取期间被覆盖)。writer_node(对象)写入该 blob 并协调其读取的节点,包含id和name。write_elapsed/write_elapsed_nanos:写入该 blob 所用的时间。overwrite_elapsed/overwrite_elapsed_nanos:覆盖所花的时间;如果未覆盖则省略。write_throttled/write_throttled_nanos:限流等待时间(通过max_snapshot_bytes_per_sec,对于托管服务则为indices.recovery.max_bytes_per_sec)。reads:对该 blob 的每次读取操作,每一项包含:node:执行读取的节点(id、name)。before_write_complete(布尔值):读取是否可能在写入完成之前开始;如果为false则省略。found(布尔值):是否找到了该 blob(对于早期读取或中止的写入可能为false)。first_byte_time/first_byte_time_nanos:首字节延迟;如果未找到则省略。elapsed/elapsed_nanos:读取持续时间;如果未找到则省略。throttled/throttled_nanos:读取限流等待时间;如果未找到则省略。
listing_elapsed/listing_elapsed_nanos:列出容器中所有 blob 所用的时间。delete_elapsed/delete_elapsed_nanos:删除容器中所有 blob 所用的时间。
示例
以下示例分析仓库 my_repository:
POST /_snapshot/my_repository/_analyze?blob_count=10&max_blob_size=1mb&timeout=120s