网络数据包损坏是否只会影响与数据库通信的众多服务器进程中的一个?

网络数据包损坏是否只会影响与数据库通信的众多服务器进程中的一个?

语境

ActiveRecord::StatementInvalid昨天的 4 个小时内,我们发现 MySQL 服务器偶尔出现错误。此后再没有出现过此类错误。

奇怪的是,SQL 语句似乎被破坏了:一个或多个随机字符被向前或向后移动了 2 个字节。例如,"Unknown table 'erades'"针对表的查询grades。这不仅限于表名:这些查询中的列名、SQL 关键字和值都受到了影响。

错误

错误消息示例:

.-> ,:表'[数据库名称].id'不存在:SELECT [..] FROM [..] INNER JOIN [..] ON [..] = `[表名称]`.`id` ..
`-> b:表名'topic_setsb ON'不正确:SELECT [..] FROM [..] INNER JOIN `topic_sets` ON ...
s-> q:'字段列表'中未知列'aqsigned_[redacted]'
U-> W:您的 SQL 语法有错误;[..] 靠近'NWLL GROUP BY ...
8-> ::您的 SQL 语法有错误;[..] 靠近':887)',第 1 行:SELECT [..] WHERE [..] IN (48846, 48901, 48887)

由于 MySQL 可能只报告语句中的第一个错误,因此我无法确定每个语句的确切损坏数量。消息中包含的完整 SQL 查询似乎是客户端持有的声明副本,并且该部分消息没有任何损坏。

在某些情况下,我无法从错误消息中判断哪个字符可能被损坏,例如“第 1 行 '' 附近使用的语法正确”,并且并非所有损坏都与字节移位有关。这可能是来自不可打印的字符,也可能是插入/删除了字符。

有一个有些语句被破坏的方式有固定的模式,但似乎没有明确的规则。例如,会出现 10-20 次相同的语句以相同的方式被破坏的模式,但这些模式中破坏的位置会有所不同。

我从 RDS 控制台获取的错误日志为空。该时间段内未报告任何 AWS 服务降级情况。

我们的异常跟踪工具总共报告了 143 个错误。这些错误来自 4 个 Passenger 工作程序,其中 2 个在同一个 EC2 实例上,另两个在另一个 EC2 实例上。这些工作程序中的错误计数分布:1、41、42、50。这约占发生此情况的 4 小时内处理的总请求数的 0.001%。

对于每个工人来说,错误都是零星发生的:每个工人报告这些错误大约持续 5 分钟,每隔几秒到 2-3 分钟就会发生 1-2 个错误 - 除了只有一个错误的错误之外。

一些查询针对主数据库,一些查询针对副本数据库。

环境和其他事实:

  • AWS RDS MySQL 5.6.39
  • AWS EC2 实例 c4.4xlarge。当时有 15 多个实例为同一网站提供服务。
  • Apache 2,mpm 模块:事件
  • Passenger 5.3.3,并发模型:进程。通常,单个 EC2 实例中有 30 多个工作进程。
  • Rails 4.2.10,数据库池大小:2。
  • MySQL 客户端库:mysql2 0.4.10
  • Ruby 2.3.7

时间线

instance A launch           2018-11-13 12:00 UTC
instance A process P errors 2018-11-13 13:40-13:43 UTC
instance A process Q errors 2018-11-13 14:22-14:26 UTC
instance A shutdown         2018-11-13 20:00 UTC
instance B launch           2018-11-13 15:00 UTC
instance B process R errors 2018-11-13 15:39-15:40 UTC
instance B process S errors 2018-11-13 17:39-17:43 UTC
instance B shutdown         2018-11-13 23:00 UTC

可能的原因

一位熟人承认,他们在同一天在 AWS 中看到了同样的错误,并提到这次谈话 [1]关于网络级数据损坏:讨论了网络交换机在重新路由时如何重新计算数据包的以太网 CRC,以及重新路由过程中的损坏可能导致“有效”的 CRC,以及 TCP 校验和如何也存在漏洞。(文字注释来自 kevinchen.co)。

[1] !!Con 2017:数据中心的腐败!TCP 无法保证您的数据安全!作者:Evan Jones

他们的建议是所有通信都使用 TLS,因为 TLS 层将无法解密损坏的字节。

我还发现这一页描述了 CRC 和校验和的限制。此错误中有一个类似的错误serverfault 问题而这其中的原因也和网络有关。

我越来越相信这些错误是由网络层面的故障引起的。

问题

以太网/TCP 理论是否同意我所描述的错误行为?我不确定一次只有一个进程可能看到此错误,但我认为如果交换机决定根据源 - 目标端口对以不同方式处理数据包,则可能会发生这种情况,因为每个连接将使用不同的端口。

如果这实际上是一个 XY 问题,我很乐意重新构建这个问题。

注意:我已发布请求至AWS 论坛确认/调查这是来自 AWS 基础设施的问题。在这里,在 serverfault 中,我感兴趣的是了解该假设的合理性以及它如何表现出我看到的行为(或没有表现出来)。

答案1

这在合理范围内,很难得出任何结论。您列出的位翻转在 8 位对齐时是一致的。尽管看到整个消息会很有趣,因为(可能)网络帧中还必须有其他翻转才能挫败 CRC/校验和。

就“同一台机器上只有部分工作程序报告错误”而言,可能是 - 工作程序之间的负载不相等,这只是每个进程生成的流量字节数的影响,或者如果工作程序确实保持持久连接,那么您只是在路径选择中输掉了机会游戏。即,如果沿途有多个活动链接,则报告错误的工作程序恰好具有散列到坏链接的连接。(请参阅散列(srcip、srcport、dstip、dstport)进行链接选择并不罕见,无论是 L2(lacp/bond)还是 L3(ECMP))。对于较短的连接也有可能,尽管现在这种可能性越来越小。AWS 也完全有可能为其网络提供更深奥的路径选择,这可以解释这一点。

我通常会有些棘手并寻找其他确凿证据,例如来自操作系统、网卡和交换机/路由器的校验和错误计数器,尽管我倾向于说您对某些实例的分割没有问题,而其他实例确实存在问题作为很好的确凿证据。

翻页样式:

00101110 .
00101100 ,
00000010 xor

01100000 `
01100010 b
00000010 xor

01110011 s
01110001 q
00000010

01010101 U
01010111 W
00000010 xor

00111000 8
00111010 :
00000010 xor

相关内容