Cum să construiți aplicația Golang conectabilă și să beneficiați de straturile Lambda AWS.

Golang - de ce merită atenția ta?

Golang este un limbaj de programare open source conceput și implementat de Google. Este foarte utilizat pe scară largă în aplicații moderne, în special în cloud. Cele mai caracteristice caracteristici sunt:

  • Golang este scris tipic - oferă o mai mică flexibilitate, dar vă protejează de a greși,
  • Nu este orientat pe obiecte. Cu toate acestea, puteți crea structuri și interfețe și asta vă oferă 3 din 4 principii OOP: abstractizarea datelor, încapsularea și polimorfismul. Moștenirea este singura care lipsește,
  • Goroutines! - cea mai mare implementare a firelor ușoare pe care le-am folosit vreodată. Vă permite să creați un fir nou în modul super ușor folosind operatorul go și să comunicați între diferite goroutine folosind canale,
  • Compilează la binarul unic cu toate dependențele - nu mai există conflicte de pachete!

Personal, consider Golangul ca fiind cea mai mare limbă pe care o folosesc zilnic. Cu toate acestea, acest articol nu va fi despre crearea primei funcții sau imprimarea „Hello World”. Îți voi arăta ceva mai avansat. Dacă sunteți începători și doriți să aflați mai multe despre Golang, vizitați pagina principală.

AWS Lambda & Golang

AWS Lambda este unul dintre cele mai populare servicii de calcul fără server din cloud public, lansat în noiembrie 2014 de Amazon Web Services. Vă permite să rulați codul dvs. ca răspuns la evenimentele precum dinamocatoarele DynamoDB, SNS sau HTTP, fără a furniza sau gestiona servere! Știți ce este cu adevărat grozav? Din ianuarie 2018, sprijină runtime Golang. Lucrul cu AWS Lambda este într-adevăr simplu - pur și simplu încărcați un pachet cu fermoar cu codul dvs. și toate dependențele (binar unic atunci când utilizați Golang).

Transmite rapid, 4 ani mai târziu la 2018 re: Invent AWS lansează Lambda Layers care vă permite să stocați și să gestionați date care sunt partajate pe diferite funcții în conturile AWS unice sau chiar multiple! De exemplu, în timp ce utilizați Python puteți pune toate dependențele într-un strat suplimentar care poate fi folosit ulterior de alte Lambdas. Nu mai este nevoie să puneți dependențe diferite în fiecare pachet cu fermoar! În lumea Golang, situația este diferită, deoarece AWS Lambda necesită să încărcați un document binar. Cum putem beneficia de straturile Lambda AWS? Răspunsul este simplu - construiți o aplicație modulară folosind plug-uri Golang!

Pluginuri Golang - o modalitate de a construi o aplicație modulară

Golang Plugins este caracteristica lansată în Go1.8 care vă permite să încărcați dinamic bibliotecile partajate (fișiere .so). Vă oferă posibilitatea de a exporta o parte din codul dvs. în biblioteca separată sau de a folosi pluginul pregătit și compilat de altcineva. Este promițător, însă, există câteva limitări:

  • Pluginul dvs. trebuie să fie un singur modul principal,
  • Puteți încărca doar funcții și variabile care sunt exportate ca simboluri ELF,
  • Datorită tastării statice, trebuie să aruncați fiecare simbol încărcat la tipul corect. În cel mai rău scenariu, trebuie să definiți interfața corectă din codul dvs.,
  • Funcționează numai pentru Linux și MacOS. Personal, nu consider asta ca un dezavantaj :)

Construirea și testarea primului dvs. plugin

Acum creăm primul nostru plugin. Ca exemplu, vom crea un modul simplu pentru criptarea șirurilor. Să revenim la noțiuni de bază și să punem în aplicare 2 algoritmi de criptare simplă - Ceasar și Verman.

  • Criptarea Cezar este algoritmul folosit în primul rând de Julius Ceases. Schimbă fiecare literă din text după numărul fix de poziții. De exemplu, dacă doriți să criptați cuvântul golang cu cheia 4, veți primi ktpek. Decriptarea funcționează în același mod. Trebuie doar să schimbați literele în direcția opusă.
  • Criptarea Verman este similară cu Ceaser, pe baza aceleiași idei de schimbare, diferența este că mutați fiecare literă după numărul diferit de poziții. Pentru a decripta textul, trebuie să aveți cheia care conține pozițiile utilizate pentru criptarea textului. De exemplu, dacă doriți să criptați cuvântul golang cu tasta [-1, 4, 7, 20, 4, -2] veți obține viitor.

Implementarea completă a acestui exemplu este disponibilă aici.

Implementarea plugin-urilor

Următorul fragment conține implementarea celor doi algoritmi menționați mai sus. Pentru fiecare implementăm 2 metode de criptare și decriptare a textului nostru:

După cum vedeți, am exportat aici 3 simboluri diferite (Golang exportă doar acești identificatori care începe cu litera superioară):

  • EncryptCeasar - șir func (int, string) care criptează textul folosind algoritmul Ceasar,
  • DecryptCeaser - șir func (int, string) care decriptează textul folosind algoritmul Caeser,
  • VermanCipher - variabilă de tip vermanCipher care implementează 2 metode: Encrypt: func (string) string și Decrypt: func () (* string, eroare)

Pentru a compila acest plugin, trebuie să executați următoarea comandă:

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

Deocamdată, nu există nimic special - puține funcții simple au fost create și un modul a fost compilat ca un plugin prin adăugarea argumentului -buildmode = plugin.

Plugin de încărcare și testare

Distracția începe atunci când vrem să folosim pluginul compilat în aplicația noastră. Să creăm un exemplu simplu:

În primul rând, trebuie să importați pachetul de plug-uri Golang. Conține doar două funcții - prima este pentru încărcarea bibliotecii partajate, iar cea de-a doua pentru găsirea unui simbol exportat. Pentru a încărca biblioteca, trebuie să utilizați funcția Open, care necesită furnizarea căii către pluginul partajat și returnarea variabilei de tipul Plugin Dacă încărcarea bibliotecii nu este posibilă (ex. Calea incorectă sau fișierul corupt) această funcție returnează eroarea care trebuie gestionată.

Următorul pas este să încărcați fiecare simbol exportat folosind metoda Căutare. Un ușor inconvenient este că trebuie să încărcați fiecare funcție exportată separat. Cu toate acestea, puteți combina mai multe funcții împreună în același mod în care a fost făcut pentru simbolul VermanCipher. După ce ai încărcat toate simbolurile pe care vrei să le folosești, trebuie să le arunci la tipul corect. Golang este un limbaj scris tipic, astfel încât nu există nici o altă modalitate de a utiliza aceste simboluri fără turnare. Amintiți-vă, când exportați o variabilă care implementează câteva metode, trebuie să o jucați la tipul corect de interfață (a trebuit să definesc interfața EncryptionEngine pentru a o gestiona). \ Newline \ newline

Pentru a compila și rula aplicația folosiți următoarea comandă:

du-te construi app.go
./app

În ieșire, ar trebui să vedeți textul criptat și decriptat ca o dovadă că algoritmul funcționează corect.

Utilizați plugin-ul în AWS lambda

Pentru a utiliza pluginul nostru în AWS Lambda, trebuie să facem câteva modificări în aplicația noastră:

  • AWS Lambda montează straturi în directorul / opt din containerul lambda, așa că trebuie să încărcăm pluginul nostru din acest director.
  • Trebuie să creăm o funcție de handler care va fi utilizată de motorul Lambda pentru a gestiona evenimentul nostru de testare.

Următorul fragment conține aplicația noastră ajustată pentru a fi folosită de Lambda:

După cum vedeți, implementarea este foarte similară cu cea anterioară. Am schimbat doar directorul din care ne-am încărcat pluginul și am adăugat răspunsul funcției în loc să imprimăm valorile. Dacă doriți să aflați mai multe despre scrierea Lambdas în golang, verificați documentația AWS.

Desfășurarea AWS Lambda

Există două moduri de implementare a funcțiilor și straturilor AWS Lambda. Puteți crea și încărca manual pachetul cu fermoar sau puteți utiliza cadrul mai avansat, ceea ce îl face mult mai ușor și mai rapid. Pentru majoritatea proiectelor mele, folosesc cadrul Serverless, așa că am pregătit deja fișierul simplu de configurare serverless.yml folosind acest instrument:

service: cipherService
frameworkVersion: "> = 1.28.0 <2.0.0"
furnizor de:
  nume: aws
  runtime: go1.x
straturi:
  cipherLayer:
    calea: bin / plugin
    compatibleRuntimes:
      - go1.x
funcţii:
  motor:
    handler: bin / cipherEngine
    pachet:
      exclude:
        - ./**
      include:
        - ./bin/cipherEngine
    straturi:
      - {Ref: CipherLayerLambdaLayer}

În secțiunea straturi am definit un singur strat cu calea către pluginul deja creat - acesta va fi implementat împreună cu funcția lambda. Puteți defini până la 5 straturi diferite, ordinea fiind foarte importantă. Acestea sunt montate în același director / opțiune, astfel încât straturile cu numărul mai mare pot înlocui fișierele din straturile montate anterior. Pentru fiecare strat, trebuie să furnizați cel puțin 2 parametri: calea către directorul care conține sursa stratului (calea către pluginul binar în cazul dvs.) și lista de rulări compatibile.

Următoarea secțiune de funcții este un loc unde definiți lista funcțiilor care urmează să fie implementate. Pentru fiecare funcție, trebuie să furnizați cel puțin calea către aplicația compilată. În plus, trebuie să definim parametrul de straturi cu referința la stratul definit mai sus. Aceasta va atașa automat stratul la funcția noastră Lambda în timpul desfășurării. Lucrul amuzant este că trebuie să convertiți numele stratului lambda pentru a fi TitleCased și adăugați sufixul LambdaLayer dacă doriți să faceți referire la respectiva resursă. Se pare că echipa Serverless a implementat-o ​​în acest mod pentru a rezolva conflictul cu referire la diferitele tipuri de resurse.

După ce fișierul nostru de configurare serverless.yml este gata, ultimul lucru de făcut este să compilăm aplicația, pluginul și să o implementăm. Putem folosi Makefile simple pentru asta:

.PHONY: build buildPlugin implementare curată
construi:
 dep asigura -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
curat:
 rm -rf ./bin ./vendor Gopkg.lock
implementare: build cleanPlugin build
 sls deploy --verbose

Puteți crea și implementa funcția dvs. rulând următoarea comandă:

face implementare

Test AWS Lambda

După cum am menționat anterior, AWS Lambda execută cod în răspunsul la eveniment. Cu toate acestea, nu am configurat niciun declanșator de eveniment, deci nu va fi invocat fără ajutorul nostru. Trebuie să o facem manual folosind cadrul Serverless sau instrumentul awscli:

sls invoca -f nume_funcție
aws lambda invoke - nume-funcție nume_ funcție ieșire_file

În răspuns, ar trebui să vedeți aceeași ieșire ca înainte, ceea ce dovedește că funcția noastră lambda funcționează corect și încarcă pluginul din stratul suplimentar. Acum puteți crea alte funcții care vor utiliza același strat sau chiar îl vor partaja cu alte conturi AWS.

rezumat

A fost foarte distractiv să folosești module Golang și să testezi cum să le integrezi cu noul lansat AWS Lambda Layers. Biblioteca de pluginuri este într-adevăr minunată, însă datorită limitărilor și specificațiilor Golang, poate fi utilizată doar în anumite scenarii speciale. Cred că pentru majoritatea dezvoltatorilor care lucrează la proiectele standard, nu va fi nevoie sau chiar posibil să utilizeze pluginuri. Doar două motive îmi vin în minte:

  • Implementarea unor algoritmi complicate care pot fi utilizate de celelalte aplicații ex. algoritmi de codare video sau de criptare.
  • Împărtășirea algoritmului cu alții fără publicarea codului său.