如果每 30 秒超过 1 个请求,Lambda 无法跟上/丢弃请求(通过 API 网关)(进程在完成请求之前退出)



我正在运行一个相对简单的AWS函数来添加订阅到Stripe。

它运行良好,除非我在刚刚点击它后不久点击它。只是尝试在一个接一个失败的邮差中运行它,并返回:

{"errorMessage": "Process exited before completing request"}

请求通过API网关传递。

功能配置为30s超时,在基本128M RAM上运行需要~1300ms(问题可重复@ 256M)。

我认为这正是Lambda设计要避免的…我正在重新考虑将Lambda用于(同步)关键任务组件的决定。

编辑:按要求,这里是函数代码:

var stripe = require('stripe');
exports.handler = function (event, context, callback) {
    var self = this;
    stripe = stripe(getKey(event.stage, 'STRIPE_SECRET_KEY'));
    self.createSubscription = createSubscription;
    self.validPayload = validPayload;
    console.log('event: ', event);
    if (self.validPayload(event, context)) {
        self.createSubscription(event, stripe, callback, context);
    }
    /**
     * checks that the necessary payload has been received
     * if YES: returns true and allows process to continue
     * if NO: throws context.fail with useful error message(s)
     * operating under custom error code naming convention of
     * http code + 3 digit ULM error code
     * @param event - from Lambda
     * @param context - from Lambda
     * @returns {boolean} - whether the payload contains the required data
     */
    function validPayload (event, context) {
        var errorResponse = {
            status: 400,
            errors: []
        };
        if (!event.billing_email) {
            errorResponse.errors.push({
                code: 400001,
                message: "No billing email provided."
            })
        }
        if (!event.plan) {
            errorResponse.errors.push({
                code: 400002,
                message: "No plan was selected."
            })
        }
        if (!event.token) {
            errorResponse.errors.push({
                code: 400003,
                message: "A valid credit card was not provided."
            })
        }
        if (!!errorResponse.errors.length) {
            context.fail(JSON.stringify(errorResponse));
            return false;
        } else {
            return true;
        }
    }
    /**
     * Creates a new customer & subscription using stripe package method
     * if success, executes callback with response data
     * if fail, throws context.fail with useful error message(s)
     * @param event - from Lambda
     * @param stripe - probably not necessary...
     * @param callback - from Lambda
     * @param context - probably not necessary...
     */
    function createSubscription (event, stripe, callback, context) {
        stripe.customers.create({
            source: event.token,
            plan: event.plan,
            email: event.billing_email
        }, function (err, customer) {
            if (err) {
                var errorResponse = {
                    status: 400,
                    errors: []
                };
                errorResponse.errors.push({
                    code: 400004,
                    message: err.message
                });
                console.error('Customer/Plan Creation Failed');
                callback(JSON.stringify(errorResponse));
            } else {
                callback(null, {
                    status: 200,
                    customer: customer
                });
            }
        });
    }
    function getKey (stage, keyId) {
        var keys = {
            STRIPE_SECRET_KEY: {
                staging: 'sk_test_123456',
                prod: 'sk_live_123456'
            }
        };
        if (stage === 'prod') {
            return keys[keyId][stage];
        } else {
            return keys[keyId]['staging'];
        }
    }
};

编辑2:在CloudWatch中发现了这个错误日志:TypeError: stripe is not a function at exports.handler (/var/task/exports.js:5:14)

@rowanu是正确的,你的问题是在这一行stripe = stripe(getKey(event.stage, 'STRIPE_SECRET_KEY'));。由于Lambda保持热来处理后续请求,因此在handler函数之外声明的任何变量将被每个进入的新请求看到。这应该是一个简单的修复,不要重新定义stripe变量。像这样的代码可以达到这个目的:

var stripe = require('stripe');
var stripeInstance; // undefined on startup
exports.handler = function (event, context, callback) {
  // now define stripeInstance if its not already defined
  if(!stripeInstance) {
    stripeInstance = stripe(getKey(event.stage, 'STRIPE_SECRET_KEY'));
  }
  // now all functions will be able to use the same instance of stripe. 
  // This assumes the event.stage is always the same, if you need a new instance for every request then remove the if statement
  // rename all references of stripe to stripeInstance
  ...

"Process exit before completed request"表示你的函数没有调用回调就退出了。它与超时或节流无关。

通常这表示从没有足够的错误处理的代码路径抛出异常。

你只需要处理或修复"stripe不是一个导出函数"。处理程序(/var/task/exports.js:5:14)"并调用相应的回调。

相关内容

  • 没有找到相关文章

最新更新