asp.net-core - 在 Web 环境中使用会话令牌管理 CosmosDb 会话一致性级别
问题描述
我的环境是使用 .NET SDK 访问 CosmosDb(又名 DocumentDb)的 ASP.NET Core 2.x。
我的收藏的默认一致性级别设置为“会话”。对于我的用例,我需要一个经过身份验证的 Web 用户在 Web 请求之间的读/写方面始终拥有一致的数据。
我有一些 CosmosDB 存储库逻辑,通过 ASP.NET Core Singleton 依赖注入可用于我的控制器逻辑,如下所示:
services.AddSingleton<DocumentDBRepository, DocumentDBRepository>(x =>
new DocumentDBRepository(
WebUtil.GetMachineConfig("DOCDB_ENDPOINT", Configuration),
WebUtil.GetMachineConfig("DOCDB_KEY", Configuration),
WebUtil.GetMachineConfig("DOCDB_DB", Configuration),
"MyCollection",
maxDocDbCons));
DocumentDBRespository 创建一个 cosmos 客户端,如下所示:
public DocumentDBRepository(string endpoint, string authkey, string database, string collection, int maxConnections)
{
_Collection = collection;
_DatabaseId = database;
_Client = new DocumentClient(new Uri(endpoint), authkey,
new ConnectionPolicy()
{
MaxConnectionLimit = maxConnections,
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
RetryOptions = new RetryOptions()
{
MaxRetryAttemptsOnThrottledRequests = 10
}
});
_Client.OpenAsync().Wait();
CreateDatabaseIfNotExistsAsync().Wait();
CreateCollectionIfNotExistsAsync().Wait();
}
据我了解,这意味着每个 Web App 服务器一个 CosmosDB 客户端。我确实有多个 Web 应用服务器,因此单个用户可能会从多个 AppServer 和不同的 CosmosDb 客户端访问 CosmosDB。
在用户与 ComosDB 交互之前,我会检查他们的会话对象是否有 CosmosDb SessionToken,如下所示:
string docDbSessionToken = HttpContext.Session.GetString("StorageSessionToken");
然后,例如,在编写文档时,该方法看起来像这样:
public async Task<Document> CreateItemAsync<T>(T item, Ref<string> sessionTokenOut, string sessionTokenIn = null)
{
ResourceResponse<Document> response = null;
if (string.IsNullOrEmpty(sessionTokenIn))
{
response = await _Client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(_DatabaseId, _Collection), item);
}
else
{
response = await _Client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(_DatabaseId, _Collection), item, new RequestOptions() { SessionToken = sessionTokenIn });
}
sessionTokenOut.Value = response.SessionToken;
Document created = response.Resource;
return created;
}
这个想法是,如果我们有一个会话令牌,我们传递一个并使用它。如果我们没有,只需创建文档,然后将新创建的会话令牌返回给调用者。这工作正常...
除了,我不清楚为什么当我传递一个会话令牌时,我会得到一个不同的会话令牌。换句话说,当_Client.CreateDocumentAsync
返回时,response.SessionToken
总是与参数不同sessionTokenIn
。
这是否意味着我应该从那时起为该用户使用新的会话令牌?这是否意味着我应该忽略新的会话令牌并使用初始会话令牌?
这些“会话”中的一个甚至会持续多长时间?它们是传统意义上的会话吗?
最终,我只需要确保同一用户始终可以读取他们的写入内容,而不管他们连接到哪个 AppServer 或当前有多少其他用户正在使用数据库。
解决方案
我想这里的困惑在于会话是什么?
在大多数场景/框架中,将 session 视为静态标识符(相关性),而与 cosmos 一样, sessionToken 是动态的(一种书签/cosmos db 状态的表示,随 writes 而变化)。将其命名为“sessionToken”可能是混淆的根源。
在这种特定情况下,您应该使用 cosmos API 中的“返回的 sessiontoken ”。
推荐阅读
- python - 为什么会得到意想不到的 dict
- jquery - 关注jquery的变化
- c++ - 使用索引几何增强多边形
- pyspark - PySpark 并行读取多个文件
- objective-c - 应用程序因 Objective-C 中的错误“Invalid pointer dequeued from free list”而崩溃
- python - Python pandas从左表和右表中获取左表中缺少的行
- kops - 当我为 kops apiVersion 指定错误名称时没有错误,发生了什么?
- python - 'Host Unreachable' 返回成功
- java - Java apache poi从多个相互关联的excel表创建数据透视表
- visual-studio-code - VS Code - 无法找到并安装 C++ 扩展