Slik bygger du pluggbar Golang-applikasjon og drar nytte av AWS Lambda Layers.

Golang - hvorfor er det verdt din oppmerksomhet?

Golang er et open source programmeringsspråk designet og implementert av Google. Det er veldig mye brukt i moderne applikasjoner, spesielt i skyen. Det er de mest karakteristiske funksjonene er:

  • Golang er statisk skrevet - det gir mindre fleksibilitet, men beskytter deg mot å gjøre feil,
  • Det er ikke objektorientert. Imidlertid kan du lage strukturer og grensesnitt, og det gir deg 3 av 4 OOP-prinsipper: datainnsamling, innkapsling og polymorfisme. Arv er den eneste som mangler,
  • Goroutines! - den største implementeringen av lystrådene jeg noen gang har brukt. Den lar deg lage en ny tråd på en superenkelig måte ved hjelp av go operator og kommunisere mellom forskjellige goroutiner ved hjelp av kanaler,
  • Den samles til den ene binæren med alle avhengigheter - ikke flere pakker konflikter!

Personlig anser jeg Golang som det største språket jeg bruker til daglig. Imidlertid handler ikke denne artikkelen om å lage din første funksjon eller skrive ut "Hello World". Jeg vil vise deg litt mer avanserte ting. Hvis du er nybegynner og vil lære mer om Golang, kan du gå til hovedsiden.

AWS Lambda & Golang

AWS Lambda er en av de mest populære serverløse datatjenestene i den offentlige skyen, utgitt i november 2014 av Amazon Web Services. Den lar deg kjøre koden din som svar på hendelsene som DynamoDB, SNS eller HTTP-triggere uten å tilby eller administrere servere! Vet du hva som virkelig er flott? Siden januar 2018 støtter den Golang runtime. Å jobbe med AWS Lambda er virkelig enkelt - bare last opp en glidelås pakke med koden og alle avhengigheter (enkelt binært når du bruker Golang).

Spol fremover, 4 år senere på 2018 re: Invent AWS gir ut Lambda Layers som lar deg lagre og administrere data som er delt på tvers av forskjellige funksjoner i de enkelte eller til og med flere AWS-kontoer! For eksempel, mens du bruker Python, kan du legge alle avhengigheter i et ekstra lag som senere kan brukes av andre Lambdas. Det er ikke nødvendig å legge forskjellige avhengigheter i hver glidelås pakke lenger! I Golang er verdenssituasjonen annerledes, ettersom AWS Lambda krever at du laster opp kompilert binær. Hvordan kan vi dra nytte av AWS Lambda Layers? Svaret er enkelt - bygg en modulær applikasjon ved hjelp av Golang Plugins!

Golang Plugins - en måte å bygge en modulær applikasjon på

Golang Plugins er funksjonen utgitt i Go1.8 som lar deg dynamisk laste delte biblioteker (.so filer). Det gir deg en mulighet til å eksportere noe av koden din til det separate biblioteket eller bruke plugin som er utarbeidet og satt sammen av noen andre. Det er lovende, men det er noen begrensninger:

  • Plugin-en din må være én hovedmodul,
  • Du kan bare laste inn funksjoner og variabler som blir eksportert som ELF-symboler,
  • På grunn av statisk inntasting må du kaste hvert lastet symbol til riktig type. I det verste scenariet må du definere riktig grensesnitt i koden,
  • Det fungerer bare for Linux og MacOS. Personlig anser jeg ikke dette som en ulempe :)

Bygge og teste din første plugin

La oss nå lage vår første plugin. Som et eksempel vil vi lage en enkel modul for strengkryptering. La oss gå tilbake til det grunnleggende og implementere to enkle krypteringsalgoritmer - Ceasar og Verman.

  • Caesar-chiffer er algoritmen som Julius Cease først har brukt. Den forskyver hver bokstav i teksten etter det faste antall stillinger. For eksempel, hvis du vil kryptere ordet golang med tasten 4, vil du få ktpek. Dekrypteringen fungerer på samme måte. Du trenger bare å flytte bokstavene i motsatt retning.
  • Verman-chiffer er lik Ceaser, basert på den samme skiftende ideen, forskjellen er at du skifter hver bokstav etter forskjellige antall stillinger. For å dekryptere teksten må du ha nøkkelen som inneholder posisjonene som brukes til å kryptere teksten. Hvis du for eksempel vil kryptere ordet golang med tasten [-1, 4, 7, 20, 4, -2], får du fremtid.

Full implementering av dette eksemplet er tilgjengelig her.

Plugin-implementering

Følgende utdrag inneholder implementeringen av de to algoritmene som er nevnt over. For hver enkelt implementerer vi to metoder for å kryptere og dekryptere teksten vår:

Som du ser, eksporterte vi her tre forskjellige symboler (Golang eksporterer bare disse identifikatorene som starter med den store bokstaven):

  • EncryptCeasar - func (int, string) streng som krypterer tekst ved hjelp av Ceasar algoritme,
  • DecryptCeaser - func (int, string) streng som dekrypterer tekst ved hjelp av Caeser-algoritme,
  • VermanCipher - variabel av typen vermanCipher implementerer 2 metoder: Krypter: func (streng) streng og Dekrypter: func () (* streng, feil)

For å kompilere denne pluginen må du kjøre følgende kommando:

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

Foreløpig er det ikke noe spesielt - få enkle funksjoner ble opprettet og en modul ble satt sammen som en plugin ved å legge til -buildmode = plugin-argumentet.

Last inn og test plugin

Moroa begynner når vi vil bruke kompilert plugin i appen vår. La oss lage et enkelt eksempel:

Først må du importere Golang-plugin-pakken. Den inneholder bare to funksjoner - den første er for innlasting av delt bibliotek, og den andre er for å finne et eksportert symbol. For å laste inn biblioteket ditt må du bruke Åpen funksjon som krever å gi banen til den delte plugin og returnere variabel av typen Plugin. Hvis det ikke er mulig å laste inn biblioteket (f.eks. Feil bane eller ødelagt fil), returnerer denne funksjonen feilen som må håndteres.

Neste trinn er å laste inn hvert eksportert symbol ved hjelp av oppslagsmetoden. En liten ulempe er at du trenger å laste hver eksporterte funksjon separat. Du kan imidlertid kombinere flere funksjoner sammen på samme måte som det ble gjort for VermanCipher-symbolet. Når du har lastet alle symbolene du vil bruke, må du kaste dem til riktig type. Golang er et statisk maskinskrevet språk, så det er ingen annen måte å bruke disse symbolene på uten casting. Husk at når du eksporterer en variabel som implementerer noen få metoder, må du kaste den til riktig grensesnitttype (jeg måtte definere krypteringEngine-grensesnitt for å håndtere dette). \ Newline \ newline

For å kompilere og kjøre appen bruker du følgende kommando:

gå og bygg app.go
./app

I utdataene skal du se den krypterte og dekrypterte teksten som et bevis på at algoritmen fungerer riktig.

Bruk plugin i AWS lambda

For å bruke plugin-modulen vår i AWS Lambda, må vi gjøre noen få endringer i applikasjonen vår:

  • AWS Lambda monterer lag til / opt-katalogen i lambda-beholderen, så vi må laste inn plugin-en fra denne katalogen.
  • Vi må lage en behandlingsfunksjon som skal brukes av Lambda-motoren til å håndtere testhendelsen vår.

Følgende utdrag inneholder applikasjonen vår som er justert for å brukes av Lambda:

Som du kan se er implementeringen veldig lik den forrige. Vi har bare endret katalogen som vi lastet inn plugin-en fra, og lagt til funksjonsresponsen i stedet for å skrive ut verdier. Hvis du vil lære mer om å skrive Lambdas in golang, vennligst sjekk AWS-dokumentasjonen.

AWS Lambda-distribusjon

Det er to måter å distribuere AWS Lambda-funksjoner og lag på. Du kan opprette og laste opp en pakket pakke manuelt eller bruke det mer avanserte rammeverket, noe som gjør det mye enklere og raskere. For de fleste av prosjektene mine bruker jeg Serverless framework, så jeg har allerede forberedt den enkle serverless.yml konfigurasjonsfilen ved hjelp av dette verktøyet:

service: cipherService
frameworkVersion: "> = 1.28.0 <2.0.0"
forsørger:
  navn: aws
  kjøretid: go1.x
lag:
  cipherLayer:
    bane: bin / plugin
    compatibleRuntimes:
      - go1.x
funksjoner:
  motor:
    handler: bin / cipherEngine
    pakke:
      utelukke:
        - ./**
      inkludere:
        - ./bin/cipherEngine
    lag:
      - {Ref: CipherLayerLambdaLayer}

I lagdelene definerte vi et enkelt lag med banen til den allerede opprettede plugin - det vil bli distribuert sammen med lambda-funksjonen. Du kan definere opptil 5 forskjellige lag hvilken rekkefølge som er veldig viktig. De er montert i den samme / opt-katalogen, slik at lag med høyere antall kan overstyre filer fra de tidligere monterte lagene. For hvert lag må du oppgi minst to parametere: bane til katalogen som inneholder lagkilde (bane til plugin-binær i ditt tilfelle) og listen over kompatible driftstider.

Den neste funksjonsdelen er et sted der du definerer listen over funksjonene som skal distribueres. For hver funksjon må du oppgi minst banen til den kompilerte applikasjonen. I tillegg må vi definere lagparameteren med referanse til laget definert over. Dette vil automatisk feste laget til vår Lambda-funksjon under utplasseringen. Det morsomme er at du må konvertere lambda-lagnavnet til å være TitleCased og legge til LambdaLayer-suffikset hvis du vil henvise til den ressursen. Det ser ut til at Serverless-teamet implementerte det på denne måten for å løse konflikten med referanse til forskjellige ressurser.

Når vår serverless.yml-konfigurasjonsfil er klar, er den siste tingen å gjøre å kompilere appen vår, plugin og distribuere den. Vi kan bruke enkel Makefile for det:

.PHONY: build buildPlugin ren distribusjon
bygge:
 dep sikre -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
ren:
 rm -rf ./bin ./vendor Gopkg.lock
distribuere: clean buildPlugin build
 sls distribuere - verbose

Du kan bygge og distribuere funksjonen din ved å kjøre følgende kommando:

gjøre distribuere

Test AWS Lambda

Som jeg nevnte tidligere kjører AWS Lambda kode som svar på hendelsen. Vi konfigurerte imidlertid ingen hendelsesutløsere, så den vil ikke bli påberopt uten vår hjelp. Vi må gjøre det manuelt ved å bruke det serverløse rammeverket eller awscli-verktøyet:

sls påkalle -f funksjonsnavn
aws lambda påkalle - funksjonsnavn funksjonsnavn output_file

I svaret skal du se den samme utgangen som før, noe som beviser at lambda-funksjonen vår fungerer riktig og laster plugin fra tilleggsjiktet. Nå kan du opprette andre funksjoner som vil bruke det samme laget eller til og med dele det med andre AWS-kontoer.

Sammendrag

Det var mye moro å bruke Golang-moduler og teste hvordan man integrerer dem med de nylig utgitte AWS Lambda Layers. Plugin-biblioteket er virkelig fantastisk, men på grunn av begrensningene og Golang-spesifikasjonen, kan det bare brukes i noen spesielle scenarier. Jeg tror at for de fleste av utviklerne som jobber med standardprosjektene, vil det ikke være nødvendig eller til og med mulig å bruke plugins. Bare to grunner kommer til meg:

  • Implementering av kompliserte algoritmer som kan brukes av de andre applikasjonene eks. videokoding eller krypteringsalgoritmer.
  • Deling av algoritmen din med andre uten å publisere koden.