Azure函数在中途重新启动,然后永不返回(HTTP触发器)

时间:2018-03-27 17:47:27

标签: node.js azure azure-functions azure-cosmosdb

我有一个通过HTTP触发的nodejs app功能。它调用cosmosdb存储过程,为事件中心设置一些输出绑定,然后返回给用户。

问题是函数工作正常,但由于某种原因它总是在返回给用户之前重新启动,即使在使存储过程处理这样的事件之后,该函数也永远不会返回。在邮递员中,它总是返回一个通用的天蓝色502.在测试用户界面中,它最终似乎超时并且响应为500而没有正文。

当我通过azure功能测试运行时,它似乎总是在中途重启。几乎总是它到达最后甚至调用Context.done()。我知道这是因为正在发送事件中心事件并触发其他功能。但是,不是将HTTP res返回给用户,而是重新启动应用程序,遍历所有内容,然后抛出错误,该错误记录在.catch中,但不会从HTTP调用返回。它最终只是达到超时并返回500或502。

更奇怪的是,当查看“监视器”选项卡下的条目日志时,只有第二次运行存在,但显示它已成功执行!我试过通过Azure功能测试和postman运行该功能,结果是一样的。

用于返回promise的函数,我过去曾遇到过这个问题,因此我转换为调用context.done()而没有运气。造成这种情况的原因是什么?

这是一个最终返回500的示例运行(取自功能测试日志流):

2018-03-27T17:27:57.636 [Info] Function started (Id=b4c64acc-3120-4dbd-b067-034ef7e6b548)
2018-03-27T17:28:00.436 [Info] 1
2018-03-27T17:28:07.167 [Info] Function started (Id=59ef098a-8ce0-43fa-9a98-c2043f40566a)
2018-03-27T17:28:10.452 [Info] 1
2018-03-27T17:28:10.881 [Info] 2
2018-03-27T17:28:10.886 [Info] 3
2018-03-27T17:29:22  No new trace in the past 1 min(s).
2018-03-27T17:30:22  No new trace in the past 2 min(s).
2018-03-27T17:31:22  No new trace in the past 3 min(s).
2018-03-27T17:32:22  No new trace in the past 4 min(s).

一个一直到context.done():

2018-03-27T17:33:56.887 [Info] Function started (Id=7e0c9d3d-549b-4f7f-905b-454d69e18cca)
2018-03-27T17:34:00.902 [Info] 1
2018-03-27T17:34:01.324 [Info] 2
2018-03-27T17:34:01.339 [Info] 3
2018-03-27T17:34:02.121 [Info] 4
2018-03-27T17:34:02.121 [Info] 5
2018-03-27T17:34:02.121 [Info] 6
2018-03-27T17:34:08.563 [Info] Function started (Id=ffcdf487-d1e6-4422-856f-ed709470605b)
2018-03-27T17:34:12.090 [Info] 1
2018-03-27T17:34:12.530 [Info] 2
2018-03-27T17:34:12.530 [Info] 3
2018-03-27T17:35:22  No new trace in the past 1 min(s).
2018-03-27T17:36:22  No new trace in the past 2 min(s).
2018-03-27T17:37:22  No new trace in the past 3 min(s).
2018-03-27T17:38:22  No new trace in the past 4 min(s).
2018-03-27T17:39:22  No new trace in the past 5 min(s).
2018-03-27T17:40:22  No new trace in the past 6 min(s).

我尝试重新启动功能应用程序似乎没有帮助。如果重要的话,这是一个消费计划应用程序。

功能如下:

const DB = require('../Shared/DB');
const Errors = require('../Shared/Errors');
const Auth = require("../Shared/Auth");
const Approvals = require("../Shared/Approval");

module.exports = function (context, req) {
  let user; 
  let found;
  let outMessage = 'CheckoutRequested';
  let outMessageObj = {'id': req.params.id};
  return Auth.get_user_from_request(req).then( (u) => {
    context.log(1);
    user = u;
    outMessageObj['user'] = u.raw();

    if (!req.params.id) throw new Errors.BadRequestError("Id is a required parameters.");

    const db = new DB();
    // Call stored procedure;
    return db.check_out(req.params.id, user);
  }).then( (res) => { 
    context.log(2);
    found = res;
    outMessageObj['found'] = found;

    context.log(3);
    return Approvals.get_approvers(user, found);
  }).then(approvers => {
      context.log(4);
    // Determine the type of event hub message to send.
    if (approvers.length == 0){
      outMessage = 'CheckoutApproved';
    }

    outMessageObj['approvers'] = approvers;

    context.bindings[outMessage] = outMessageObj;
    context.log(5);
    context.bindings.res = {
      status: 200,
      body: {
        "found": found, 
        "user": user
      }
    };
    context.bindings.output = context.bindings.res;
    context.log(6);
    context.done();
  }).catch( (error) => {
      context.log('error');
    context.log.error(error);
    if (outMessageObj.user){
      context.bindings['CheckoutFailed'] = outMessageObj;
    }
    context.bindings.res = {
      status: 500,
      body: {
        "error": error.message, 
      }
    };
    context.done();
  });
};

根据输出,我在3个不同的分区上有3个输出绑定:

{
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "route": "checkout/{id}",
      "methods": [
        "put"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "eventHub",
      "name": "CheckoutApproved",
      "connection": "********",
      "path": "CheckoutApproved",
      "direction": "out"
    },
    {
      "type": "eventHub",
      "name": "CheckoutRequested",
      "connection": "********",
      "path": "CheckoutRequested",
      "direction": "out"
    },
    {
      "type": "eventHub",
      "name": "CheckoutFailed",
      "connection": "********",
      "path": "CheckoutFailed",
      "direction": "out"
    }
  ],
  "disabled": false
}

编辑:为此,我尝试将输出设置为所有context.res,context.bindings.res,context.done(null,响应对象),并返回一个promise。

1 个答案:

答案 0 :(得分:0)

您是否尝试在context.res中返回状态代码?

像这样的东西       context.res = {         状态:200,         身体:物品       };