处理特定的作业类别

caution 以下是高级设置。大多数极狐GitLab 实例应该添加更多进程来监听所有队列。

极狐GitLab 有两个选项用于创建仅处理特定作业类的 Sidekiq 进程:

  1. 路由规则在 SaaS 上使用。它们将应用程序内部的作业定向到管理员配置的队列名称,降低了 Redis 的负载,对于非常大规模的部署很重要。
  2. 在启动 Sidekiq 进程时,队列选择器用于在应用程序外部执行作业选择。队列选择器在 SaaS 上使用到 2021 年 9 月,并出于兼容性原因保留。

这两者都使用相同的 worker 匹配查询语法。虽然它们在技术上可以一起使用,但大多数部署应该选择其中之一。

所有极狐GitLab 节点的路由规则必须相同,因为它们是应用程序配置的一部分。队列选择器在极狐GitLab 节点之间可能不同,因为它们只会更改启动的 Sidekiq 进程的参数。

路由规则

  • 引入于 13.12 版本。
  • 默认路由规则值添加于 15.4 版本。
note Mailer 作业无法通过路由规则进行路由,并且始终会进入 mailers 队列。使用路由规则时,确保至少有一个进程正在侦听 mailers 队列。通常可以放在 default 队列旁边。

我们建议大多数极狐GitLab 实例,使用路由规则来管理它们的 Sidekiq 队列,其允许管理员根据作业类的属性为作业类组选择单个队列名称。语法是成对的 [query, queue] 有序数组:

  1. 该查询是一个 worker 匹配查询
  2. 队列名称必须是有效的 Sidekiq 队列名称。如果队列名称为 nil 或空字符串,则 worker 将路由到由 worker 名称生成的队列(有关详细信息,请参阅可用作业类列表)。队列名称不必与可用作业类列表中的任何现有队列名称相匹配。
  3. 为该 worker 选择与其匹配的第一个查询,以后的规则将被忽略。

路由规则迁移

Sidekiq 路由规则更改后,管理员必须注意迁移以避免完全丢失作业,尤其是在作业队列很长的系统中。迁移可以按照 Sidekiq 作业迁移中提到的迁移步骤完成。

详细示例

以下为旨在展示不同可能性的综合示例,不是建议。

  1. 编辑 /etc/gitlab/gitlab.rb

    sidekiq['routing_rules'] = [
      # Route all non-CPU-bound workers that are high urgency to `high-urgency` queue
      ['resource_boundary!=cpu&urgency=high', 'high-urgency'],
      # Route all database, gitaly and global search workers that are throttled to `throttled` queue
      ['feature_category=database,gitaly,global_search&urgency=throttled', 'throttled'],
      # Route all workers having contact with outside world to a `network-intenstive` queue
      ['has_external_dependencies=true|feature_category=hooks|tags=network', 'network-intensive'],
      # Route all import workers to the queues generated by the worker name, for
      # example, JiraImportWorker to `jira_import`, SVNWorker to `svn_worker`
      ['feature_category=import', 'import'],
      # Wildcard matching, route the rest to `default` queue
      ['*', 'default']
    ]
    

    然后可以设置 queue_groups 以匹配这些生成的队列名称。例如:

    sidekiq['queue_selector'] = false
    sidekiq['queue_groups'] = [
      # Run two high-urgency processes
      'high-urgency',
      'high-urgency',
      # Run one process for throttled, network-intensive, import
      'throttled,network-intensive,import',
      # Run one 'catchall' process on the default and mailers queues
      'default,mailers'
    ]
    
  2. 保存文件并重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

队列选择器

queue_selector 选项允许使用 worker 匹配查询,以更通用的方式选择队列组。设置 queue_selector 后,所有 queue_groups 必须遵循上述语法。

使用队列选择器

  1. 编辑 /etc/gitlab/gitlab.rb

    sidekiq['enable'] = true
    sidekiq['routing_rules'] = [['*', nil]]
    sidekiq['queue_selector'] = true
    sidekiq['queue_groups'] = [
      # Run all non-CPU-bound queues that are high urgency
      'resource_boundary!=cpu&urgency=high',
      # Run all continuous integration and pages queues that are not high urgency
      'feature_category=continuous_integration,pages&urgency!=high',
      # Run all queues
      '*'
    ]
    
  2. 保存文件并重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

Negate 设置

此设置允许您让 Sidekiq 进程在每个队列上工作,除了您列出的队列,一般只有在有多个 Sidekiq 节点的情况下才会用到。在此示例中,我们从 Sidekiq 节点中排除了所有与导入相关的作业。

  1. 编辑 /etc/gitlab/gitlab.rb

    sidekiq['routing_rules'] = [['*', nil]]
    sidekiq['negate'] = true
    sidekiq['queue_selector'] = true
    sidekiq['queue_groups'] = [
       "feature_category=importers"
    ]
    
  2. 保存文件并重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

从队列选择器迁移到路由规则

我们建议极狐GitLab 部署添加更多监听所有队列的 Sidekiq 进程。对于非常大规模的部署,我们建议使用 路由规则,而不是队列选择器。我们在 JihuLab.com 上使用路由规则,因为它有助于降低 Redis 的负载。

从队列选择器迁移到路由规则:

  1. 打开 /etc/gitlab/gitlab.rb
  2. sidekiq['queue_selector'] 设置为 false
  3. 获取 sidekiq['queue_groups'] 中的所有队列 selector
  4. 给每个 selector 设置一个 queue_name,格式为 [selector, queue_name]
  5. sidekiq['routing_rules'] 替换为一组 [selector, queue_name] 条目。
  6. sidekiq['routing_rules'] 中添加一个通配符匹配项 ['*', 'default'] 作为最后一个条目。这个 catchall 队列必须命名为 default
  7. sidekiq['queue_groups'] 替换为 queue_name
  8. 添加至少一个 default 队列和至少一个 mailers 队列到 sidekiq['queue_groups']
  9. 保存文件并重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    
  10. 运行 Rake 任务,迁移现有作业

    sudo gitlab-rake gitlab:sidekiq:migrate_jobs:retry gitlab:sidekiq:migrate_jobs:schedule gitlab:sidekiq:migrate_jobs:queued
    
note 在重新配置极狐GitLab 后立即运行 Rake 任务很重要。 重新配置极狐GitLab 后,现有作业不会被处理,直到 Rake 任务开始迁移作业。

下面的例子更好地说明了上面的迁移过程:

  1. 查看 /etc/gitlab/gitlab.rb 的如下内容:

    sidekiq['routing_rules'] = []
    sidekiq['queue_selector'] = true
    sidekiq['queue_groups'] = [
      'urgency=high',
      'urgency=low',
      'urgency=throttled',
      '*'
    ]
    
  2. 更新 /etc/gitlab/gitlab.rb 以使用路由规则:

    sidekiq['min_concurrency'] = 20
    sidekiq['max_concurrency'] = 20
    
    sidekiq['routing_rules'] = [
      ['urgency=high', 'high_urgency'],
      ['urgency=low', 'low_urgency'],
      ['urgency=throttled', 'throttled_urgency'],
      # Wildcard matching, route the rest to `default` queue
      ['*', 'default']
    ]
    
    sidekiq['queue_selector'] = false
    sidekiq['queue_groups'] = [
      'high_urgency',
      'low_urgency',
      'throttled_urgency',
      'default,mailers'
    ]
    
  3. 保存文件并重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    
  4. 运行 Rake 任务以迁移现有作业

    sudo gitlab-rake gitlab:sidekiq:migrate_jobs:retry gitlab:sidekiq:migrate_jobs:schedule gitlab:sidekiq:migrate_jobs:queued
    
caution 并发部分中所述,我们建议将 min_concurrencymax_concurrency 设置为相同的值。例如,队列组条目中的队列数为 1min_concurrency 设置为 0max_concurrency 设置为 20,则生成的并发数设置为 2。在大多数情况下,2 的并发性可能太低,CPU 绑定非常高的任务除外。

Worker 匹配查询

极狐GitLab 提供了一种查询语法来根据其属性匹配 worker。队列路由规则队列选择器都使用此查询语法。查询包括两个部分:

  • 可以选择的属性。
  • 用于构造查询的运算符。

可用属性

队列匹配查询适用于 worker 属性。我们支持基于 worker 属性子集的查询:

  • feature_category - 队列所属的极狐GitLab 功能类别。例如,merge 队列属于 source_code_management 类别。
  • has_external_dependencies - 队列是否连接到外部服务。例如,所有导入器都将此设置为 true
  • urgency - 该队列的作业快速运行是多么重要。可以是 highlowthrottled。例如,authorized_projects 队列用于刷新用户权限,是 high 紧急的。
  • worker_name - worker 名称。使用此属性来选择特定的 worker。
  • name - 从 worker 名称生成的队列名称。使用此属性选择特定队列。因为这是从 worker 名称生成的,所以不会根据其他路由规则的结果而改变。
  • resource_boundary - 队列被 cpumemoryunknown 绑定。例如,ProjectExportWorker 是内存绑定的,因为它必须在保存数据以供导出之前将数据加载到内存中。
  • tags - 队列的短期注释。这些预计会在不同版本之间频繁更改,并且可能会被完全删除。

has_external_dependencies 是一个 boolean 属性:只有确切的字符串 true 被认定为 true,其他的都被认定为 false。

tags 是一个集合,这意味着 = 检查相交集,而 != 检查不相交集。例如,tags=a,b 选择具有标签 ab 或两者兼有的队列。tags!=a,b 选择没有这些标签的队列。

可用的运算符

路由规则和队列选择器支持以下运算符,从最高到最低优先级列出:

  • | - 逻辑 OR 运算符。例如,query_a|query_b(其中 query_aquery_b 是由此处的其他运算符组成的查询)包括匹配任一查询的队列。
  • & - 逻辑 AND 运算符。例如,query_a&query_b(其中 query_aquery_b 是由此处的其他运算符组成的查询)将仅包括与这两个查询匹配的队列。
  • != - NOT IN 运算符。例如,feature_category!=issue_trackingissue_tracking 特征类别中排除所有队列。
  • = - IN 运算符。例如,resource_boundary=cpu 包括所有受 CPU 限制的队列。
  • , - the concatenate set 运算符。例如,feature_category=continuous_integration,pages 包括来自 continuous_integration 类别或 pages 类别的所有队列。此示例也可以使用 OR 运算符,但允许更简洁,并且优先级更低。

此语法的运算符优先级是固定的:不可能使 AND 具有比 OR 更高的优先级。

与上面的标准队列组语法一样,单个 * 作为整个队列组选择所有队列。

可用的作业类列表

有关现有 Sidekiq 作业类和队列的列表,请检查以下文件: