从gitlab.com找到解决大问题的解决方案中学到的6课。 第二部分

敬请您注意gitlab.com团队与时间专制斗争的材料翻译的第二部分。



→顺便说一下,这里是第一部分

请求处理速度限制


此时,我们对仅提高MaxStartups参数的值不感兴趣。 尽管此参数增加50%被证明是很好的,但在没有充分理由的情况下将其进一步增加似乎可以解决该问题。 当然,我们还有其他事情可以做。

搜索使我进入了HAProxy级别,该级别位于SSH服务器的前面。 HAProxy有一个不错的rate-limit sessions选项,它会影响系统中接受传入请求的部分。 如果配置了此选项,则它用于限制前端每秒发送到后端的新TCP请求的数量,同时将其他传入连接保留到TCP套接字。 如果传入请求的速度超过限制(每毫秒更改一次),则仅延迟新连接。 TCP客户端(在本例中为SSH)在建立TCP连接之前只会看到延迟。 我认为这是一个非常美丽的举动。 在太长的时间内,直到收到请求的速度超过限制为止,系统才能正常工作。

下一个问题是rate-limit sessions选项的值的选择,我们应该使用它。 由于我们有27个SSH后端和18个HAProxy前端(16个主代理和2个alt-ssh),并且前端在请求处理速度上彼此不协调,因此很难找到该问题的答案。 。 此外,我们还必须考虑到新SSH会话的身份验证步骤需要花费多长时间。 假设MaxStartups的第一个值为150。这意味着,如果身份验证阶段花费两秒钟,那么我们每秒只能传输每个后端75个新会话。 在这里,您可以找到有关计算rate-limit sessions的值的详细信息,在此不再赘述。 我仅注意到,为了计算该值,必须考虑四个参数。 第一个和第二个是这两种类型的服务器的数量。 第三是MaxStartups的值。 第四个是T验证SSH会话花费多长时间。 T的值非常重要,但只能近似推导。 我们就是这样做的,结果留在了2秒。 结果,我们得到了前端的rate-limit值,总计为112.5。 我们将其舍入为110。

现在,新设置生效。 也许您认为此后一切都愉快地结束了? 一定是错误数量冲到了零,周围的每个人都非常高兴吗? 好吧,实际上它远非如此好。 此更改不会导致错误率的任何可见变化。 坦白说,我很沮丧。 我们错过了一些重要问题,或者误解了问题的实质。

结果,我们返回到日志(最后是HAProxy信息),并能够确保按预期方式对查询进行操作,至少可以确保查询处理速度的限制。 以前,相应的指标较高,这使我们可以得出结论,我们成功限制了传入请求发送进行处理的速度。 但是很明显,请求到达的速度仍然很高。 尽管也很明显,当它可能对系统产生显着影响时,它甚至还没有达到这些水平。 当我们分析选择后端的过程(根据HAProxy日志)时,我们注意到那里很奇怪。 在一小时开始时,后端连接在SSH服务器之间分布不均。 在选择进行分析的时间间隔内,不同服务器上每秒的连接数从30变为121。这意味着我们的负载平衡无法很好地完成工作。 对配置的分析表明,我们使用了balance source选项,以便具有特定IP地址的客户端始终连接到同一后端。 在需要会话绑定的情况下,这可以被视为积极现象。 但是我们正在使用SSH,因此我们不需要这样做。 我们曾经配置过此选项,但是我们没有找到执行此操作的任何提示。 我们找不到继续使用它的值得理由。 结果,我们决定切换到leastconn 。 多亏了此选项,新的传入连接为后端提供了最少的当前连接数。 这影响了我们的SSH(Git)服务器对处理器资源的使用。 这是相应的时间表。


应用Minimumconn选项之前和之后服务器的CPU消耗

看到这一点之后,我们意识到使用leastconn是一个好主意。 图底部的两行是我们的Canary服务器,您可以忽略它们。 但是以前,不同服务器的CPU负载值的散布关联为2:1(从30%到60%)。 这清楚地表明,由于客户端与后端之间的连接,我们的某些后端比其他后端负载更多。 这让我感到惊讶。 可以预期,各种各样的客户端IP地址足以使我们的服务器更均匀地加载,这似乎是合理的。 但是,显然,为了扭曲服务器负载指标,几个大型客户端就足够了,它们的行为与某些平均选项有所不同。

课程编号4。 当您选择与默认设置不同的特定设置时,请对其进行注释或留下指向说明更改的材料的链接。 将来任何需要处理这些设置的人都将感谢您。

这种透明度是GitLab的核心价值之一

启用leastconn选项还有助于减少错误级别。 而这正是我们所追求的。 因此,我们决定保留此选项。 但是,他们继续进行实验,将请求处理速度限制的级别降低到100,这有助于进一步减少错误级别。 这表明T值的初始选择可能不正确。 但是,如果是这样,则该指标太小,导致太强的速度限制,甚至每秒100个请求也被认为是非常低的值,因此我们不准备进一步降低它。 不幸的是,由于某些内部原因,这两个更改只是一个实验。 我们不得不回到使用balance source选项,并将请求的处理速度限制为每秒100个请求。

鉴于查询处理速度设置为适合我们的较低级别,并且我们无法使用leastconn ,因此我们尝试增加MaxStartups参数。 起初我们将其增加到200,这产生了一些效果。 然后-最多250个。错误几乎完全消失,没有发生任何不好的情况。

第5课 较高的MaxStartups看起来令人生畏,但即使它们远远高于默认值,它们对性能的影响也很小。

也许这就像一个强大的杠杆,将来我们可以在必要时使用它。 如果我们谈论的数字在几千或几万的范围内,也许会遇到问题,但我们离这还很遥远。

这对我对T参数的估计,安装和验证SSH会话所花费的时间有什么说明? 如果使用计算连接处理速度限制指标的公式,知道200对于MaxStartups指标还不够,而250足够了,那么您会发现T的值可能在2.7到3.4秒之间。 结果,估计值2秒与真实值相差不远,但实际值当然要高于预期。 我们待会儿会再谈这个。

最后步骤


我们再次考虑了我们已经知道的内容,查看了日志,并经过一番思考后发现,可以通过以下标志来识别所有日志问题。 首先,这是一个等于SDt_state值。 其次,这是b_read (客户端读取的字节)的值,等于0。如上所述,我们每天处理大约26-28百万个SSH连接。 不幸的是,在灾难期间,这些连接中约有1.5%严重断开。 显然,问题的规模比我们一开始就想的要大得多。 此外,没有什么是我们早期无法检测到的(即使当我们意识到t_state="SD"指示日志中存在问题时),但是我们没有考虑如何执行此操作,尽管我们你应该考虑一下 可能正因为如此,我们在解决问题上花费了比我们本来可以花费的时间和精力更多的时间。

第6课 尽早测量实际错误级别。

如果我们最初知道问题的严重性,那么我们可以更加注意它。 虽然,如何看待它,仍然取决于使我们能够描述问题的特征知识。

如果我们谈论增加MaxStartups的值并调整处理请求的速度后出现的优点,那么我们可以说错误率降低到0.001%。 那就是-每天多达几千。 这种情况看起来要好得多,但是类似的错误级别仍然比我们希望达到的级别更高。 在找出一些问题之后,我们再次能够使用leastconn选项,并且错误完全消失了。 之后,我们可以松一口气。

未来的工作


显然,SSH身份验证阶段仍然需要很多时间。 可能长达3.4秒。 GitLab可以使用AuthorizedKeysCommand直接在数据库中搜索SSH密钥。 这对于有大量用户的快速操作非常重要。 否则,SSHD需要顺序读取一个很大的authorized_keys文件以找到用户的公共密钥。 此任务无法很好地扩展。 我们使用一定数量的Ruby代码实现了搜索,该代码执行对外部HTTP API的调用。 我们工程部门的负责人Stan Hugh也是有关GitLab的不竭知识的来源,他发现Unicorn的Git / SSH服务器实例在不断受到来自他们的请求的负载。 这可能会对认证请求所需的三秒钟做出重大贡献。 结果,我们意识到将来我们应该对此问题进行调查。 也许我们会在这些节点上增加Unicorn(或Puma)实例的数量,以便SSH服务器不必等待访问它们。 但是,这里存在一定的风险,因此我们需要谨慎并注意系统指标的收集和分析。 生产力方面的工作仍在继续,但是现在,在解决了主要问题之后,事情进展得越来越慢。 我们也许可以减小MaxStartups的值,但是由于它的高级别不会对它似乎正在创建的系统产生负面影响,因此这并不是特别必要。 如果OpenSSH可以随时告诉我们我们离MaxStartups的极限有多近,那么每个人的生活就会容易MaxStartups 。 如果我们能够始终保持了解就会更好。 这比得知连接断开时超出限制要好得多。

此外,当出现HAProxy日志条目时,我们需要某种通知系统,这表明断开连接的问题。 事实是,实际上这根本不应该发生。 如果再次发生这种情况,我们将需要进一步增加MaxStartups值,或者如果我们遇到资源不足的情况,则需要向系统添加更多的Git / SSH节点。

总结


复杂系统的各个部分以复杂模式交互。 并且在其中,为了解决各种问题,人们常常会发现一个“杠杆”远非如此。 处理此类系统时,了解其中存在的工具很有用。 事实是,他们都有自己的优缺点。 另外,应注意,基于假设和估计值进行某些设置可能会有风险。 现在,看看我们走过的路,我将尝试尽可能准确地测量完成请求认证所需的时间,这将导致我推导出的T的近似值更接近事实。

但是我们从所有这些中学到的主要教训是,当很多人根据一些不错的时间指标来计划任务时,对于像GitLab这样的集中式服务提供商来说,这会导致真正异常的扩展问题。

如果您是使用计划任务启动工具的人之一,那么您可能要考虑设置一种以新方式启动任务的时间。 例如,您可以使任务“入睡”一会儿,在启动后仅30秒即可开始真正工作。 例如,您可以在任务启动时间表中指定一小时内的随机时间(此处您可以在任务实际执行之前添加随机等待时间)。 这将帮助我们所有人与手表暴政作斗争。

亲爱的读者们! 您是否遇到过与该材料致力于其故事的问题类似的问题?

Source: https://habr.com/ru/post/zh-CN466553/


All Articles