首页 > 解决方案 > 一次不能调用超过 64 个 Lambda 函数?

问题描述

我不能调用超过 64 个同步 lambda 函数而不会出现Ops Limit: 64异常,我也不知道为什么。

Lambda 限制文档中没有提及这一点。事实上,它说您最多可以有 1000 个并发执行。lambda scaling 文档还声明支持高达 3k 调用的临时突发。

那么为什么我微不足道的 65 次调用会导致 Lambda 拒绝?

复制:

在我的帐户上,我有一个非常简单的 Lambda,它会等待 5 秒(模拟工作),然后返回默认的 json blob。

import json
import time 

def lambda_handler(event, context):
    # TODO implement
    time.sleep(5)
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

不包括time.sleep调用,这是您创建新 Python Lambda 函数时生成的确切代码。所以,这里没有奇怪的事情发生。

调用

现在要调用它,我只需将调用任务提交到线程池中。

(defn invoke-python [_]
  (aws/invoke
        lambda
        {:op :Invoke
         :request {:FunctionName "ExampleSlowPythonFunction"
                   :Payload (json/write-str payload)}})

这就是所有的电话正在做的事情。只需直接invoke致电 AWS。(这里的库是Cognitect 的 AWS API。但它只是遵循 REST API,所以没关系。)

线程池只是 Java 的执行器之一。我给它一个大小和任务,它在一个大小的池中执行所述任务n

(defn call-it-a-bunch
  [n tasks]
  (let [pool (Executors/newFixedThreadPool n)]
    (let [futures (.invokeAll pool tasks)]
      (.shutdown pool)
      (mapv #(.get %) futures))))

64 次调用:没问题

(def sixty-four-invoke-tasks (map invoke-python (range 64)))

(call-it-a-bunch 64 sixty-four-invoke-tasks)

一个OK。没问题。

65 次调用:问题

(def sixty-FIVE-invoke-tasks (map invoke-python (range 65)))

(call-it-a-bunch 65 sixty-FIVE-invoke-tasks

我会收到Ops limit reached: 64第 65 个请求。

我的账户上没有运行其他 Lambda。我尝试拨打 Python Lambda 函数上的保留实例,以确保 lambda 可用

但是,Ops 限制错误仍然存​​在。

为什么我的账户有一个bucket 1000并发可用,但我的函数不能同时调用超过64次?

标签: amazon-web-servicesclojureaws-lambda

解决方案


我无法重现您的问题。我正在使用常规Java。我有你确切的 Python Lambda 并且有Runnable

import com.amazonaws.regions.Regions;
import com.amazonaws.services.lambda.AWSLambda;
import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;

public class LambdaThread implements Runnable {
    private String name;

    public LambdaThread(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        System.out.println( "starting thread " + name);

        Regions region = Regions.fromName("us-west-2");
        AWSLambda client = AWSLambdaClientBuilder.standard()
                .withRegion(region).build();
        InvokeRequest req = new InvokeRequest()
                .withFunctionName("test-load");

        InvokeResult result = client.invoke(req);

        System.out.println( "result from thread " + name + " is " + new String( result.getPayload().array()) );
    }
}

还有一个跑步者:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LambdaRunner {
    public static void main(String[] argv) {

        long startTime = System.currentTimeMillis();

        ExecutorService executor = Executors.newFixedThreadPool(999);
        for (int i = 0; i < 999; i++) {
            Runnable worker = new LambdaThread("thread " + i);
            executor.execute(worker);
        }
        executor.shutdown();
        while (!executor.isTerminated()) {
            try { Thread.sleep(1000); } catch ( InterruptedException ie ) { /* ignored */ }

            System.out.println( "waiting for thread termination...");
        }
        System.out.println("Finished all threads in " + (System.currentTimeMillis() - startTime) + "ms");

    }
}

对我来说,这个错误通常与 Clojure 中的一些措辞一致。您使用的是哪个版本的 Cognitect 库?我在 master 分支中看不到这条消息。

如果我用 2000 个线程运行它,我会得到:

线程“pool-1-thread-1990”中的异常

com.amazonaws.services.lambda.model.TooManyRequestsException:超出速率。(服务:AWSLambda;状态代码:429;错误代码:TooManyRequestsException;请求 ID:b7f1426b-419a-4d40-902d-e0ed306ff120)

没有任何关系ops


推荐阅读