SaaS 环境/方案中的实体框架 6 启动性能



我们在Web SaaS应用程序中使用EF6.2。我们每个帐户都有数据库架构,这意味着每个客户都会获得单独的SQL Server数据库。

我们看到的是极慢的启动。我们还看到,随着我们添加的帐户数量,初创公司的速度会相应变慢

我们目前不使用任何可能的优化。我们不做 ngen,我们不"预编译"视图。但令我困扰的是,我们整体上承受的不是性能影响,而是每个帐户。

这让我相信它与元数据缓存有关,根据这里的文章,元数据缓存是在内存中构建的,并使用从连接字符串派生的哈希进行标记。 https://learn.microsoft.com/en-us/ef/ef6/fundamentals/performance/perf-whitepaper

3.4.1 元数据缓存算法

1.模型的元数据信息存储在每个实体连接的项集合中。 •作为旁注,有不同的 模型不同部分的 ItemCollection 对象。例如 StoreItemCollections 包含有关数据库的信息 型;对象项集合包含有关数据模型的信息; EdmItemCollection 包含有关概念模型的信息。

2.如果两个连接使用相同的连接字符串,则它们将共享同一个 ItemCollection 实例

寻找有关如何将"预热"时间减少到单次发生的任何建议

编辑:这是基于模型优先的EDMX数据库,没有迁移

每个数据库上下文在首次访问时都会产生一次性的启动成本,因此您需要确保客户端连接仅接触其自己的 DbContext,以避免第一次启动等待所有客户端数据库上下文被触及。对于我的模型,我有一个通用数据库,初始登录使用它来解析客户端应该与之通信的版本数据库,从那里将经过身份验证的用户移交给他们的数据库。您最不想要的是以任何方式迭代 DbContext 的代码。

编辑:以上不正确,通过测试验证。同一架构的 DbContext 实例命中同一应用程序域中的不同数据库实例不会产生启动成本。Web 应用程序的关键因素是应用程序域的范围如何限定为请求。(考虑任何负载平衡等)

另一个需要考虑的因素是使用 DB-First 并将数据库初始值设定项设置为 #null 以避免任何迁移检查等。这将节省启动时间。

可以采用边界上下文来为应用程序的关键区域提供服务。上下文定义越大、越复杂,启动所需的时间就越长。通过使用边界上下文来涵盖应用程序的密切相关区域,可以减少在首次使用时启动给定上下文所需的时间。 例如 OrderManagementContext、CustomerManagementContext。可以在每个上下文中引用实体,但您可以优化定义,其中只需要在上下文中提供摘要表示形式,而不在顶级处理该实体。例如,当我处理订单时,我需要客户摘要。OrderDbContext 不是映射整个客户及其我不关心的相关实体,而是映射一个 OrderCustomer 实体,该实体仅将"客户"表(或视图中)中的字段映射到我在处理订单时需要的有关客户的字段。每个上下文中更少、更小、更简单的实体 = 更快的上下文初始化。

最后,当用户登录时,通过在登录过程中对上下文中的一个实体执行简单查询,尽早启动上下文。这会触发映射的初始一次性启动,这样第一个"真实"查询就不会受到该延迟的打击。 即

using (var orderContext = new OrdersDbContext())
{
var result = orderContext.Orders.Any();
}
using (var customerContext = new CustomersDbContext())
{
var result = customerContext.Customers.Any();
}

其中每个都执行一个非常快速的查询,但初始化初始启动命中的映射。

除了最小化上下文启动成本之外,您可能要考虑的另一个因素是环境正在执行的任何负载平衡以及对启动成本的可能影响。启动与应用程序域相关联,因此,负载均衡的问题是否必须在每个工作线程上发生。 (这超出了我所知道的范围,我会从最小化上下文启动成本开始,然后开始窥视那个兔子洞,如果仍然需要的话。

最新更新