CosmosDB中RUs调整为何影响结果集及续传令牌返回?
首先,我得先点出你代码里的几个关键逻辑错误,这就是导致高RU下续传令牌异常的核心原因:
核心问题诊断
错误的结果计数逻辑
你用result.length >= maxResult来判断是否达到最大记录数,但result.push(docFeed)是把整页的记录数组(docFeed)直接push进去,所以result是一个二维数组,result.length统计的是页数而非总记录数。你的maxResult设为900000,但实际总记录只有65000,这个判断永远不会触发,等于完全失效。对
queryDocuments返回值的错误处理
Cosmos DB的collection.queryDocuments是异步操作,返回false并不代表查询失败,而是表示当前无法立即发起查询(比如系统内部缓冲暂时饱和),此时应该等待回调执行,而不是直接终止查询并返回续传令牌。在高RU下,查询发起速度更快,更容易触发这种场景,导致你中途停止查询,误以为续传令牌为NULL。无效的
pageSize设置
Cosmos DB查询的单页返回上限是1000条记录,你设置的pageSize: 900000不会生效,反而可能导致查询逻辑混乱。
修复后的完整代码
function count(continuationToken) { var filterQuery = 'select c.id from c where c.Type = 0'; var collection = getContext().getCollection(); var maxResult = 900000; // 最大返回记录数 var result = []; var totalCount = 0; // 跟踪已获取的总记录数 tryQuery(continuationToken); function tryQuery(nextContinuationToken) { // Cosmos DB单页最多返回1000条,设置合理的pageSize var responseOptions = { continuation: nextContinuationToken, pageSize: 1000 }; // 先检查是否已经达到最大记录数,避免无效查询 if (totalCount >= maxResult) { setBody(nextContinuationToken); return; } // 发起查询,不管返回true/false,都通过回调处理后续逻辑 var queryInitiated = collection.queryDocuments( collection.getSelfLink(), filterQuery, responseOptions, onReadDocuments ); // 仅当完全无法发起查询时,才返回当前结果和续传令牌 if (!queryInitiated) { setBody(nextContinuationToken); } } function onReadDocuments(err, docFeed, responseOptions) { if (err) { throw 'Error while reading document: ' + err; } // 将当前页的记录展开添加到结果数组(变成一维数组,方便后续处理) result.push(...docFeed); totalCount += docFeed.length; // 优先判断是否达到最大记录数,再决定是否继续查询 if (totalCount >= maxResult) { setBody(responseOptions.continuation); } else if (responseOptions.continuation) { // 还有更多数据,继续递归查询 tryQuery(responseOptions.continuation); } else { // 所有数据已获取完成,返回NULL续传令牌 setBody(null); } } function setBody(continuationToken) { var body = { records: result, continuationToken: continuationToken, totalCount: totalCount // 可选:返回已获取的总记录数,方便客户端校验 }; getContext().getResponse().setBody(body); } }
关键修复点说明
总记录数跟踪
新增totalCount变量,每次获取到分页数据后累加docFeed.length,用这个值来判断是否达到maxResult,逻辑更准确。扁平化结果数组
使用result.push(...docFeed)将每页的记录展开添加到结果数组,返回的records是一维数组,避免后续客户端处理二维数组的麻烦。修正异步查询处理逻辑
不再因为queryDocuments返回false就直接终止查询,而是仅在完全无法发起查询时才返回当前状态,确保所有能获取的数据都被收集。合理设置
pageSize
遵循Cosmos DB的限制,将pageSize设为1000,最大化每页获取的记录数,减少递归调用次数。
额外建议
- 添加错误重试机制:如果
onReadDocuments抛出错误,可以增加重试逻辑(比如重试3次),避免单次查询失败导致整个流程中断。 - 利用分区键:如果你的集合是分区的,在查询中指定分区键可以大幅提升查询效率,减少续传令牌的生成频率。
- 监控存储过程性能:在高RU下,可以通过Cosmos DB的监控面板查看存储过程的执行时间、内存占用等指标,确保不会触发资源限制。
内容的提问来源于stack exchange,提问作者Wynand Murray

