Как создать подключаемое приложение Golang и воспользоваться преимуществами AWS Lambda Layers.

Голанг - почему это стоит вашего внимания?

Golang - это язык программирования с открытым исходным кодом, разработанный и реализованный Google. Он очень широко используется в современных приложениях, особенно в облаке. Это наиболее характерные особенности:

  • Голанг имеет статическую типизацию - он обеспечивает меньшую гибкость, но защищает вас от ошибок,
  • Это не объектно-ориентированный. Однако вы можете создавать структуры и интерфейсы, что дает вам 3 из 4 принципов ООП: абстракция данных, инкапсуляция и полиморфизм. Наследование - единственное, чего не хватает,
  • Goroutines! - лучшая реализация легких нитей, которые я когда-либо использовал. Это позволяет вам создать новый поток очень простым способом, используя оператор go, и общаться между различными программами, используя каналы,
  • Он компилируется в один двоичный файл со всеми зависимостями - никаких конфликтов пакетов!

Лично я считаю Голанг величайшим языком, которым я пользуюсь ежедневно. Однако эта статья не будет посвящена созданию вашей первой функции или печати «Hello World». Я покажу вам немного более продвинутые вещи. Если вы новичок и хотите узнать больше о Голанге, пожалуйста, посетите его главную страницу.

AWS Lambda & Golang

AWS Lambda - это одна из самых популярных в общедоступном облаке вычислительных служб без серверов, выпущенная в ноябре 2014 года Amazon Web Services. Это позволяет запускать ваш код в ответ на такие события, как триггеры DynamoDB, SNS или HTTP, без подготовки или управления серверами! Вы знаете, что действительно здорово? С января 2018 года он поддерживает Golang Runtime. Работать с AWS Lambda действительно просто - просто загрузите упакованный пакет с вашим кодом и всеми зависимостями (один двоичный файл при использовании Golang).

Перенесемся через 4 года на 2018 год. Re: Invent AWS выпускает Lambda Layers, который позволяет хранить и управлять данными, которые совместно используются различными функциями в одной или даже нескольких учетных записях AWS! Например, при использовании Python вы можете поместить все зависимости в дополнительный слой, который впоследствии может быть использован другими Lambdas. Больше нет необходимости помещать разные зависимости в каждый zip-пакет! В мире Голанга ситуация иная, так как AWS Lambda требует загрузки скомпилированного двоичного файла. Какую пользу мы можем получить от использования лямбда-слоев AWS? Ответ прост - создайте модульное приложение с помощью плагинов Golang!

Плагины Golang - способ создания модульного приложения

Плагины Golang - это функция, выпущенная в Go1.8, которая позволяет динамически загружать разделяемые библиотеки (файлы .so). Это дает вам возможность экспортировать часть вашего кода в отдельную библиотеку или использовать плагин, подготовленный и скомпилированный кем-то другим. Это многообещающе, однако, есть несколько ограничений:

  • Ваш плагин должен быть одним основным модулем,
  • Вы можете загружать только функции и переменные, которые экспортируются как символы ELF,
  • Из-за статической типизации вы должны привести каждый загруженный символ к правильному типу. В худшем случае вам нужно определить правильный интерфейс в вашем коде,
  • Работает только для Linux и MacOS. Лично я не считаю это недостатком :)

Сборка и тестирование вашего первого плагина

Теперь давайте создадим наш первый плагин. В качестве примера мы создадим простой модуль для шифрования строк. Давайте вернемся к основам и реализуем 2 простых алгоритма шифрования - Ceasar и Verman.

  • Шифр Цезаря - это алгоритм, впервые использованный Юлиусом Цезасом. Он сдвигает каждую букву в тексте на фиксированное количество позиций. Например, если вы хотите зашифровать слово golang ключом 4, вы получите ktpek. Расшифровка работает аналогично. Вам просто нужно сместить буквы в обратном направлении.
  • Верманский шифр похож на Ceaser, основанный на той же идее смещения, разница в том, что вы сдвигаете каждую букву на разное количество позиций. Для расшифровки текста необходим ключ, содержащий позиции, используемые для шифрования текста. Например, если вы хотите зашифровать слово golang с помощью ключа [-1, 4, 7, 20, 4, -2], вы получите будущее.

Полная реализация этого примера доступна здесь.

Реализация плагина

Следующий фрагмент содержит реализацию двух алгоритмов, упомянутых выше. Для каждого мы реализуем 2 метода шифрования и дешифрования нашего текста:

Как видите, мы экспортировали здесь 3 разных символа (Golang экспортирует только эти идентификаторы, которые начинаются с заглавной буквы):

  • EncryptCeasar - строка func (int, string), которая шифрует текст с использованием алгоритма Ceasar,
  • DecryptCeaser - строка func (int, string), которая расшифровывает текст с использованием алгоритма Caeser,
  • VermanCipher - переменная типа vermanCipher, реализующая 2 метода: Encrypt: func (string) string и Decrypt: func () (* string, error)

Чтобы скомпилировать этот плагин, вы должны выполнить следующую команду:

go build -buildmode = плагин -o плагин / cipher.so плагин / cipher.go

На данный момент в этом нет ничего особенного - было создано несколько простых функций, и модуль был скомпилирован как плагин путем добавления аргумента -buildmode = plugin.

Загрузить и протестировать плагин

Веселье начинается, когда мы хотим использовать скомпилированный плагин в нашем приложении. Давайте создадим простой пример:

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

Следующим шагом является загрузка каждого экспортируемого символа с использованием метода Lookup. Небольшое неудобство заключается в том, что вам нужно загружать каждую экспортируемую функцию отдельно. Однако вы можете объединить несколько функций вместе, как это было сделано для символа VermanCipher. Как только вы загрузите все символы, которые хотите использовать, вы должны привести их к правильному типу. Голанг является языком статической типизации, поэтому нет другого способа использовать эти символы без приведения. Помните, что когда вы экспортируете переменную, которая реализует несколько методов, вам нужно привести ее к правильному типу интерфейса (для этого мне нужно было определить интерфейс encryptionEngine). \ Newline \ newline

Для компиляции и запуска приложения используйте следующую команду:

иди строить app.go
./приложение

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

Используйте плагин в AWS лямбда

Чтобы использовать наш плагин в AWS Lambda, нам нужно внести несколько изменений в наше приложение:

  • AWS Lambda монтирует слои в каталог / opt в контейнере lambda, поэтому мы должны загрузить наш плагин из этого каталога.
  • Нам нужно создать функцию-обработчик, которая будет использоваться механизмом Lambda для обработки нашего тестового события.

Следующий фрагмент содержит наше приложение, настроенное для использования Lambda:

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

Развертывание AWS Lambda

Существует два способа развертывания функций и слоев AWS Lambda. Вы можете создавать и загружать сжатые пакеты вручную или использовать более продвинутые рамки, что делает его намного проще и быстрее. Для большинства моих проектов я использую Serverless Framework, поэтому я уже подготовил простой файл конфигурации serverless.yml, используя этот инструмент:

сервис: cipherService
frameworkVersion: "> = 1.28.0 <2.0.0"
поставщик:
  Название: AWS
  время выполнения: go1.x
слои:
  cipherLayer:
    путь: бин / плагин
    compatibleRuntimes:
      - go1.x
функции:
  двигатель:
    обработчик: bin / cipherEngine
    пакет:
      исключить:
        - ./**
      включают:
        - ./bin/cipherEngine
    слои:
      - {Ref: CipherLayerLambdaLayer}

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

Следующий раздел функций - это место, где вы определяете список функций, которые должны быть развернуты. Для каждой функции необходимо указать хотя бы путь к скомпилированному приложению. Кроме того, нам нужно определить параметр layer со ссылкой на слой, определенный выше. Это автоматически прикрепит слой к нашей функции Lambda во время развертывания. Самое смешное, что вам нужно преобразовать имя лямбда-слоя в TitleCased и добавить суффикс LambdaLayer, если вы хотите сослаться на этот ресурс. Похоже, что команда Serverless реализовала это таким образом, чтобы разрешить конфликт со ссылкой на другой тип ресурсов.

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

.PHONY: сборка buildPlugin clean deploy
сборки:
 dep обеспечить -v
 env GOOS = linux go build -ldflags = "- s -w" -o bin / cipherEngine cipherEngine / main.go
buildPlugin:
 env GOOS = linux go build -ldflags = "- s -w" -buildmode = плагин -o bin / plugin / cipher.so ../plugin/cipher.go
чистый:
 rm -rf ./bin ./vendor Gopkg.lock
deploy: чистый buildPlugin build
 sls deploy --verbose

Вы можете создать и развернуть свою функцию, выполнив следующую команду:

сделать развертывание

Тест AWS Lambda

Как я упоминал ранее, AWS Lambda выполняет код в ответ на событие. Однако мы не настроили никаких триггеров событий, поэтому они не будут вызываться без нашей помощи. Мы должны сделать это вручную, используя Serverless Framework или инструмент awscli:

sls вызывает -f имя_функции
aws лямбда-вызов - имя-функции имя_функции output_file

В ответе вы должны увидеть тот же вывод, что и раньше, что доказывает, что наша лямбда-функция работает правильно и загружает плагин из дополнительного слоя. Теперь вы можете создавать другие функции, которые будут использовать тот же слой или даже делиться им с другими учетными записями AWS.

Резюме

Было очень весело использовать модули Golang и тестировать, как интегрировать их с недавно выпущенными лямбда-слоями AWS. Библиотека плагинов действительно потрясающая, однако из-за своих ограничений и спецификации Golang ее можно использовать только в некоторых особых сценариях. Я думаю, что для большинства разработчиков, которые работают над стандартными проектами, не будет необходимости или даже возможности использовать плагины. Мне на ум приходят только две причины:

  • Реализация сложных алгоритмов, которые могут быть использованы другими приложениями напр. алгоритмы кодирования или кодирования видео.
  • Поделитесь своим алгоритмом с другими без публикации его кода.