首页 > 解决方案 > 活动函数Http调用问题Nodejs

问题描述

我有一个需要100 search terms. 将这些搜索词以 10 个为一组进行批处理,然后扇出以开始搜索活动(每个活动需要 10 个名称)。

搜索活动按顺序处理每个名称。对于每个名称,它2 search requests使azure search. 一个有空格和标点符号,另一个没有。为了发出搜索请求,我调用了天蓝色搜索的 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 秒。

在本地,当我使用相同的输入和对相同天蓝色搜索索引的请求运行此编排时,每个请求的时间不会超过1.5 - 2一秒。1.0-1.2 minutes编排需要在本地完成。但是部署的应用程序需要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 个搜索词。这里所有对天蓝色搜索的请求都被占用了3.0-3.5 seconds。但是3.5sec * 200 req = 11.6666666667 minutes。所以不散开不是一种选择。

部署的应用程序有一个1 instance count. 我将其更新为6 instances. 现在有 6 个实例需要3.5 - 7.5 seconds一个请求。现在的总时间100 search terms需要4.0 - 4.3 minutes. 将实例增加到 6 个有很大的改进。但是,很多请求仍然需要 7.5 秒。maxConcurrentActivityFunctions主机文件中的参数为 6。

我更新了instance countto10maxConcurrentActivityFunctionsto 10。但它仍然4.0 - 4.3 minutes需要100 search terms。没提升。我看到很多请求最多需要 10 秒。

我认为这不是代码级别的问题。它与扇出并为同一功能发出多个并发请求有关。

为什么这发生在已部署的应用程序而不是本地?我应该怎么做才能减少请求延迟?任何建议将不胜感激。

我的函数应用在 azure function 上运行App Service plan。我的 DurableTask 版本是1.7.1

标签: node.jsazure-functionsazure-cognitive-searchazure-durable-functions

解决方案


当同时进行索引时,延迟会增加。你是这种情况吗?elapsed-time因为查询可能没有考虑延迟。

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

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


推荐阅读