我们目前托管在一家托管服务提供商处,该提供商允许我们使用 KVM 设置多个虚拟机,其中每个虚拟机都在自己的物理机上运行(即:一个虚拟机管理程序,一个 VM,所有内存和 CPU 都分配给它)。最近我们遇到了一些需要诊断的棘手问题(原来是堆栈溢出 - 哈哈)。在此过程中,我们设置了 DataDog 来监控我们所有的服务器,它帮助我们缩小了原因范围并最终修复了它。但我们发现它非常有用,所以我们将其全部启用。在学习工具的过程中,我们不断发现我们网站的响应时间在白天很慢。启用 APM 跟踪后,我们能够将其缩小到 MySQL 集群的响应时间较慢。有时我们会看到 MySQL 连接需要 900 毫秒或更长时间才能创建,而其他时候,无效的简单查询(如设置连接排序规则或时区)需要 600 毫秒或更长时间。查询通常在不到 800 微秒内运行。
为了诊断问题,我们在集群中设置了多个端点的 ping,并且有两个 ping 经常运行缓慢(有时需要 4-5 秒!),它们只是返回一个字符串(PHP/apache 版本)或返回一些客户端 IP 信息(.net 和 IIS 版本)。我们设置这些是为了看看我们是否会在 Linux 或 IIS 上看到问题,而无需任何其他操作,结果确实如此。奇怪的是,在我们遇到这些中断时,机器上的 CPU 非常低,MySQL 集群也是如此。当查询运行缓慢时,CPU 非常低,因为这些盒子通常大部分时间都占用 5-6% 的 CPU。
为了尝试确定这是否是网络问题,我们在 Windows 上使用 Wireshark 设置了捕获,并在查询中进行了一些修饰时转储了数据包,以便我们可以轻松地在数据包转储中找到它们(基本上在查询中设置一个 MySQL 变量,它是当前 UTC 时间戳的编码版本,以微秒为单位)。使用它,我们能够将 DataDog APM 中的长 MySQL 跨度与 TCP 转储中的数据包正确匹配。查看 Windows/IIS 端,我们可以看到所有时间都花在等待结果从 MySQL 服务器通过线路返回。因此,DataDog 中报告的 MySQL 查询时间与数据转储中的时间完全匹配。
因此,正如您从两个屏幕截图中看到的那样,它们完全匹配。为了确定网络问题是否发生在 MySQL 端,我们在 Linux 机器上再次执行了相同的捕获转储,并看到了完全相同的事情。MySQL 收到了请求,并在数毫秒后发送了回复。因此,问题显然不是网络问题,而是导致 MySQL 本身变慢的原因。
现在真正奇怪的是,MySQL 本身并没有被阻塞,因为我运行这些查询的特定框仅从我们的一个 Windows 虚拟机(作为读取从属)运行读取查询。因此它没有太多负载,并且在查询期间 CPU 负载可能为 3%(它有 16 个 CPU 物理核心,带有双 8C Xeon CPU,并为 VM 分配了 32 个 vCore)。因此显然不是 MySQL 服务器上的负载问题,更重要的是,从 TCP 转储中可以清楚地看出,虽然我们感兴趣的查询需要很长时间才能执行,但来自其他连接的大量其他查询也随之而来并得到了处理,没有延迟。
现在更糟糕的是,我们在日志中还发现 MySQL 从服务器通常会落后很多,比主服务器落后 30-40 秒。我们曾见过它落后主服务器 110 秒的情况,这毫无道理,因为机器上的负载很低,而且都在主数据库(和 Web 服务器)所在的同一个本地专用网络上。有时从服务器中的延迟发生在速度变慢的同时,有时则不是。
所以现在我们已经确定这不是网络问题,我们开始认为这是 KVM 本身的某种线程死锁问题?特别是因为我们发现我们所有的虚拟机都出现了非常奇怪的减速现象,其中一些与 MySQL 无关(例如静态 PHP hello 文件)。由于我们无法控制 KVM 层,所以我们不知道它现在运行的版本,也不知道它是如何配置的。但是,我们越深入研究这个令人困惑的问题,就越能发现 KVM 是问题的根本原因,但我们不知道如何解决它。
为了说明问题,下面是一个 PHP 页面的 ping,该页面只回显“hello”,没有执行任何其他操作,以及来自三个 AWS 服务器的 ping 时间。显然,您有时会看到很大的峰值。
现在你可能会争辩,但这就是网络!当然,你可能会在白天遇到 AWS 与该服务器通信的故障。确实如此,但这是在同一时间段内从完全相同的 AWS 服务器到 Apache 中的静态页面的 ping,这次以毫秒为单位(比 PHP 甚至需要为一个简单的页面提供服务所需的时间要少):
因此,正如您所见,它也不是外部网络,因为静态文件 ping 从未变慢。完全没有问题。我们实际上设置了静态文件 ping 来针对该框上的第二个 Apache 实例运行,以确保它没有负载以获得基线。在 ping 结束时,您可以看到事情开始变得有点疯狂,ping 时间到处都是。这是因为我们刚刚在该实例中启用了 PHP,并从第二个 apache 实例提供了相同的 hello.php 文件,以查看它会产生什么不同。主要是因为第一个实例还为我们的 wordpress 博客和广告服务器提供真实的实时流量(流量很小,但不是零)。所以很明显,一旦我们在混合中添加使用更多 CPU 的东西,事情就会开始变得不稳定。
所以我的问题是,是否有其他人在使用 KVM 时遇到过这种问题?如果是,您如何解决?我们即将放弃这种 KVM 解决方案,并重新迁移到专用机器(十年前我们就放弃了),迁移到私有 VMware 云或考虑迁移到 Google 或 Azure(这两种方式都会花费我们更多的钱)。但如果它们可能存在类似的问题,我看不出迁移到其他云架构(如 Google 或 Azure 或私有 VMware 云)有什么意义?
有什么建议么?
答案1
每秒速率 = RPS
对 my.cnf [mysqld] 的建议
read_rnd_buffer_size=128K # from 256K to reduce handler_read_rnd_next RPS of 262756
innodb_lru_scan_depth=100 # from 1024 to conserve 90% of CPU cycles used for function
innodb_flush_neighbors=2 # from 0 to speed reduction of innodb_buffer_pool_pages_dirty of 148,465
sort_buffer_size=512K # from 256K to reduce sort_merge_passes RPhr of 1370
innodb_io_capacity=1900 # from 200 to use more of available SSD IOPS capacity
这只是前五条性能改进建议。还有很多建议需要考虑。请查看个人资料、网络个人资料以获取联系信息和可免费下载的实用程序脚本,以帮助进行性能调整。