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

应用限制开发

本文档为贡献者提供了在 GitLab 中添加应用限制的开发指南。

文档

首先,您需要收集信息并确定针对不同 GitLab 版本设置的不同限制。与他人协调,记录并传达这些限制。

有一份关于引入应用限制的指南。

实现计划限制

插入数据库计划限制

plan_limits 表中,创建一个新列并插入限制值。建议创建两个独立的迁移脚本文件。

  1. plan_limits 表添加一个具有非空默认值的新列,该值表示所需的限制,例如:

    add_column(:plan_limits, :project_hooks, :integer, default: 100, null: false)

    设置为 0 的计划限制条目表示未启用限制。您仅在特殊且已记录的情况下才应使用此设置。

  2. (可选)使用 create_or_update_plan_limit 迁移助手创建数据库迁移,微调每个级别的所需限制。此迁移中的计划应与 GitLab.com 上的计划 匹配。如果遗漏了某个计划,该计划上的客户将收到默认限制,可能是 0(无限制)。

    例如:

    class InsertProjectHooksPlanLimits < Gitlab::Database::Migration[2.1]
      def up
        create_or_update_plan_limit('project_hooks', 'default', 0)
        create_or_update_plan_limit('project_hooks', 'free', 10)
        create_or_update_plan_limit('project_hooks', 'premium', 30)
        create_or_update_plan_limit('project_hooks', 'premium_trial', 30)
        create_or_update_plan_limit('project_hooks', 'ultimate', 100)
        create_or_update_plan_limit('project_hooks', 'ultimate_trial', 100)
        create_or_update_plan_limit('project_hooks', 'ultimate_trial_paid_customer', 100)
        create_or_update_plan_limit('project_hooks', 'opensource', 100)
      end
    
      def down
        create_or_update_plan_limit('project_hooks', 'default', 0)
        create_or_update_plan_limit('project_hooks', 'free', 0)
        create_or_update_plan_limit('project_hooks', 'premium', 0)
        create_or_update_plan_limit('project_hooks', 'premium_trial', 0)
        create_or_update_plan_limit('project_hooks', 'ultimate', 0)
        create_or_update_plan_limit('project_hooks', 'ultimate_trial', 0)
        create_or_update_plan_limit('project_hooks', 'ultimate_trial_paid_customer', 0)
        create_or_update_plan_limit('project_hooks', 'opensource', 0)
      end
    end

    某些计划仅存在于 GitLab.com 上。对于不存在的计划,这是一个空操作。

    要在迁移中仅为 GitLab.com 设置限制并允许其他实例使用默认限制,请在 #up#down 方法的开头添加 return unless Gitlab.com?,以使迁移对其他实例成为空操作。

计划限制验证

获取当前限制

可以通过项目或命名空间访问当前限制,例如:

project.actual_limits.project_hooks

检查当前限制

有一个方法 PlanLimits#exceeded? 用于检查是否超出当前限制。您可以使用 ActiveRecord 对象或 Integer

确保记录数不超过定义的限制,例如:

project.actual_limits.exceeded?(:project_hooks, ProjectHook.where(project: project))

确保数量不超过定义的限制,例如:

project.actual_limits.exceeded?(:project_hooks, 10)

Limitable 关切

Limitable 关切可用于验证模型是否超出限制。它确保当前模型的记录数不超过定义的限制。

您必须指定被验证对象的限制范围,如果限制名称与复数形式的模型名称不同,还需指定限制名称。

class ProjectHook
  include Limitable

  self.limit_name = 'project_hooks' # 可选,因为 ProjectHook 对应 project_hooks
  self.limit_scope = :project
end

要测试模型,您可以包含共享示例。

it_behaves_like 'includes Limitable concern' do
  subject { build(:project_hook, project: create(:project)) }
end

测试实例范围限制

实例范围功能始终使用 default 计划,因为实例范围功能没有分配许可证。

class InstanceVariable
  include Limitable

  self.limit_name = 'instance_variables' # 可选,因为 InstanceVariable 对应 instance_variables
  self.limit_scope = Limitable::GLOBAL_SCOPE
end

订阅计划

GitLab 自托管:

  • default:所有人。

GitLab.com:

  • default:任何系统范围的功能。
  • free:具有免费订阅的命名空间和项目。
  • premium:具有高级订阅的命名空间和项目。
  • premium_trial:具有高级试用订阅的命名空间和项目。
  • ultimate:具有终极订阅的命名空间和项目。
  • ultimate_trial:具有终极试用订阅的命名空间和项目。
  • ultimate_trial_paid_customer:具有高级订阅并正在试用 Ultimate 30 天的命名空间和项目。
  • opensource:属于 GitLab 开源计划的成员的命名空间和项目。

GitLab.com 上有一个 early_adopter 计划,没有订阅。

test 环境没有任何计划。

使用 Rack::Attack 实现速率限制

我们使用 Rack::Attack 中间件来限制 Rack 请求。这适用于 Rails 控制器、Grape 端点以及任何其他 Rack 请求。

添加新限制的过程大致如下:

  1. ApplicationSetting 模型中向 rate_limits JSONB 列 添加新字段。
  2. 更新 rate_limits 列 的 JSON 架构验证器。
  3. 扩展 Gitlab::RackAttackGitlab::RackAttack::Request 以配置新的速率限制,并将其应用于所需的请求。
  4. 将新设置添加到 app/views/admin/application_settings/_ip_limits.html.haml 中的 Admin 区域表单。
  5. 用户和 IP 速率限制应用程序设置 API 中记录新设置。
  6. 为 GitLab.com 配置速率限制,并在 GitLab.com 上的速率限制 中记录。

有关实施细节,请参考以下过去的问题:

使用 Gitlab::ApplicationRateLimiter 实现速率限制

该模块实现了一个自定义速率限制器,可用于限制某些操作。与在中间件级别运行的 Rack::AttackRack::Throttle 不同,它可以在控制器或 API 级别使用。

有关在控制器中使用,请参见 CheckRateLimit 关切。在代码的其他部分,可以直接调用 Gitlab::ApplicationRateLimiter 模块。

下一个速率限制架构

2022年5月,我们开始使用前瞻性的速率限制架构开发应用程序限制框架的下一个迭代。

我们正在定义新需求并设计下一个架构,因此如果您需要新功能来添加新限制,而不是立即构建它们,请考虑贡献于 速率限制架构工作组

我们可能希望在下一个速率限制架构迭代中构建的功能示例:

  1. 能够按命名空间/计划定义和覆盖限制。
  2. 自动生成关于已实施限制及其默认值的文档。
  3. 在单一位置定义限制,该位置可以被找到和探索。
  4. 软限制和硬限制,支持在接近限制时通知用户。