2016-07-07 2 views
2

Я новичок в безостановочной фреймворке. При изучении лучших практик в бессервере. hereЛучшие практики в безсерверной платформе

У меня возник вопрос о «Инициализация внешних служб за пределами вашего Лямбда-кода». Как его реализовать? Например: Ниже кода в handler.js

const getOneUser = (event, callback) => { 
    let response = null; 
    // validate parameters 
    if (event.accountid && process.env.SERVERLESS_SURVEYTABLE) { 
    let docClient = new aws.DynamoDB.DocumentClient(); 
    let params = { 
     TableName: process.env.SERVERLESS_USERTABLE, 
     Key: { 
     accountid: event.accountid, 
     } 
    }; 
    docClient.get(params, function(err, data) { 
     if (err) { 
     // console.error("Unable to get an item with the request: ", JSON.stringify(params), " along with error: ", JSON.stringify(err)); 
     return callback(getDynamoDBError(err), null); 
     } else { 
     if (data.Item) { // got response 
      // compose response 
      response = { 
      accountid: data.Item.accountid, 
      username: data.Item.username, 
      email: data.Item.email, 
      role: data.Item.role, 
      }; 
      return callback(null, response); 
     } else { 
      // console.error("Unable to get an item with the request: ", JSON.stringify(params)); 
      return callback(new Error("404 Not Found: Unable to get an item with the request: " + JSON.stringify(params)), null); 
     } 
     } 
    }); 
    } 
    // incomplete parameters 
    else { 
    return callback(new Error("400 Bad Request: Missing parameters: " + JSON.stringify(event)), null); 
    } 
}; 

Вопрос заключается в том, что, как первоначальный DynamoDB вне моего кода лямбда.

Update 2:

ниже код оптимизированной?

Handler.js

let survey = require('./survey'); 
module.exports.handler = (event, context, callback) => { 
    return survey.getOneSurvey({ 
     accountid: event.accountid, 
     surveyid: event.surveyid 
    }, callback); 
}; 

survey.js

let docClient = new aws.DynamoDB.DocumentClient(); 
module.exports = (() => { 
    const getOneSurvey = (event, callback) {.... 
     docClient.get(params, function(err, data)... 
     .... 
    }; 

    return{ 
    getOneSurvey : getOneSurvey, 
    } 
})(); 
+0

* «Под оптимизированным кодом?» * Я бы сказал «нет», а не в соответствии с этим правилом. Каждый раз, когда вызывается «обработчик», «обследование».getOneSurvey() ', и каждый раз, когда это происходит, вы создаете новый' aws.DynamoDB.DocumentClient'. Это нужно присваивать переменной соответствующей области только один раз, когда ваш исходный код загружается, а не каждый раз при вызове обработчика. –

+0

OK! Я помещаю docClient вне module.exports. Сначала он загрузит и создаст только один docClient. Я правильно понял? – Jim

ответ

6

Вот цитата вопрос:

Инициализировать внешние услуги за пределами вашего кода Lambda

При использовании сервисов (например, DynamoDB) убедитесь, что вы инициализировали вне вашего лямбда-кода. Пример: инициализатор модуля (для узла) или статический конструктор (для Java). Если вы инициируете соединение с DDB внутри функции Lambda, этот код будет запускаться при каждом вызове.

Иными словами, в том же файле, но за пределами - до - фактического кода обработчика.

let docClient = new aws.DynamoDB... 
... 
const getOneUser = (event, callback) => { 
.... 
    docClient.get(params, ... 

Когда контейнер запускается, выполняется код вне обработчика. Когда последующие вызовы функций повторно используют один и тот же контейнер, вы сохраняете ресурсы и время, не повторяя внешние службы снова. Контейнеры часто используются повторно, но каждый контейнер обрабатывает только один одновременный запрос за раз, и как часто они используются повторно и как долго вы находитесь за пределами вашего контроля ... Если вы не обновите эту функцию, в этом случае любые существующие контейнеры больше не будут повторно используются, потому что у них будет старая версия функции.

Ваш код будет работать как написано, но не оптимизировано.

Предостережение с таким подходом, которое возникает в текущем поколении Node.js Лямбда-функции (Node 4.x/6.x), заключается в том, что некоторые объекты, в частности те, которые создают литеральные постоянные соединения с внешними службами, цикл событий становится пустым (типичным примером является соединение с базой данных mysql, которое поддерживает прямое TCP-соединение с сервером, а наоборот, соединение «ДинамоДБ» на самом деле не требует установления соединения, поскольку это транспортный протокол HTTPS). В этом случае перед замораживанием контейнера необходимо либо выполнить другой подход, либо allow lambda to not wait for an empty event loop, установив context.callbackWaitsForEmptyEventLoop на номер false перед вызовом обратного вызова ... но только при необходимости, и только если вы полностью поймете, что это значит. Установка по умолчанию, потому что какой-то парень в Интернете сказал, что это хорошая идея, потенциально принесет вам загадочные ошибки, позже.

+0

Спасибо за прекрасный ответ! Я обновил свой вопрос! – Jim

+0

Как насчет тестирования и насмешки? Я использую 'aws-sdk-mock', и там вы можете найти: _The AWS-сервис должен быть инициализирован внутри тестируемой функции, чтобы метод SDK был изделен_. Поэтому, чтобы заставить это работать, мне пришлось перемещать 'var dynamoDb = AWS.DynamoDB();' inside 'export.handler = function (event, context) {' [См. Их пример 2] (https: // www .npmjs.com/package/aws-sdk-mock) – iaforek

+0

@iaforek * prima facie *, это действительно похоже на проблему, потому что это не приведет к оптимальному дизайну, если код написан таким образом. Ясно (!?) Накладные расходы на инициализацию объекта при каждом выполнении функции обработчика менее эффективны, чем выполнение его только один раз для каждого контейнера. –

Смежные вопросы