活动函数Http调用问题Nodejs



我有一个业务流程,需要100 search terms。将这些搜索词分批处理,每批10个,然后扇形展开搜索活动(每个活动有10个名称)。

搜索活动按顺序处理每个名称。对于每个名字,它使2 search requests变成azure search。一个有空格和标点符号,另一个没有。为了使搜索请求,我调用azure搜索的REST API。

业务流程等待所有搜索活动解析并返回结果。

我面临的问题是the round trip for the azure search HTTP request is taking too long in the function app when deployed on azure.

在搜索开始时,每个请求需要3-4秒。但是在请求很少的情况下,单个请求的时间会增加到17-20秒。

在本地,当我使用相同的输入和请求运行此业务流程到相同的azure搜索索引时,每个请求不需要超过1.5 - 2秒。在本地,它需要1.0-1.2 minutes来完成业务流程。但是已部署的应用程序对相同的azure搜索索引的相同输入和请求采用7-8 minutes

以下是我如何为搜索活动函数发出请求(代码)):
const request = require('request');
const requestDefault = request.defaults({
method: 'GET',
gzip: true,
json: true,
timeout: `some value`,
time: true, 
pool: {maxSockets: 100}
});

module.exports = async function (context, names) {
let results = [];
for (let i = 0; i < names.length; i++) {
results.push(await search(context, names[i]));
results.push(await search(context, withOutSpaceAndPunctuations(names[i])));
}
return results;
}
function search(context, name) {
let url = createAzureSearchUrl(name);
return (new Promise((resolve, reject) => {
requestDefault({
uri: url,
headers: { 'api-key': `key` }
}, function (error, response, body) {
if (!error) {
context.log(`round trip time => ${response.elapsedTime/1000} sec`);
context.log(`elapsed-time for search => ${response.headers['elapsed-time']} ms`);
resolve(body.value);
} else {
reject(new Error(error));
}
})
}));
}
function createAzureSearchUrl(name) {
return `azure search url`;
}

编排

const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
let names = context.bindings.context.input;
let chunk = 10;
let batches = [];
for (let i = 0; i < names.length; i += chunk) {
let slice = names.slice(i, i + chunk);
let batch = [];
for (let j = 0; j < slice.length; j++) {
batch.push(slice[j]);
}
batches.push(batch);
}
const tasks = [];
for (let i = 0; i < batches.length; i++) {
tasks.push(context.df.callActivity("Search", batches[i]));
}
let searchResults = yield context.df.Task.all(tasks);
return searchResults;
});

elapsed-time for search总是小于500毫秒。

根据本文档,我删除了request模块并使用了本地https模块。

var https = require('https');
https.globalAgent.maxSockets = 100;

function searchV2(context, name) {
let url = createAzureSearchUrl(name);
const t0 = performance.now();
return (new Promise((resolve, reject) => {
let options = {headers: { 'api-key': 'key' }}
https.get(url, options, (res) => {
onst t1 = performance.now();
context.log(`round trip time => ${(t1-t0)/1000} sec`);
context.log(`elapsed-time => ${res.headers['elapsed-time']}`);
res.on('data', (d) => {
resolve(d);
});
});
}));
}

为了进行测试,我将批计数从10更改为100,以便单个搜索活动依次处理所有100个搜索项。这里所有对azure搜索的请求都采用3.0-3.5 seconds。但是3.5sec * 200 req = 11.6666666667 minutes。所以不散开是不行的

部署的应用程序有一个1 instance count。我更新到6 instances。有了6个实例,现在单个请求需要3.5 - 7.5 seconds100 search terms的总时间现在占用4.0 - 4.3 minutes。将实例增加到6有很大的改进。但是,它仍然需要7.5秒来处理很多请求。

主机文件中maxConcurrentActivityFunctions

参数为6。我将instance count更新为10,maxConcurrentActivityFunctions也更新为10。但仍然用4.0 - 4.3 minutes代替100 search terms。没有改善。我看到很多请求需要10秒。

我不认为这是一个代码级的问题。它与扇形展开和对同一函数进行多个并发请求有关。

为什么这发生在部署的应用程序,而不是本地?我应该做些什么来减少请求延迟?如有任何建议,我们将不胜感激。

我的功能应用程序运行在azure功能App Service plan上。我的DurableTask版本是1.7.1

当并行进行索引时,延迟会增加。你也是这样吗?查询的elapsed-time可能没有考虑延迟。

在Azure门户上,当您导航到搜索资源时,如果您转到监视选项卡,您应该能够看到延迟,查询数量,受限查询的百分比。这应该会提供一些方向。你的搜索服务在哪一层?您为搜索服务提供了多少分区和哪些副本?

作为测试,您可以增加副本和分区的数量,看看这是否有助于您的性能。

最新更新