C# .NET 6 - 当在 K8S pod 中运行时,读取一条(大)记录的简单 SQL 查询需要很长时间,在 IIS 中运行时则瞬间完成

Cri*_*rsi 12 c# sql-server entity-framework-core kubernetes .net-6.0

我在 SQL Server 中有一个简单的表:

CREATE TABLE [dbo].[MyTable]
(
    [Ticket] [uniqueidentifier] NOT NULL,
    [UserID] [int] NOT NULL,
    [Progress] [int] NOT NULL,
    [Created] [datetime2](7) NOT NULL,
    [KeepRes] [bit] NOT NULL,
    [Result] [nvarchar](max) NULL,
    [ResultFetched] [datetime2](7) NULL,
    [CorrelationID] [varchar](100) NULL,

    CONSTRAINT [PK_MyTable] 
        PRIMARY KEY CLUSTERED ([Ticket] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
)
Run Code Online (Sandbox Code Playgroud)

请注意,该表的行可能有一Result列非常大(300 MB 左右)。我使用简单的主键
从 .Net6/C# 中的应用程序查询此表。select

我使用实体框架核心:

public void QueryTable(Guid ticket)
{
    using (MyDBContext db = new MyDBContext)
    {
        var res = db.MyTable.Find(ticket);
        Console.Write("Res found:" + (res != null));
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码是我的应用程序的一部分,部署在两个环境中:

  1. 在 Windows Server 2014 下运行的 IIS
  2. 一个 K8S Pod

两个环境都指向同一个数据库实例,即 SQL Server 2014。

现在有趣的部分:

当要检索的记录有Result大于 500KB 的列时,该语句db.MyTable.Find(ticket);在环境 #1 中运行时耗时不到一秒,在环境 #2 中运行时耗时超过一分钟。

Result我执行的另一个测试是,如果检索到的记录的列小于 500KB(大约 10KB 或更小),则查询在两种环境中花费的时间相当(不到一秒) 。

为什么两个环境之间存在这种性能差异,仅对于检索大记录的特定查询?

环境网络化

有一台金属服务器托管所有这些环境。金属服务器操作系统是Windows Server 2012 Data Center R2。知识产权10.0.1.1。金属服务器还运行 SQL Server DB。

IIS 在虚拟机上运行(假设使用 IP 10.0.1.2)。该虚拟机使用 VMWare Workstation 15 Player 在金属服务器之上运行。虚拟机操作系统为Windows Server 2016 Datacenter。

K8S 环境部署在金属服务器顶部运行的 3 个虚拟机上,使用 VMWare Workstation 15 Player。这3台虚拟机的操作系统是Linux Ubuntu Server 20.04。

一台VM作为主节点。另外 2 个 VM 是运行 Pod 的工作节点。VM 的 IP 为10.0.1.10(master)10.0.1.1110.0.1.12(workers)。

现在,K8S 有一个内部 IP 分配的内部机制,可以为不同的 pod 提供其他内部地址,例如 192.168.1.X(不确定这是否与此对话相关......)。无论如何,在我们的连接字符串中,我们使用地址10.0.1.1(运行 SQL Server 的金属服务器)来引用 SQL Server。

附加实验1

我们在测试中添加了第三个环境,即另一个 K8S 集群,在完全相同的 pod 配置上运行相同版本的应用程序(在集群上部署资源的相同 YAML)。

注意:但在这种情况下,数据库的实例是不同的:它具有完全相同的架构、资源、DBMS 版本、网络配置等,它只是一个不同的实例。

查询的结果与在 IIS 上运行的环境 #1 相当。

附加实验2

我们尝试使用独立的命令行 SQL 客户端 (Python) 执行相同的查询。

public void QueryTable(Guid ticket)
{
    using (MyDBContext db = new MyDBContext)
    {
        var res = db.MyTable.Find(ticket);
        Console.Write("Res found:" + (res != null));
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我们从工作节点(即 K8S pod 外部)的命令行执行这些行,则查询速度很快,耗时不到一秒。如果我们将这些行作为 K8S pod 的一部分执行,则又需要 1 分钟左右。

因此,最重要的是,我们使用 python 客户端与 EF Core 得到了可比较的结果,此时罪魁祸首似乎是 pod(的网络)。我正确地阅读了这些结果吗?