在 DocumentDB 中分割租户和主机名的最佳方法是什么?
What's the best way to segment tenants and hostnames in DocumentDB?
我们有一个 B2B 模型,我们在 Azure 中为我们的小型企业客户的员工、合作伙伴和客户托管一个门户。这目前在 node.js Web 应用程序中对我们来说运行良好,但我们希望大规模迁移到 Azure Functions,这让我们重新考虑初始设计。
目前,进入网络应用程序的每个 XHR 请求都经过以下逻辑:
- 获取主机名对应的siteconfig文件
- 从站点配置文件中检索 organization_id
- 将 organization_id 插入到查询的 WHERE 子句中
我们使用 node-cache 将 siteconfig 文档存储在内存中,因此检索时间仍然非常快,只有在第一次请求主机名时,我们才会 运行 连续两次查询。
由于 Azure Functions 不存储请求之间的状态或没有缓存,我们将无法缓存 hostname/organizationid 关系。似乎如果我们 运行 在一个函数中针对每个请求执行两个 DocumentDB 查询,那么我们的数据库成本将几乎翻倍。
所以我的问题是 - 是否有一种好的方法可以在可以加载到 Azure 函数中的单个查询中检索此信息?在 RDBMS 的旧世界中,我只使用连接或什至像这样的子查询:
SELECT c.name, c.price
FROM c
WHERE c.type = "product"
AND c.organization_id =
(SELECT d.organization_id FROM d WHERE d.hostname = @hostname)
下面是一些示例文档。具体来说,当请求进入 portal.xyz.com/api/products 时,我们希望 return Widget A 和 Widget B 使用单个查询而不是 Gadget,因为它属于不同的公司。
{
id: "17500961",
type: "organization",
name: "XYZ inc."
}
{
id: "34903332",
type: "siteconfig",
hostname: "portal.xyz.com",
organizationid: "17500961"
}
{
id: "86785057",
type: "product",
name: "Widget A",
price: "9.99",
organizationid: "17500961"
}
{
id: "17979681",
type: "product",
name: "Widget B",
price: "14.99",
organizationid: "17500961"
}
{
id: "24669887",
type: "product",
name: "Gadget",
price: "899",
organizationid: "31514620"
}
我们不想依赖数据请求中来自客户端的 organizationid,这提供了内部安全性,因为知道 X 公司永远无法检索除他们自己的组织以外的任何组织的数据,正如在服务器上确定的那样传入请求 headers.
我想到的一个解决方案是将主机名添加到每个文档,但这似乎是一个极端数量的 redundant/replicated 数据。
DocumentDB 专家是否愿意对此进行权衡并提供一些指导?
有人可能会提供有关 Cosmos 的其他选项 DB/DocumentDB,但从 Azure Functions 的角度来看,这里有一些选项:
1.使用身份验证信息派生组织 ID
您没有描述您如何对用户进行身份验证,但一种非常常见的方法是确保诸如您的租户 ID(在您的情况下为组织 ID)之类的内容作为声明出现在签名令牌中可以在服务器上验证。这完全消除了在颁发令牌后进行缓存或额外查找的需要。
2。使用外部缓存
像 Azure Redis Cache 这样的外部缓存将允许您在函数环境之外维护所需的状态,并且可以在扩展时从函数应用程序实例访问。这提供了物超所值的卓越性能(您需要根据负载将成本与您为文档数据库请求支付的费用进行比较)
3。本地静态映射
仅将此选项用作后备选项,因为它不可预测并且可能会随着时间的推移而改变。推荐其他 2 个选项超过此
您可以在 Function App 环境中维护一个本地缓存,以减少查找次数。该缓存将确保这些查找不会针对每个请求进行,而是针对每个运行时实例进行,因此随着 Function App 的扩展,新实例不会填充该缓存,但是一旦信息被缓存,后续请求将不会访问同一主机需要获取组织信息。
如果您选择使用此解决方案,则需要密切关注应用程序的行为,因为如上所述,它可能会有所不同并且不会那么可预测
希望对您有所帮助。
我们有一个 B2B 模型,我们在 Azure 中为我们的小型企业客户的员工、合作伙伴和客户托管一个门户。这目前在 node.js Web 应用程序中对我们来说运行良好,但我们希望大规模迁移到 Azure Functions,这让我们重新考虑初始设计。
目前,进入网络应用程序的每个 XHR 请求都经过以下逻辑:
- 获取主机名对应的siteconfig文件
- 从站点配置文件中检索 organization_id
- 将 organization_id 插入到查询的 WHERE 子句中
我们使用 node-cache 将 siteconfig 文档存储在内存中,因此检索时间仍然非常快,只有在第一次请求主机名时,我们才会 运行 连续两次查询。
由于 Azure Functions 不存储请求之间的状态或没有缓存,我们将无法缓存 hostname/organizationid 关系。似乎如果我们 运行 在一个函数中针对每个请求执行两个 DocumentDB 查询,那么我们的数据库成本将几乎翻倍。
所以我的问题是 - 是否有一种好的方法可以在可以加载到 Azure 函数中的单个查询中检索此信息?在 RDBMS 的旧世界中,我只使用连接或什至像这样的子查询:
SELECT c.name, c.price
FROM c
WHERE c.type = "product"
AND c.organization_id =
(SELECT d.organization_id FROM d WHERE d.hostname = @hostname)
下面是一些示例文档。具体来说,当请求进入 portal.xyz.com/api/products 时,我们希望 return Widget A 和 Widget B 使用单个查询而不是 Gadget,因为它属于不同的公司。
{
id: "17500961",
type: "organization",
name: "XYZ inc."
}
{
id: "34903332",
type: "siteconfig",
hostname: "portal.xyz.com",
organizationid: "17500961"
}
{
id: "86785057",
type: "product",
name: "Widget A",
price: "9.99",
organizationid: "17500961"
}
{
id: "17979681",
type: "product",
name: "Widget B",
price: "14.99",
organizationid: "17500961"
}
{
id: "24669887",
type: "product",
name: "Gadget",
price: "899",
organizationid: "31514620"
}
我们不想依赖数据请求中来自客户端的 organizationid,这提供了内部安全性,因为知道 X 公司永远无法检索除他们自己的组织以外的任何组织的数据,正如在服务器上确定的那样传入请求 headers.
我想到的一个解决方案是将主机名添加到每个文档,但这似乎是一个极端数量的 redundant/replicated 数据。
DocumentDB 专家是否愿意对此进行权衡并提供一些指导?
有人可能会提供有关 Cosmos 的其他选项 DB/DocumentDB,但从 Azure Functions 的角度来看,这里有一些选项:
1.使用身份验证信息派生组织 ID
您没有描述您如何对用户进行身份验证,但一种非常常见的方法是确保诸如您的租户 ID(在您的情况下为组织 ID)之类的内容作为声明出现在签名令牌中可以在服务器上验证。这完全消除了在颁发令牌后进行缓存或额外查找的需要。
2。使用外部缓存
像 Azure Redis Cache 这样的外部缓存将允许您在函数环境之外维护所需的状态,并且可以在扩展时从函数应用程序实例访问。这提供了物超所值的卓越性能(您需要根据负载将成本与您为文档数据库请求支付的费用进行比较)
3。本地静态映射
仅将此选项用作后备选项,因为它不可预测并且可能会随着时间的推移而改变。推荐其他 2 个选项超过此
您可以在 Function App 环境中维护一个本地缓存,以减少查找次数。该缓存将确保这些查找不会针对每个请求进行,而是针对每个运行时实例进行,因此随着 Function App 的扩展,新实例不会填充该缓存,但是一旦信息被缓存,后续请求将不会访问同一主机需要获取组织信息。 如果您选择使用此解决方案,则需要密切关注应用程序的行为,因为如上所述,它可能会有所不同并且不会那么可预测
希望对您有所帮助。