Статьи

Эксперименты по интеграции (часть 1): Безсерверная платформа

Будучи членом команды доставки Cloud Elements, я вижу много интеграций; как те, которые мы строим сами (от имени клиентов), так и те, которые строят наши клиенты. И часто, думая об этих интеграциях, я также думаю о том, как мы можем сделать их лучше / быстрее / проще / надежнее-э / т. Д.

Меня особенно тянет к легче. В некоторой степени это потому, что я немного ленив (просто спросите мою жену).

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

Есть еще ряд вариантов, таких как AWS Lambdas, Google Cloud Functions и Azure Functions. Cloud Elements даже предлагает наш собственный FaaS — средство графического программирования с низким кодом, называемое Формулы , которое может быть отличным выбором для создания интеграции. Я лично использовал Формулы много раз. Но я программист старой школы, которому действительно нравится код, поэтому я ищу способы сделать его столь же простым для создания и развертывания кода, как и для развертывания Формул.

Одна вещь, которая в последнее время заинтересовала меня, — это Serverless Framework . Serverless Framework — это CLI с открытым исходным кодом для создания и развертывания бессерверных приложений. Он поддерживает ряд различных серверных архитектур и обеспечивает в основном унифицированный способ развертывания и тестирования безсерверных приложений. Это также позволяет расширение через механизм плагина . Поэтому было трудно удержаться от создания специального плагина Cloud Elements, чтобы увидеть, насколько он помог сделать мою жизнь проще. Таким образом, этот эксперимент в интеграции родился.

Затем возник вопрос: «Как я хочу, чтобы это работало?» В Serverless Framework есть концепция ресурсов, которые вы определяете, и она управляет ими за вас. Примеры поддерживаемых ресурсов включают (для AWS) таблицы DynamoDB, сегменты S3 и темы SNS. Казалось разумным использовать эту возможность, добавляя типы для Elements (наша идея соединителя для конкретного поставщика, такого как Salesforce, Marketo или DropBox). Когда вы указываете ресурс в файле конфигурации serverless.yml, плагин будет предоставлять Javascript SDK (используя наш инструмент SDKifier ), который может использоваться кодом для доступа к элементу.

В Serverless Framework также есть концепция событий, которые можно настроить и затем доставить в ваш код. Облачные элементы имеют похожую концепцию событий, которые могут быть доставлены из экземпляра. Плагин настроит конечную точку шлюза API для получения события, а затем подключит правильный URL-адрес после развертывания, чтобы экземпляр вызывал код при возникновении событий.

Пример простой синхронизации контактов с указанием кода и файла конфигурации показан ниже.

service: salesforce-finance-contact-sync

provider:
  name: aws
  runtime: nodejs8.10

plugins:
  - serverless-cloud-elements-plugin

functions:
  sync:
    handler: contactSync.eventHandler
    timeout: 30
    memorySize: 256
    events:
      - instance:
          resource: sfdc

resources:
  Resources:
    sfdc:
      Type: CE::Element::sfdc
      Properties:
        id: ${env:SFDC_ID}
    dest:
      Type: CE::Hub::general
      Properties:
        id: ${env:DEST_ID}
    account:
      Type: CE::Account
      Properties:
        userToken: ${env:USER_TOKEN}
        orgToken: ${env:ORG_TOKEN}
        baseUrl: ${env:BASE_URL}
const {configurator} = require('./configurator');

async function eventHandler() {
  const {trigger, config, done} = configurator(arguments);
  for (let event of trigger.events) {
    const myContact = await config.sfdc.getObjectNameByObjectId_myContact(event.objectId).run();
    if (myContact.Email) {
      let foundContacts = await config.dest.getByObjectName('myContact').where(`Email='${myContact.Email}'`).run();
      if (foundContacts.length === 1) {
        await config.dest.updateObjectNameByObjectId('myContact', foundContacts[0].Id, myContact).run();
        console.log(`${foundContacts[0].Id} updated`);
      } else {
        const newContact = await config.dest.createByObjectName('myContact', myContact).run();
        console.log(`${newContact.Id} created`);
      }
    }
  }
  done();
}

module.exports.eventHandler = eventHandler;

Если вы хотите поэкспериментировать с этим плагином, вы можете скачать его с помощью npm .

У этого подхода есть ограничения, например, максимальное время выполнения составляет около 5 минут для продуктов FaaS, доступных в настоящее время. У меня есть некоторые мысли по поводу адресации, о которых я расскажу в своем следующем посте, озаглавленном, что неудивительно, «Эксперименты в интеграции», часть 2

Пока что я чувствую, что это перспективное направление, хотя YMMV. Я хотел бы услышать ваши мысли о том, что сложно делать интеграции и что вы думаете, может сделать это проще.

Так что я могу украсть твои идеи.

Потому что я ленивый.