为生产传输编写脚本

概览

如果您在大型生产任务(例如每晚上传或下载数 GiB 数据)中使用 gsutil,则可以采取多项措施来确保操作成功完成。具体来说,本部分介绍了如何围绕 gsutil 的可续传传输机制为大型生产任务编写脚本。

有关可续传传输的背景知识

首先,有必要了解 gsutil 的可续传传输机制以及如何围绕此机制实现您的脚本以确保可靠运行。当您尝试下载任意大小的文件或上传大于可配置阈值(默认情况下,此阈值为 8 MiB)的文件时,gsutil 会使用可续传传输支持。如果传输中途失败(例如由于间歇性网络问题),gsutil 会使用截断的随机二进制指数退避和重试策略;默认情况下,该策略在 10 分钟的时间段内最多重试 23 次传输(请参阅 gsutil 帮助:重试了解详情)。如果所有这些传输尝试均失败且没有任何进展,则 gsutil 会放弃传输,但会将其“跟踪器”文件保留在一个可配置的位置(默认位置为 ~/.gsutil/,位于一个以存储分区名称和待传输对象名称的 SHA1 哈希值组合以及文件名的最后 16 个字符命名的文件中)。如果传输以这种方式失败,您可以稍后重新运行 gsutil(例如在网络问题解决后),可续传传输机制会接续上次进度执行。

为数据传输任务编写脚本

如需围绕此机制为大型生产数据传输任务编写脚本,您可以实现一个定期运行的脚本来确定哪些文件传输尚未成功完成并运行 gsutil 对其进行复制。下面,我们提供一些有关如何实现此类脚本的建议:

  1. 如果可续传传输在长达 10 分钟的过程中连续失败 23 次且没有任何进展,那么简单地立即重试传输可能就行不通了。一个较为成功的策略是:构建一个每 30 分钟运行一次的 Cron 作业来确定需要运行哪些传输并运行它们。如果网络出现间歇性问题,脚本会在网络问题得到解决后从中断的地方继续执行,并将最终取得成功。

  2. 如果您的业务依赖于及时的数据传输,您应该考虑实施一定程度的网络监控。例如,您可以实现一项任务,使其每隔几分钟尝试一次小规模下载,并在连续几次尝试失败(失败频率可能会更高或更低,具体取决于您的要求)时发出提醒,以便您的 IT 人员能够迅速调查问题。与监控实现一样,您应该对提醒阈值进行实验,以避免误报提醒,导致员工开始忽略提醒。

  3. 您可以通过多种方式确定要传输的文件。我们建议您不要尝试获取包含很多对象(例如数万个或更多)的存储分区的完整列表。一种策略是以一种表示传输过程的方式来构建对象名称,并使用 gsutil 前缀通配符来请求部分存储分区列表。例如,如果您的定期过程涉及下载当天的对象,则可以使用“年-月-日-对象 ID”格式命名对象,然后使用诸如 gsutil ls "gs://bucket/2011-09-27-*" 之类的命令查找当天的对象。请注意,像这样使用非通配符前缀比使用 gsutil ls "gs://bucket/*-2011-09-27" 之类的内容更高效。后一个命令实际上请求完整的存储分区列表,然后在 gsutil 中进行过滤,而前一个命令则要求 Google Storage 返回名称以“*”之前的所有内容开头的对象的子集。

    对于数据上传,另一种方法是将本地文件从“待处理”区域移至“完成”区域,因为脚本会成功将文件复制到云端。您可以使用类似如下所示的命令并行批量执行此操作:

    gsutil -m cp -r to_upload/subdir_$i gs://bucket/subdir_$i
    

    其中,i 是一个 shell 循环变量。请务必在每个 gsutil cp 命令之后检查 shell $status 变量是否为 0,以检测某些副本是否失败,然后重新运行受影响的副本。

    使用此策略时,文件系统会跟踪所有待完成的剩余工作。

  4. 如果单个存储分区中确实有大量对象(例如数十万个或更多),则应考虑在数据库中跟踪对象,而不是使用存储分区列表来枚举这些对象。例如,此数据库可以跟踪下载状态,因此您可以通过在本地查询数据库(而不是执行存储分区列出操作)来确定定期下载脚本需要下载的对象。

  5. 确保在传输失败后不要删除部分下载的临时文件:gsutil 会从上次停止的位置继续执行(并对最终下载内容执行哈希处理以确保数据完整性),因此删除部分传输的文件会导致进度丢失以及网络资源浪费。

  6. 如果您的网络连接速度较快,可以使用 gsutil -m(多线程/多处理)选项加快大量文件的传输。不过请注意,如果某些文件下载失败,gsutil 不会尝试跟踪成功下载的文件。例如,如果您使用多线程传输下载 100 个文件,但下载失败 3 次,那么由脚本编制过程确定哪些传输失败并重试这些传输。如前文所述,定期检查并运行 (check-and-run) 方法可处理这种情况。

    如果您使用的是并行传输 (gsutil -m),则可能需要通过 .boto 配置文件中的 parallel_thread_count 设置来对所使用的线程数进行实验。默认情况下,gsutil 在 Linux 系统上使用 10 个线程,而在其他操作系统上使用 24 个线程。根据您的网络速度、可用内存、CPU 负载和其他条件,这未必是最佳选择。建议尝试使用更多或更少的线程,以找到最适合您的环境的线程数。