简体   繁体   中英

How to execute N concurrent instances of a lambda function

I'm trying to see if I can call N instances of a lambda function in my code. This is a simple code that I execute on an EC2 instance:

const AWS = require('aws-sdk');
const https = require('https');

const sslAgent = new https.Agent({
    keepAlive: true,
    maxSockets: 50,
    rejectUnauthorized: true,
});
sslAgent.setMaxListeners(0);

AWS.config.update({
    region: 'us-east-1',
    httpOptions: {
        agent: sslAgent,
    },
});

const lambda = new AWS.Lambda();

function call() {
    return lambda.invoke({
        FunctionName: "test",
        Payload: JSON.stringify({
            wait: 5000,
        }),
    }).promise();
}

(async () => {
  let start = Date.now();
  const promises = [...Array(200).keys()].map(i => {
    return call(new Date(Date.now()).toISOString())
      .then(data => {
        console.log(`Success (${i})`);
      })
      .catch(err => {
        console.log(`Error (${i}): ${err}`);
      });
  });
  await Promise.all(promises);
  let end = Date.now();
  console.log((new Date(end - start).toISOString()).substr(11, 12));
})();

As you can see, this code will execute a lambda function called test 200 times. Then it will wait for all of them to return and then measures how long it takes (in case you are interested, it takes 20.883 seconds - yeah I know it's too long!).

Then on the server side, I have this test lambda function:

exports.handler = async (event, context, callback) => {
    // TODO implement
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return new Promise((resolve) => {
        setTimeout(() => {
            callback(null, response);
            resolve();
        }, event.wait);
    });
};

Pretty simple and straight forward, it will wait as long as it is requested before it returns.

Now, the problem is that I executed this scenario and this led to only 50 concurrent execution of the lambda function. I know this based on the logs generated on CloudWatch. There I can see that each instance of the lambda function has served 4 requests (hence the 20 seconds reported before - 4 sequential execution * 5 seconds wait equals 20 seconds).

I can verify that I have not set any concurrency limit for the lambda function and it is on the default option Use unreserved account concurrency . Also, the account is rather empty and I'm far behind the 1000 limitation.

My question is; why I cannot execute all the 200 requests concurrently and why did I face the throttling?

Many AWS SDK's services have default executor pool size of 50. Since you are also using AWS SDK, looks like it is the same problem. You can try running the same script multiple times in parallel and I think then you should not see the same 50 invocations limitation.

You can configure the Max Socket size with something like this

var https = require('https');
var agent = new https.Agent({
   maxSockets: 200
});
const lambda = new AWS.Lambda({
    httpOptions:{
        agent: agent
    }
});

Similar issue on AWS forum: https://forums.aws.amazon.com/thread.jspa?threadID=286655

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM