Comment créer une application Golang enfichable et bénéficier des couches AWS Lambda.

Golang - pourquoi vaut-il votre attention?

Golang est un langage de programmation open source conçu et mis en œuvre par Google. Il est très largement utilisé dans les applications modernes, en particulier dans le cloud. Ce sont les caractéristiques les plus caractéristiques:

  • Golang est typé statiquement - il offre moins de flexibilité, mais vous protège contre les erreurs,
  • Il n'est pas orienté objet. Cependant, vous pouvez créer des structures et des interfaces et cela vous donne 3 des 4 principes de POO: abstraction de données, encapsulation et polymorphisme. L'héritage est le seul manquant,
  • Goroutines! - la plus grande implémentation des fils légers que j'utilise. Il vous permet de créer un nouveau fil de manière très simple à l'aide de l'opérateur go et de communiquer entre différents goroutines à l'aide de canaux,
  • Il se compile en un seul binaire avec toutes les dépendances - plus de conflits de packages!

Personnellement, je considère le Golang comme la plus grande langue que j'utilise au quotidien. Cependant, cet article ne portera pas sur la création de votre première fonction ou l'impression de "Hello World". Je vais vous montrer des choses un peu plus avancées. Si vous êtes un débutant et que vous souhaitez en savoir plus sur Golang, veuillez visiter sa page principale.

AWS Lambda & Golang

AWS Lambda est l'un des services de calcul sans serveur les plus populaires dans le cloud public, publié en novembre 2014 par Amazon Web Services. Il vous permet d'exécuter votre code en réponse à des événements tels que les déclencheurs DynamoDB, SNS ou HTTP sans provisionner ni gérer les serveurs! Savez-vous ce qui est vraiment génial? Depuis janvier 2018, il prend en charge l'exécution de Golang. Travailler avec AWS Lambda est vraiment simple - il suffit de télécharger un package zippé avec votre code et toutes les dépendances (binaire unique lors de l'utilisation de Golang).

Avance rapide, 4 ans plus tard à 2018 re: Invent AWS publie Lambda Layers qui vous permet de stocker et de gérer des données partagées entre différentes fonctions dans les comptes AWS uniques ou même multiples! Par exemple, lors de l'utilisation de Python, vous pouvez placer toutes les dépendances dans une couche supplémentaire qui pourra être utilisée ultérieurement par d'autres Lambdas. Il n'est plus nécessaire de mettre des dépendances différentes dans chaque paquet zippé! Dans le monde de Golang, la situation est différente car AWS Lambda vous oblige à télécharger un binaire compilé. Comment pouvons-nous bénéficier des couches AWS Lambda? La réponse est simple: créez une application modulaire à l'aide des plugins Golang!

Plugins Golang - un moyen de construire une application modulaire

Golang Plugins est la fonctionnalité publiée dans le Go1.8 qui vous permet de charger dynamiquement des bibliothèques partagées (fichiers .so). Il vous donne la possibilité d'exporter une partie de votre code vers la bibliothèque séparée ou d'utiliser le plugin préparé et compilé par quelqu'un d'autre. Il est prometteur, cependant, il y a quelques limites:

  • Votre plugin doit être un module principal unique,
  • Vous ne pouvez charger que des fonctions et des variables exportées en tant que symboles ELF,
  • En raison de la saisie statique, vous devez convertir chaque symbole chargé dans le type correct. Dans le pire des cas, vous devez définir la bonne interface dans votre code,
  • Cela ne fonctionne que pour Linux et MacOS. Personnellement, je ne considère pas cela comme un inconvénient :)

Construire et tester votre premier plugin

Créons maintenant notre premier plugin. À titre d'exemple, nous allons créer un module simple pour le cryptage de chaîne. Revenons aux bases et implémentons 2 algorithmes de chiffrement simples - Ceasar et Verman.

  • Le chiffre de César est l'algorithme utilisé en premier par Julius Ceases. Il décale chaque lettre du texte du nombre fixe de positions. Par exemple, si vous souhaitez crypter le mot golang avec la clé 4, vous obtiendrez ktpek. Le décryptage fonctionne de la même manière. Vous avez juste besoin de déplacer les lettres dans la direction opposée.
  • Le chiffre de Verman est similaire au Ceaser, basé sur la même idée de décalage, la différence est que vous décalez chaque lettre selon le nombre différent de positions. Pour décrypter le texte, vous devez avoir la clé contenant les positions utilisées pour crypter le texte. Par exemple, si vous souhaitez crypter le mot golang avec la clé [-1, 4, 7, 20, 4, -2], vous obtiendrez l'avenir.

L'implémentation complète de cet exemple est disponible ici.

Implémentation du plugin

L'extrait suivant contient l'implémentation des deux algorithmes mentionnés ci-dessus. Pour chacun, nous mettons en œuvre 2 méthodes de cryptage et décryptage de notre texte:

Comme vous pouvez le voir, nous avons exporté ici 3 symboles différents (Golang exporte uniquement ces identifiants qui commencent par la lettre supérieure):

  • EncryptCeasar - chaîne func (int, string) qui chiffre le texte en utilisant l'algorithme Ceasar,
  • DecryptCeaser - chaîne func (int, string) qui déchiffre le texte en utilisant l'algorithme Caeser,
  • VermanCipher - variable de type vermanCipher implémentant 2 méthodes: Encrypt: func (string) string et Decrypt: func () (* string, error)

Pour compiler ce plugin, vous devez exécuter la commande suivante:

go build -buildmode = plugin -o plugin / cipher.so plugin / cipher.go

Pour l'instant, il n'y a rien de spécial - peu de fonctions simples ont été créées et un module a été compilé en tant que plugin en ajoutant l'argument -buildmode = plugin.

Charger et tester le plugin

Le plaisir commence lorsque nous voulons utiliser le plugin compilé dans notre application. Créons un exemple simple:

Tout d'abord, vous devez importer le package du plugin golang. Il ne contient que deux fonctions - la première sert à charger la bibliothèque partagée et la seconde à rechercher un symbole exporté. Pour charger votre bibliothèque, vous devez utiliser la fonction Open qui nécessite de fournir le chemin vers votre plugin partagé et retourne une variable de type Plugin. Si le chargement de la bibliothèque n'est pas possible (ex. Chemin incorrect ou fichier corrompu), cette fonction renvoie l'erreur qui doit être gérée.

L'étape suivante consiste à charger chaque symbole exporté à l'aide de la méthode Lookup. Un léger inconvénient est que vous devez charger chaque fonction exportée séparément. Cependant, vous pouvez combiner plusieurs fonctions ensemble de la même manière que pour le symbole VermanCipher. Une fois que vous avez chargé tous les symboles que vous souhaitez utiliser, vous devez les convertir au type correct. Golang est un langage typé statiquement, il n'y a donc pas d'autre moyen d'utiliser ces symboles sans lancer. N'oubliez pas que lorsque vous exportez une variable qui implémente quelques méthodes, vous devez la caster dans le type d'interface correct (j'ai dû définir l'interface encryptionEngine pour gérer cela). \ Newline \ newline

Pour compiler et exécuter l'application, utilisez la commande suivante:

allez construire app.go
./app

Dans la sortie, vous devriez voir le texte chiffré et déchiffré comme une preuve que l'algorithme fonctionne correctement.

Utiliser le plugin dans AWS lambda

Pour utiliser notre plugin dans AWS Lambda, nous devons apporter quelques modifications à notre application:

  • AWS Lambda monte les couches dans le répertoire / opt du conteneur lambda, nous devons donc charger notre plug-in à partir de ce répertoire.
  • Nous devons créer une fonction de gestionnaire qui sera utilisée par le moteur Lambda pour gérer notre événement de test.

L'extrait suivant contient notre application adaptée pour être utilisée par la Lambda:

Comme vous pouvez le voir, l'implémentation est très similaire à la précédente. Nous avons seulement changé le répertoire à partir duquel nous avons chargé notre plugin et ajouté la réponse de fonction au lieu d'imprimer des valeurs. Si vous souhaitez en savoir plus sur l'écriture de Lambdas dans golang, veuillez consulter la documentation AWS.

Déploiement AWS Lambda

Il existe deux façons de déployer des fonctions et des couches AWS Lambda. Vous pouvez créer et télécharger manuellement un package zippé ou utiliser le framework plus avancé, ce qui le rend beaucoup plus facile et plus rapide. Pour la plupart de mes projets, j'utilise le framework Serverless, j'ai donc déjà préparé le fichier de configuration simple serverless.yml en utilisant cet outil:

service: cipherService
frameworkVersion: "> = 1.28.0 <2.0.0"
fournisseur:
  nom: aws
  runtime: go1.x
couches:
  cipherLayer:
    chemin: bin / plugin
    compatibleRuntimes:
      - go1.x
les fonctions:
  moteur:
    gestionnaire: bin / cipherEngine
    paquet:
      exclure:
        - ./**
      comprendre:
        - ./bin/cipherEngine
    couches:
      - {Réf: CipherLayerLambdaLayer}

Dans la section des couches, nous avons défini une seule couche avec le chemin vers le plugin déjà créé - il sera déployé avec la fonction lambda. Vous pouvez définir jusqu'à 5 couches différentes dont l'ordre est vraiment important. Ils sont montés dans le même répertoire / opt, de sorte que les couches avec le nombre le plus élevé peuvent remplacer les fichiers des couches précédemment montées. Pour chaque couche, vous devez fournir au moins 2 paramètres: chemin vers le répertoire contenant la source de la couche (chemin vers le plugin binaire dans votre cas) et la liste des runtimes compatibles.

La section des fonctions suivante est un endroit où vous définissez la liste des fonctions à déployer. Pour chaque fonction, vous devez fournir au moins le chemin d'accès à l'application compilée. De plus, nous devons définir le paramètre des couches avec la référence à la couche définie ci-dessus. Cela attachera automatiquement la couche à notre fonction Lambda pendant le déploiement. Le plus drôle, c'est que vous devez convertir le nom de votre couche lambda en TitleCased et ajouter le suffixe LambdaLayer si vous voulez vous référer à cette ressource. Il semble que l'équipe Serverless l'ait implémenté de cette manière pour résoudre le conflit en référence aux différents types de ressources.

Une fois que notre fichier de configuration serverless.yml est prêt, la dernière chose à faire est de compiler notre application, de le brancher et de la déployer. Nous pouvons utiliser un Makefile simple pour cela:

.PHONY: build buildPlugin clean deploy
construire:
 dep assurer -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 = plugin -o bin / plugin / cipher.so ../plugin/cipher.go
nettoyer:
 rm -rf ./bin ./vendor Gopkg.lock
déploiement: build proprePlugin build
 sls deploy --verbose

Vous pouvez créer et déployer votre fonction en exécutant la commande suivante:

faire déployer

Testez AWS Lambda

Comme je l'ai mentionné précédemment, AWS Lambda exécute du code dans la réponse à l'événement. Cependant, nous n'avons configuré aucun déclencheur d'événement, il ne sera donc pas appelé sans notre aide. Nous devons le faire manuellement en utilisant le framework Serverless ou l'outil awscli:

sls invoque -f nom_fonction
aws lambda invoke - nom_fonction nom_fonction fichier_sortie

Dans la réponse, vous devriez voir la même sortie que précédemment, ce qui prouve que notre fonction lambda fonctionne correctement et charge le plugin à partir de la couche supplémentaire. Vous pouvez maintenant créer d'autres fonctions qui utiliseront la même couche ou même la partager avec d'autres comptes AWS.

Sommaire

C'était très amusant d'utiliser des modules Golang et de tester comment les intégrer aux nouvelles couches AWS Lambda. La bibliothèque de plugins est vraiment géniale, mais en raison de ses limites et de la spécification Golang, elle ne peut être utilisée que dans certains scénarios spéciaux. Je pense que pour la plupart des développeurs qui travaillent sur des projets standard, il ne sera pas nécessaire ni même possible d'utiliser des plugins. Deux raisons me viennent à l'esprit:

  • Implémenter des algorithmes compliqués qui peuvent être utilisés par les autres applications ex. algorithmes de codage vidéo ou de cryptage.
  • Partager votre algorithme avec d'autres sans publier son code.