Mastodon服务器扩容终极指南:性能优化与高可用性实战

引言

猛犸象(Mastodon)是一个开源的自托管社交网络。它具有联邦化的特性,这意味着多个猛犸象实例可以相互操作,使得不同服务器的用户能够相互通信,从而创建一个名为“联邦宇宙”(Fediverse)的网络。联邦宇宙是一个互连的服务器网络,它们使用ActivityPub协议进行通信。

随着猛犸象社区的指数级增长,服务器负载也随之增加。在过去的一年里,由于用户活动高峰,猛犸象服务器宕机事件屡次发生。为了防止猛犸象服务器在用户涌入时宕机,需要对其进行扩容。

Mastodon架构非透明图

可选地,对象存储可以显著提高静态媒体文件的性能并减轻Web服务的负载。虽然ElasticSearch不会直接提升性能,但它可以启用全文搜索;LibreTranslate则可以允许您的服务器自动翻译消息,使您的服务器体验更佳。

注意:

猛犸象服务仅通过数据存储(Redis和PostgreSQL)进行通信。这为分布式部署提供了极大的灵活性,但简单地将组件分布到多台机器上而没有适当的配置,并不会带来预期的性能提升。

在本教程中,您将学习猛犸象服务器的不同扩容技术:

  • 增加数据库资源和可用连接数
  • 将Sidekiq队列拆分为多个进程
  • 配置每个Sidekiq队列的线程和资源
  • 添加对象存储以减轻Web服务负载
  • 增加Web服务的线程和进程数

如果您计划扩容猛犸象服务器以满足活跃用户容量需求,我们建议您通读整篇文章并扩容每个组件。

另一方面,如果您只想扩容特定组件,请随意跳转到相应的组件章节。

经验法则是,运行猛犸象组件的每台机器的平均负载应保持在60-70%左右。有时,糟糕的服务配置可能导致性能低下以及平均负载过低。

以下每个章节都包含检测此类情况的症状。

注意:

本文包含的示例适用于运行在systemd服务上的猛犸象服务器(例如猛犸象vServer一键安装)。如果您有其他类型的猛犸象设置(Docker、K8s等),请考虑使用相应的配置方法。

提升数据库性能

PostgreSQL是猛犸象服务器的主要数据源。它包含所有用户凭据、嘟文、转发、用户关系等。因此,确保数据库的安全和备份是您的首要任务。

猛犸象会使用大量的数据库连接。连接耗尽的症状包括Sidekiq性能不佳、动态更新延迟数小时、整体运行缓慢,甚至整个服务器无法访问。

在本节中,您将计算服务器所需的连接数并相应地配置数据库。即使没有额外的资源,这也将使您的服务器免受连接耗尽的影响,连接耗尽会影响所有猛犸象服务的性能。

信息:

猛犸象服务器所需的连接数绝不能超过PostgreSQL的max_connections变量。此外,max_connections应尽可能低,以避免数据库争用。

要计算猛犸象服务器所需的总连接数,您需要计算每个组件所需的连接数:

  • 对于每个Web服务实例,所需连接数为MAX_THREADS乘以WEB_CONCURRENCY
  • 对于每个StreamingAPI实例,所需连接数为STREAMING_CLUSTER_NUM乘以DB_POOL
  • 对于每个Sidekiq实例,所需连接数等于DB_POOL

信息:

上述所有变量都可以在相应组件的环境中找到。在文章的后续部分,您将用到这里列出的每个变量。

将所有这些数字相加,并额外增加20个连接用于维护。这就是您max_connections的值。

信息:

正确配置数据库是您扩容猛犸象的首要任务,但要确定max_connections的数量,您必须首先了解如何扩容其他服务。

在您制定了如何扩容其他服务的计划(您将在后续章节中找到)后,您可以返回此处完成max_connections的计算。

既然您已经确定了max_connections的值,接下来就可以用它来配置您的数据库了。

一个很好的配置生成工具是 PGTune 服务。

打开 PGTune 页面后,您会看到需要填写的配置字段:

  • 数据库版本 (DB Version):在此处指定您的 Mastodon 服务器使用的 PostgreSQL 版本。您可以在运行 PostgreSQL 的机器上使用以下命令找到它:
pg_config --version
  • 操作系统类型 (OS Type):运行 PostgreSQL 机器的操作系统。
  • 数据库类型 (DB Type):PostgreSQL 将执行的工作负载类型。对于 Mastodon,请选择在线事务处理系统 (Online Transaction Processing System, 简称 OLTP),因为 Mastodon 会创建大量的连接。
  • 总内存 (Total Memory – RAM):PostgreSQL 将使用的内存量。尝试分配机器物理内存的一半,但如果同一台机器上还运行其他服务,请确保不要超过总内存。例如,在一台拥有 8 GB 内存且仅运行 PostgreSQL 的机器上,我们在 PGTune 中指定 4 GB。
  • CPU 数量 (Number of CPUs):PostgreSQL 将使用的 CPU 核心数量。由于 OLTP 是 CPU 密集型任务,我们强烈建议将此数字设置得尽可能高,达到您的机器支持的 CPU 线程数。
  • 连接数 (Number of Connections):此处填写 max_connections 的值。
  • 数据存储 (Data Storage):运行 PostgreSQL 机器上的数据存储设备类型。

例如,在一台 8 GB 内存、8 线程和 420 个 max_connections 的机器上,配置如下所示:

PGTune 示例

点击“生成 (Generate)”后,您将收到应添加到 postgresql.conf 文件中的配置参数。

在运行 PostgreSQL 的机器上打开 postgresql.conf

sudo nano /etc/postgresql/您的 PostgreSQL 主版本/main/postgresql.conf

例如,如果您运行的是 PostgreSQL 15.x 版本,则此文件的位置将是 /etc/postgresql/15/main/postgresql.conf

接下来,对于 PGTune 生成的每个参数,您将在 postgresql.conf 中搜索相同的参数并更改其值。在 nano 中使用 Ctrl+W 进行搜索,在 vi/vim 中使用 Esc+/。如果 postgresql.conf 中不存在某个参数,您可以在文件中的任何位置创建它。

在 postgresql.conf 中搜索参数的示例

最后,重启 PostgreSQL 服务以应用更改:

sudo service postgresql restart

现在您已经了解了如何为 Mastodon 配置 PostgreSQL 以获得更好的性能,以及如何应用新配置。在下一节中,您将找到计算 max_connections 所需的所有变量的确切值。

优化 Sidekiq 队列

Sidekiq:Mastodon的后台任务调度器

Sidekiq是Ruby语言的作业调度器和工作器,负责执行各种后台任务,例如在服务器之间传播帖子、生成链接预览、处理点赞等。

Sidekiq使用Redis作为作业队列管理器,并使用PostgreSQL保存作业结果。如果连接了多个服务器(用户关注了来自其他服务器的人),将产生大量作业来在服务器之间传播必要的数据。

Sidekiq瓶颈的症状包括:动态更新延迟长、Sidekiq队列堵塞以及数据库持续高负载。

在本节中,您将估算服务器所需的Sidekiq队列大小以及运行它们所需的物理机器数量。

Mastodon为Sidekiq设置了多个队列。其中一些队列资源密集,会完全占用CPU,而另一些则几乎不产生任何负载。下表包含Mastodon所需的所有队列的描述及其资源优先级。高优先级队列将比低优先级队列占用更多CPU:

队列 优先级 作用
default 最高 处理所有影响本地用户的任务。
ingress 处理传入的远程活动。优先级低于默认队列,因此在服务器负载高时,本地用户仍能看到他们的帖子。请注意,ingress队列是CPU密集型队列。
push 将数据负载传递给其他服务器。
pull 处理导入、备份、解析话题、删除用户和转发回复等任务。
mailers 发送电子邮件。
scheduler 最低 管理cron作业,例如刷新热门话题和清理日志。

警告:

scheduler队列绝不能扩展到多个进程。您的Mastodon服务器只能有一个运行scheduler的进程。

上表将帮助您正确分配机器,但如何配置队列本身呢?队列能够有效服务的活跃用户数量是有限的,并且此限制与特定队列的线程数相关。分配的线程越多,特定队列可以处理的活跃用户就越多。队列类型也会影响此限制,某些队列需要更少的线程来服务相同数量的用户,而其他队列则需要更多。这种多维关系如下图所示。

Mastodon Sidekiq扩展估算

根据您的服务器社区,push或pull队列可能具有不同的优先级。如果您的社区与其他联邦高度互联,请优先考虑push队列。否则,如果您的服务器专注于某个特定领域,您可以预期会有大量本地活动,并优先考虑pull队列。

注意:

不同的服务器具有不同的使用模式和负载分布。尝试通过分析您的服务器用户提升或点赞其他服务器用户的可能性来预测您服务器的使用模式。

例如,如果您的服务器涵盖特定的科学主题,您的服务器用户将主要相互交流。另一方面,如果您的服务器是个人政治博客,您的服务器用户可能更有可能提升其他政治人物。作为Mastodon管理员,您需要监控自己服务器的负载并相应地扩展组件。

Sidekiq参数与资源关系

警告:

单个Sidekiq服务不应使用超过50个线程。要服务60个线程,请运行2个服务,每个服务30个线程。

例如,我们估算有15000名活跃用户,他们主要使用本地联邦。

根据上图,我们需要:

  • 默认队列 (default):总共约70个线程,2个服务,每个35个线程。
  • 入口队列 (ingress):总共约50个线程,2个服务,每个25个线程。
  • 拉取队列 (pull):总共约40个线程,1个服务,包含所有40个线程。
  • 推送队列 (push):总共约30个线程,1个服务,包含所有35个线程。
  • 邮件队列 (mailer):总共约20个线程,1个服务,包含所有20个线程。
  • 调度队列 (scheduler):总共5个线程,1个服务,包含所有5个线程。

请记住,我们的用户不经常使用外部联邦,因此我们优先考虑了拉取队列而不是推送队列。

由于调度队列是优先级最低的队列,我们可以将其与默认队列一起运行,这完全不会影响默认队列。它们总共需要70 + 5 = 75个线程,大约对应8GB内存。由于这只是一个高负载队列,我们可以使用一台单核4核8GB的机器。

入口队列和邮件队列分别是高优先级和低优先级队列,这意味着与单个默认队列相比,它们需要的CPU资源更少,但我们仍将使用一台4核机器。它们所需的线程总数为25 + 20 = 45个,大约对应6GB内存。

拉取队列和推送队列都属于中等优先级,这使得它们比入口队列和邮件队列更消耗CPU,因此我们再次使用4核机器。线程数量为40 + 30 = 70个,对应8GB内存。

总而言之,如果我们计划服务15000名活跃用户,对于Sidekiq配置,我们总共需要3台机器:

  • 一台4核/8GB的机器,用于服务默认队列的2个服务(每个35个线程)和调度队列的1个服务(5个线程)。
  • 一台4核/8GB的机器,用于服务入口队列的1个服务(50个线程)和邮件队列的1个服务(20个线程)。
  • 一台4核/6GB的机器,用于服务拉取队列的1个服务(40个线程)和推送队列的1个服务(30个线程)。

注意:确定所需核心数量的最佳方法是观察运行Sidekiq的机器的平均负载。如果平均负载超过80%,则需要更多的CPU核心。如果核心数量已经足够高(例如超过8个核心),您可以尝试创建另一台具有相同配置的机器,无需任何负载均衡,它将分散负载并为您提供另一个扩展维度。请记住不要多次运行调度队列。

扩展Sidekiq

为了充分利用硬件资源,Sidekiq需要配置适当数量的线程,并在进程级别进行扩展。在本节中,您将了解如何精确设置Sidekiq队列的线程数量,以及如何使用服务模板在同一台机器上运行多个队列。

注意:以下示例可以内联到systemd服务的ExecStart或Docker的command字段中。如果您正在使用Docker,请记住在修改Docker文件后重建您的容器。

增加单个Sidekiq进程使用的线程数量

Mastodon服务器扩容全攻略:Sidekiq服务配置优化(5/12)

服务是Systemd可以管理、记录、自动重启等的一种资源。将可执行文件封装在服务中是部署应用程序最简单的方法之一。Systemd服务是运行Sidekiq队列最常见的方式。

Sidekiq服务的位置取决于您的Mastodon安装类型。例如,如果您使用的是Mastodon vServer 1-Click,您可以在以下位置找到Sidekiq服务文件:

  1. cat /etc/systemd/system/mastodon-sidekiq.service

让我们快速查看服务文件的顶部:

[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=25"
Environment="MALLOC_ARENA_MAX=2"
Environment="LD_PRELOAD=libjemalloc.so"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25
...

[Install]
WantedBy=multi-user.target

我们的注意力应放在两个特定字段上:ExecStartEnvironment

  • ExecStart 定义了服务启动或重启时运行的起点。
  • Environment 定义了传递给 ExecStart 的环境变量。

要扩展单个Sidekiq进程,您应该增加Sidekiq将使用的线程数。此数字由ExecStart字段中的-c参数控制。请务必保持DB_POOL环境变量与-c参数同步。

例如,我们将线程数增加到45。您将更改-c参数和DB_POOL的值:

[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=40"
Environment="MALLOC_ARENA_MAX=2"
Environment="LD_PRELOAD=libjemalloc.so"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 40
...

[Install]
WantedBy=multi-user.target

重要提示:DB_POOL环境变量的值应始终与-c参数的值相同(例如,在上述示例中为40)。如果DB_POOL较小,将导致Sidekiq性能问题;如果DB_POOL较高,则会增加数据库的负载。

对服务文件进行任何更改后,请务必重新加载单元文件并重启Sidekiq服务:

  1. sudo systemctl daemon-reload
  2. sudo systemctl restart mastodon-sidekiq.service

通过应用本节中的更改,您增加了Sidekiq使用的线程数量,使其能够服务更多用户。

为单个Sidekiq实例指定特定队列

6. Sidekiq服务文件分析与队列优化

我们首先来分析默认的Sidekiq服务文件。如果您使用的是Mastodon vServer 1-Click安装,您可以在以下位置找到Sidekiq服务文件:

cat /etc/systemd/system/mastodon-sidekiq.service

如您所知,Mastodon将Sidekiq数据分为多个队列。默认情况下,服务文件中没有明确指定任何队列。

[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=25"
Environment="MALLOC_ARENA_MAX=2"
Environment="LD_PRELOAD=libjemalloc.so"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25
...

[Install]
WantedBy=multi-user.target

没有明确指定队列意味着Sidekiq将以一些默认优先级处理所有队列。鉴于即使是单个Sidekiq队列也占用大量资源,在单个Sidekiq实例上运行所有队列远非理想方案。

您希望实现的目标是将Sidekiq队列拆分为多个Sidekiq实例。这将允许您为每个队列指定精确的线程数,并且还允许您在多台机器上运行不同的队列。

幸运的是,覆盖Sidekiq的默认行为只需要在ExecStart字段中添加一个-q参数。

例如,让我们让Sidekiq只处理ingress队列:

[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=25"
Environment="MALLOC_ARENA_MAX=2"
Environment="LD_PRELOAD=libjemalloc.so"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 25 -q ingress
...

[Install]
WantedBy=multi-user.target

通过指定-q ingress,您告诉Sidekiq只处理ingress队列,而不处理其他任何队列。

警告:上述示例将导致除ingress队列之外的所有队列都无法处理,这意味着Mastodon将无法正常运行。请确保至少覆盖所有队列一次。下一节将提供关于如何在单台机器上运行多个Sidekiq服务实例的指导。

让Sidekiq服务只处理单个队列有几个优点:它更容易处理特定队列的日志,它提供了按队列的管理和线程控制,并允许通过在不同机器上运行不同队列来实现分布式设置。总的来说,这被认为是扩展Sidekiq队列的主要实践。

然而,将所有硬件资源都分配给单个队列并不总是高效的,因此在下一节中,您将学习如何在单台机器上单独运行多个队列。

使用模板在单台机器上运行多个Sidekiq实例

仅运行单个 Sidekiq 实例效率低下。为了进一步扩展 Sidekiq,您可以同时运行多个 Sidekiq 实例。

由于 systemd 服务是运行 Sidekiq 最常见的方式,因此您将学习如何创建服务模板,以简化在单台机器上运行多个 Sidekiq 实例。

服务模板允许我们从单个服务文件创建多个服务。

首先,让我们复制现有的 Sidekiq 服务文件:

  1. cp /etc/systemd/system/mastodon-sidekiq.service /etc/systemd/system/mastodon-sidekiq-template.service

 

这将创建一个名为 mastodon-sidekiq-template.service 的新文件,它是现有 Sidekiq 服务的副本。

您将修改此副本以将其转换为模板。模板由模板说明符定义,在本文中,您将使用两个特定的说明符:%i 和 %j。

  • %i 是实例名称。对于实例化服务,这是第一个“@”字符和类型后缀之间的字符串。
  • %j 是前缀的最后一个组成部分。这是最后一个“-”和前缀名称末尾之间的字符串。

听起来很困惑?让我们进入实践部分以更好地理解它。

首先,打开您的新服务文件进行编辑:

  1. sudo nano /etc/systemd/system/mastodon-sidekiq-template.service

 

现在,更改服务文件中的一些值以使用模板说明符:

  • 描述字段应包含 %j 说明符,以便于服务跟踪和维护。
  • DB_POOL 环境变量应等于 %i 说明符。
  • ExecStart 中的 -c 参数应等于 %i。
  • ExecStart 中的 -q 参数应等于 %j。
/etc/systemd/system/mastodon-sidekiq-template.service

[Unit]
Description=mastodon-sidekiq-%j-queue
After=network.target

[Service]
...
Environment="DB_POOL=%i"
Environment="MALLOC_ARENA_MAX=2"
Environment="LD_PRELOAD=libjemalloc.so"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c %i -q %j
...
[Install]
WantedBy=multi-user.target

正如您可能猜到的,%i 说明符将包含 Sidekiq 的线程数,而 %j 说明符将包含 Sidekiq 队列的名称。

服务文件中说明符的替换

创建和启用Sidekiq服务

我们将使用此模板为所需的Sidekiq配置创建服务文件。

首先,复制模板以指定您希望在此机器上运行的队列。例如,要运行defaultscheduler队列:

  1. cp /etc/systemd/system/mastodon-sidekiq-template.service /etc/systemd/system/mastodon-sidekiq-default@.service
  2. cp /etc/systemd/system/mastodon-sidekiq-template.service /etc/systemd/system/mastodon-sidekiq-scheduler@.service

对于队列的名称,您可以使用defaultingresspushpullmailersscheduler中的一个。

您可能已经注意到,您没有在@符号后指定任何内容。这是因为您将在启用服务本身时指定此参数。

现在,要启用新服务,让我们为default队列使用20个线程,为scheduler队列使用5个线程:

  1. sudo systemctl enable mastodon-sidekiq-default@20.service
  2. sudo systemctl enable mastodon-sidekiq-scheduler@5.service

最后,在您启用新服务后,您可以使用以下命令一次性运行所有服务:

  1. sudo systemctl start mastodon-sidekiq*

至此,您已成功创建了一个模板服务文件,并使用它来运行具有不同队列和线程的多个Sidekiq服务。

更改正在运行的模板服务的配置

如果您希望将模板化的default服务的线程数从20更改为40,您应该首先禁用现有服务:

  1. sudo systemctl stop mastodon-sidekiq-default.service
  2. sudo systemctl disable mastodon-sidekiq-default@20.service

请注意,您只为disable命令指定了线程数,而不是stop命令。

禁用旧的push服务后,您可以创建一个新服务,使用40个线程而不是20个:

  1. sudo systemctl enable mastodon-sidekiq-default@40.service
  2. sudo systemctl start mastodon-sidekiq-default.service

至此,您已成功更改了现有systemd服务的线程数。

运行同一Sidekiq队列的多个服务

如您所知,单个Sidekiq实例不应超过50个线程。运行60个线程的某个队列需要将其拆分为2个服务,每个服务30个线程。

为此,您需要多次复制模板,使用相同的队列,但添加一个索引。索引只是一个数字,用于区分每个服务文件。

多次复制初始模板,但每次重复相同的队列时增加索引。例如,要创建两个default队列的服务文件:

  1. cp /etc/systemd/system/mastodon-sidekiq-template.service /etc/systemd/system/mastodon-sidekiq-1-default@.service
  2. cp /etc/systemd/system/mastodon-sidekiq-template.service /etc/systemd/system/mastodon-sidekiq-2-default@.service

警告:

请勿将索引附加到队列名称之后,例如:/etc/systemd/system/mastodon-sidekiq-default-2@service。这将使模板将“2”视为队列名称,从而不可避免地导致失败。请仅在队列名称之前插入索引。

现在,让我们为默认队列的第一个实例启用40个线程,为第二个实例启用60个线程:

  1. sudo systemctl enable mastodon-sidekiq-1-default@40.service
  2. sudo systemctl enable mastodon-sidekiq-2-default@60.service

 

最后,在您启用服务后,可以使用以下命令运行所有服务:

  1. sudo systemctl start mastodon-sidekiq*

 

至此,您已成功创建了同一队列的多个实例,从而可以正确地分割大量线程。

您学习了设置Sidekiq服务的多种方法。在某些情况下,单个默认服务就足够了;另一些情况则需要在单台机器上运行多个服务;还有些情况甚至需要在多台机器上运行同一队列的多个服务。这完全取决于您希望支持的活跃用户数量。

添加对象存储

对象存储,或简称存储桶,允许存储用户上传到您服务器的媒体文件。这包括照片、视频、GIF、音频文件等。

从文件系统迁移到对象存储有助于提高存储速度和容量,但更重要的是,它减少了Mastodon服务的负载。此外,大多数云提供的对象存储还提供CDN,这将更快地向用户交付媒体文件。

注意:Mastodon使用S3兼容接口,这意味着您的对象存储提供商必须支持S3接口并提供S3存储凭证的映射。

如果您在Mastodon初始化期间不小心遗漏了对象存储配置,您可以将必要的变量直接添加到运行Web服务的机器配置中,因为对象存储仅由Web服务使用。

警告

警告:更改对象存储将导致您服务器上所有现有媒体文件丢失。

在运行Web服务的机器上,使用您喜欢的文本编辑器打开.env.production文件。如果您使用的是Mastodon vServer一键部署,.env.production位于/home/mastodon/live

  1. sudo nano .env.production

 

将以下行添加到您的.env.production文件中的任意位置,并将高亮显示的文本替换为您自己的信息。如果这些变量已经存在,则表示对象存储已在设置期间配置,如果值不正确,您仍然可以更改它们:

.env.production

...
S3_ENABLED=true
S3_PROTOCOL=https
S3_BUCKET=您的存储桶名称
S3_REGION=您的存储桶区域
S3_HOSTNAME=您的存储桶主机名
S3_ENDPOINT=您的存储桶端点
AWS_ACCESS_KEY_ID=您的存储桶密钥ID
AWS_SECRET_ACCESS_KEY=您的存储桶密钥
...

上述变量代表S3接口连接参数。请确保使用您的对象存储提供商提供的正确S3连接参数映射。

然后保存并退出编辑器。

保存更改后,请务必重启Web服务:

  1. sudo systemctl restart mastodon-web.service

 

现在您知道如何在自动设置失败、人为错误或手动安装的情况下,为Mastodon手动配置对象存储。对象存储将有助于减轻Mastodon Web服务的负载,并为服务器上的媒体文件提供更好的上传/下载速度。

扩展Web服务

Web服务扩容:提升用户并发处理能力

Web服务是基于Ruby-on-Rails的HTTPS服务器,负责提供Mastodon的用户界面并处理用户请求。Web服务的负载与活跃用户数量直接相关。每个线程一次只能处理一个请求。如果所有线程都处于忙碌状态,后续请求就必须等待。如果请求等待时间过长,就会因超时错误而被取消。Web服务瓶颈通常表现为请求处理时间过长:页面打开缓慢、发布内容有明显延迟,或者日志中出现超时错误。

警告:

Web服务强制使用HTTPS,这意味着在托管Web服务的多个机器之间的负载均衡器上无法使用SSL终止。为了让Web服务处理更多用户,您需要增加服务使用的总线程数。这可以通过增加环境变量WEB_CONCURRENCY(工作进程数)和/或MAX_THREADS(每个工作进程的线程数)来实现。每个工作进程拥有MAX_THREADS数量的线程,因此总线程数等于WEB_CONCURRENCY乘以MAX_THREADS

增加MAX_THREADS倾向于消耗更多CPU,而增加WEB_CONCURRENCY倾向于消耗更多RAM。根据Mastodon 4.0.2版本的平均估算,单个工作进程需要2-3 GB的RAM。在上述示例中,如果WEB_CONCURRENCY = 3,则估计所需的RAM为9 GB。

对于MAX_THREADS,我们建议从15这样的通用值开始,然后逐步增加,直到CPU平均使用率达到70%。这意味着您需要观察运行Web服务的机器,以判断是否可以承载更多线程。

注意:

以下展示的是Systemd Web服务配置的代码片段。如果您使用其他技术(如Docker、Kubernetes等)运行Web服务,请根据您的技术环境规范调整WEB_CONCURRENCYMAX_THREADS变量。

首先,让我们打开Web服务文件:

  1. sudo nano /etc/systemd/system/mastodon-web.service

您将看到一个Web服务Systemd文件,内容如下:

/etc/systemd/system/mastodon-web.service

[Unit]
Description=mastodon-web
After=network.target

[Service]
...
Environment="LD_PRELOAD=libjemalloc.so"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
ExecReload=/bin/kill -SIGUSR1 $MAINPID
...
[Install]
WantedBy=multi-user.target

现在,在ExecStart字段上方添加两个额外的字段,包含WEB_CONCURRENCYMAX_THREADS变量:

/etc/systemd/system/mastodon-web.service

[Unit]
Description=mastodon-web
After=network.target

[Service]
...
Environment="LD_PRELOAD=libjemalloc.so"
Environment="WEB_CONCURRENCY=您的并发值"
Environment="MAX_THREADS=您的线程值"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
ExecReload=/bin/kill -SIGUSR1 $MAINPID
...
[Install]
WantedBy=multi-user.target

这些新字段将用您自己的值覆盖WEB_CONCURRENCYMAX_THREADS的默认值。

保存并退出编辑器。

保存更改后,请务必重新加载单元文件并重启服务:

  1. sudo systemctl daemon-reload
  2. sudo systemctl restart mastodon-web.service

注意:

自2017年以来,Web服务的性能几乎翻了一番,我们强烈建议每个人监控硬件使用情况,以确定是否应分配更多或更少的资源。

至此,您已经增加了Web服务配置的默认值。这使得您的Mastodon前端能够支持更多的活跃用户。请记住,始终保持一定的性能余量,以确保您的Mastodon服务器在大量用户涌入时不会出现瓶颈。

增加StreamingAPI吞吐量

Mastodon服务器扩容全攻略:StreamingAPI优化指南

StreamingAPI是一个基于Node.js的服务器,提供实时更新的API接口。它允许用户直接从服务器接收事件流。StreamingAPI能够同时服务的用户数量是有限的,这个限制由环境变量STREAMING_CLUSTER_NUM决定。

StreamingAPI的性能瓶颈可以通过查看服务日志来识别。如果日志中出现类似node[1201554]: ERR! error: sorry, too many clients already的错误信息,这意味着使用StreamingAPI的用户数量超出了其处理能力,新用户会被自动断开连接。

扩容StreamingAPI

扩容StreamingAPI的方法非常直接。

增加STREAMING_CLUSTER_NUM环境变量的值将允许StreamingAPI服务更多的用户。

如果您在日志中看到大量error: sorry, too many clients already消息,建议将STREAMING_CLUSTER_NUM的值增加1.5到2倍。例如,如果当前STREAMING_CLUSTER_NUM的配置是2,可以将其更新为4。

在运行StreamingAPI的机器上,打开StreamingAPI服务文件:

  1. sudo nano /etc/systemd/system/mastodon-streaming.service

编辑STREAMING_CLUSTER_NUM变量的值:

[Unit]
Description=mastodon-streaming
After=network.target

[Service]
...
Environment="STREAMING_CLUSTER_NUM=您的新值"
ExecStart=/usr/bin/node ./streaming
...

保存文件后,请务必重新加载单元文件并重启服务:

  1. sudo systemctl daemon-reload
  2. sudo systemctl restart mastodon-streaming.service

优化数据库连接池(可选)

此外,默认情况下StreamingAPI没有设置DB_POOL变量。如果未明确设置此变量,StreamingAPI将使用10个数据库连接。通常不建议在不增加STREAMING_CLUSTER_NUM变量的情况下单独增加DB_POOL变量,但如果您确实需要这样做,可以在StreamingAPI服务文件中创建一个新的环境变量。

在运行StreamingAPI的机器上,打开StreamingAPI服务文件:

  1. sudo nano /etc/systemd/system/mastodon-streaming.service

添加新的环境变量DB_POOL

[Unit]
Description=mastodon-streaming
After=network.target

[Service]
...
Environment="DB_POOL=您的值"
Environment="STREAMING_CLUSTER_NUM=您的值"
ExecStart=/usr/bin/node ./streaming
...

保存文件后,请务必重新加载单元文件并重启服务:

  1. sudo systemctl daemon-reload
  2. sudo systemctl restart mastodon-streaming.service

这将覆盖DB_POOL的默认值,使您更清楚地了解StreamingAPI实例所需的数据库连接数量。

注意:如果您没有明确指定DB_POOL的值,在计算max_connections变量时,请使用10作为DB_POOL的值。

至此,您已经更新了StreamingAPI的配置,以实现更好的吞吐量。这将帮助您的StreamingAPI服务更多的并发用户而不会出现故障。您可以选择明确指定DB_POOL环境变量以优化数据库配置,或者保持不变并使用10作为StreamingAPI的DB_POOL值。

总结

在本教程中,您已经学习了如何识别并解决PostgreSQL、Sidekiq、Web服务和StreamingAPI中的瓶颈问题。现在,您可以设置一台新服务器或扩展您现有的服务器。

扩展方法总能得到改进和完善,例如,复杂的Sidekiq配置可以进一步模板化。

官方的Mastodon扩展指南包含了一些关于如何扩展和优化服务器的额外观点。

另一种提升服务器用户体验的绝佳方式是启用基于Elasticsearch的全文搜索。这将允许用户搜索他们的嘟文(statuses)、提及(mentions)、收藏(favourites)和书签(bookmarks)中的内容。

通过启用LibreTranslate,Mastodon还可以将嘟文和其他消息翻译成用户的语言。

bannerAds