Help us learn about your current experience with the documentation. Take the survey.

上传开发指南

上传是许多 GitLab 功能的重要组成部分。为了解 GitLab 如何处理上传,本页提供了将文件传输到存储目标的关键机制概述。

GitLab 的上传功能按特性配置。所有涉及上传的功能都提供相同的配置选项,但它们可以相互独立配置。例如,Git LFS 上传可以独立于 CI/CD 构建工件上传进行配置,但它们都提供相同的一组设置键。这些设置决定了上传的处理方式,对性能和可扩展性有重大影响。

本页总结了在决定如何处理此类文件时重要的上传设置。接下来的章节将详细描述每种机制。

上传设置如何驱动上传流程

在我们更详细地研究各个上传策略之前,让我们先看看哪些上传设置映射到这些策略的高级分解。

上传设置本身在上传管理中有文档说明。在这里,我们重点关注这些设置如何驱动 GitLab 上传逻辑的内部机制。在顶层,我们区分上传文件的两种目标

  • 本地存储 - 文件存储在附加到 Web 服务器节点的卷上。
  • 对象存储 - 文件存储在远程对象存储桶中。

在此表中,x.y.z 指定了通过 gitlab.yml 的路径:

设置 行为
<feature>.object_store.enabled false 文件存储在 <feature>.storage_path 本地
<feature>.object_store.enabled true 文件存储在 <feature>.object_store.remote_directory 远程

使用对象存储时,管理员可以控制这些文件如何移动到相应的存储桶。这种移动可以通过以下方式之一发生:

单独的 Sidekiq 工作进程也可能将文件存储在对象存储中,但这不是本文档涵盖的内容。

最后,Workhorse 使用上传缓冲机制协助大多数用户发起的上传,以将耗时的工作排除在 Rails 控制器之外。这种机制在Workhorse 协助的上传中有说明,因为它与我们之前讨论的大部分内容并行运行。

我们现在更详细地查看每种情况。

本地存储

本地存储是上传可以采取的最简单路径。这是 GitLab 早期处理上传的方式。它假设一个存储卷(如磁盘或网络附加存储)在 storage_path 处对 Rails 应用程序是可访问的。此文件路径相对于 Rails 根目录,并且像任何上传设置一样,可以按特性配置。

当客户端发送文件上传时,Workhorse 首先将文件缓冲到磁盘,这种机制在Workhorse 协助的上传中有更详细的说明。当请求到达 Rails 应用程序时,文件已存在于本地存储中,因此 Rails 只需将其移动到指定目录即可完成事务。

本地存储不能与云原生 GitLab (CNG) 安装一起使用。因此 GitLab SaaS 也不使用它。

对象存储

为了提供可水平扩展的存储,您必须使用对象存储提供商,例如:

  • Amazon AWS.
  • Google Cloud Storage (GCS).
  • Azure Cloud Storage.

使用对象存储提供两个主要好处:

  • 轻松添加更多存储容量:云提供商为您自动完成。
  • 启用 GitLab 安装的水平扩展:当数据存储在对象存储中时,多个 GitLab 应用服务器可以访问相同的数据。

包括 GitLab SaaS 在内的 CNG 安装始终使用对象存储(GitLab SaaS 的情况使用 GCS)。

上传到远程对象存储的一个挑战是,它包括从 GitLab 到对象存储提供商的出站 HTTP 请求。如上所述,对于如何发送此 HTTP 请求,有三种不同的策略可用。

Rails 控制器上传

当直接上传不可用时,Rails 将文件上传到对象存储,作为控制器 create 操作的一部分。哪个控制器负责取决于上传的文件类型。

Rails 控制器上传与上传到本地存储非常相似。主要区别在于:Rails 必须向对象存储发送 HTTP 请求。这是通过 CarrierWave Fog 上传器完成的。

与本地存储一样,这种策略受益于 Workhorse 协助,以将一些耗时的 I/O 工作排除在 Ruby 和 Rails 之外。直接上传在这方面做得更好,因为它也将向对象存储的 HTTP PUT 请求保持在 Puma 之外。

此策略仅适用于小文件上传,因为它受 Puma 60 秒请求超时的限制。

直接上传

直接上传是将大文件移动到 GitLab SaaS 等 CNG 安装中的对象存储的推荐方式。

启用直接上传后,Workhorse:

  1. 使用 Rails 授权请求。
  2. 与对象存储本身建立连接,将文件传输到临时位置。
  3. 传输完成后,Workhorse 使用 Rails 完成请求。
  4. 通过删除对象存储中的临时文件完成上传。

这种策略是 Workhorse 协助 的不同形式。它不依赖于 Workhorse 和 Puma 都可以访问的共享存储。

在所有现有的上传策略中,直接上传最能处理大文件(千兆字节)上传。

磁盘缓冲上传

当在对象存储设置中禁用 direct_upload 时,直接上传会回退到_磁盘缓冲上传_。/authorize 调用的答案只包含文件系统路径。

sequenceDiagram
    participant c as Client
    participant w as Workhorse
    participant r as Rails
    participant os as Object Storage

    activate c
    c ->>+w: POST /some/url/upload

    w ->>+r: POST /some/url/upload/authorize
    Note over w,r: this request has an empty body
    r-->>-w: presigned OS URL

    w->>+os: PUT file
    Note over w,os: file is stored on a temporary location. Rails select the destination
    os-->>-w: request result

    w->>+r:  POST /some/url/upload
    Note over w,r: file was replaced with its location<br>and other metadata

    r->>+os: move object to final destination
    os-->>-r: request result

    opt requires async processing
      r->>+redis: schedule a job
      redis-->>-r: job is scheduled
    end

    r-->>-c: request result
    deactivate c
    w->>-w: cleanup

    opt requires async processing
      activate sidekiq
      sidekiq->>+redis: fetch a job
      redis-->>-sidekiq: job

      sidekiq->>+os: get object
      os-->>-sidekiq: file

      sidekiq->>sidekiq: process file

      deactivate sidekiq
    end

Workhorse 协助的上传

大多数上传都会以某种方式获得 Workhorse 的协助。

  • 通常,Workhorse 将上传缓冲到临时文件。Workhorse 向请求添加元数据,以告知 Puma 临时文件的名称和位置。这需要在 Workhorse 和 Puma 之间共享临时存储。所有 GitLab 安装(包括 CNG)都有此共享临时存储。
  • Workhorse 有时会预处理文件。例如,对于 CI 工件上传,Workhorse 创建 ZIP 文件内容的单独索引。在 Workhorse 中这样做可以绕过 Puma 请求超时。与 Sidekiq 后台处理相比,这样做的优点是用户不会看到 GitLab 已接受文件但尚未处理的中间状态。
  • 使用直接上传,Workhorse 可以预处理文件并将其上传到对象存储。将大文件上传到对象存储需要时间;在 Workhorse 中这样做可以避免 Puma 请求超时。

有关上传的更多信息,请参阅Workhorse 处理程序