Jak vytvořit zásuvnou Golang aplikaci a těžit z AWS Lambda Layers.

Golang - proč to stojí za pozornost?

Golang je programovací jazyk s otevřeným zdrojovým kódem navržený a implementovaný společností Google. Je velmi široce používán v moderních aplikacích, zejména v cloudu. Nejcharakterističtějšími rysy jsou:

  • Golang je staticky napsaný - poskytuje menší flexibilitu, ale chrání vás před chybami,
  • Není objektově orientovaný. Můžete však vytvořit struktury a rozhraní, což vám poskytne 3 ze 4 zásad OOP: abstrakce dat, zapouzdření a polymorfismus. Dědictví je jediné, které chybí,
  • Goroutiny! - největší implementace lehkých vláken, jaké jsem kdy použil. To vám umožní vytvořit nový vlákno v super snadným způsobem pomocí go operátora a komunikovat mezi různými goroutiny pomocí kanálů,
  • Zkompiluje se do jediného binárního kódu se všemi závislostmi - žádné konflikty dalších balíčků!

Osobně považuji Golang za největší jazyk, který denně používám. Tento článek se však nebude týkat vytvoření vaší první funkce nebo tisku „Hello World“. Ukážu vám trochu pokročilejší věci. Pokud jste začátečník a chcete se dozvědět více o Golangu, navštivte jeho hlavní stránku.

AWS Lambda & Golang

AWS Lambda je jednou z nejpopulárnějších výpočetních služeb bez serverů ve veřejném cloudu, kterou v listopadu 2014 vydala společnost Amazon Web Services. To vám umožní spustit váš kód v reakci na události, jako je dynamoDB, SNS nebo HTTP triggery, aniž by provizorní nebo správu serverů! Víte, co je opravdu skvělé? Od ledna 2018 podporuje běhový systém Golang. Práce s AWS Lambda je opravdu jednoduchá - stačí nahrát balíček se zipem s vaším kódem a všemi závislostmi (jeden binární při použití Golang).

Rychlý posun vpřed, o 4 roky později v roce 2018: Invent AWS vydává vrstvy Lambda, které vám umožňují ukládat a spravovat data, která jsou sdílena mezi různými funkcemi v jednom nebo více účtech AWS! Například, když používáte Python, můžete umístit všechny závislosti do další vrstvy, kterou mohou později použít i jiné Lambdy. V každém balíčku se zipem již nemusíte dávat různé závislosti! Ve světě Golang je situace jiná, protože AWS Lambda vyžaduje, abyste nahráli kompilovaný binární soubor. Jak můžeme těžit z vrstev AWS Lambda Layers? Odpověď je jednoduchá - vytvořte modulární aplikaci pomocí Golang Plugins!

Golang Pluginy - způsob, jak vytvořit modulární aplikaci

Golang Plugins je funkce vydaná v Go1.8, která vám umožňuje dynamicky načítat sdílené knihovny (soubory .so). To vám dává možnost exportovat část kódu do samostatné knihovny nebo použít plugin připravený a kompilovaný někým jiným. Je to slibné, existuje však několik omezení:

  • Váš Plugin musí být jeden hlavní modul,
  • Můžete načíst pouze funkce a proměnné, které jsou exportovány jako symboly ELF,
  • Kvůli statickému psaní musíte přetypovat každý načtený symbol na správný typ. V nejhorším případě musíte v kódu definovat správné rozhraní,
  • Funguje to pouze pro Linux a MacOS. Osobně to nepovažuji za nevýhodu :)

Vytvoření a testování prvního pluginu

Nyní vytvořme náš první plugin. Jako příklad vytvoříme jednoduchý modul pro šifrování řetězců. Vraťme se k základům a implementujeme 2 jednoduché šifrovací algoritmy - Ceasar a Verman.

  • Caesarova šifra je algoritmus, který poprvé použil Julius Ceases. Posune každé písmeno v textu o pevný počet pozic. Například, pokud chcete zašifrovat slovo golang klíčem 4, dostanete ktpek. Dešifrování funguje stejným způsobem. Musíte pouze posunout písmena opačným směrem.
  • Vermanova šifra je podobná Ceaserovi, na základě stejného nápadu na posun je rozdíl v tom, že posunete každé písmeno o jiný počet pozic. K dešifrování textu potřebujete klíč obsahující pozice použité k zašifrování textu. Pokud například chcete zašifrovat slovo golang klíčem [-1, 4, 7, 20, 4, -2], dostanete budoucnost.

Úplné provedení tohoto příkladu je k dispozici zde.

Implementace pluginu

Následující úryvek obsahuje implementaci výše uvedených dvou algoritmů. Pro každý z nich implementujeme 2 způsoby šifrování a dešifrování našeho textu:

Jak vidíte, exportovali jsme zde 3 různé symboly (Golang exportuje pouze tyto identifikátory začínající velkým písmenem):

  • EncryptCeasar - func (int, string) řetězec, který šifruje text pomocí Ceasarova algoritmu,
  • DecryptCeaser - func (int, string) řetězec, který dešifruje text pomocí Caeserova algoritmu,
  • VermanCipher - proměnná typu vermanCipher implementující 2 metody: Encrypt: func (string) string a Decrypt: func () (* string, error)

Chcete-li zkompilovat tento plugin, musíte spustit následující příkaz:

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

Prozatím není nic zvláštního - bylo vytvořeno několik jednoduchých funkcí a modul byl kompilován jako plugin přidáním argumentu -buildmode = plugin.

Načíst a vyzkoušet plugin

Zábava začíná, když chceme v naší aplikaci použít kompilovaný plugin. Vytvořme jednoduchý příklad:

Nejprve musíte importovat balíček pluginu golang. Obsahuje pouze dvě funkce - první je pro načtení sdílené knihovny a druhá pro nalezení exportovaného symbolu. Chcete-li načíst knihovnu, musíte použít funkci Otevřít, která vyžaduje poskytnutí cesty ke sdílenému zásuvnému modulu a vrací proměnnou typu Plugin. Pokud načítání knihovny není možné (např. Nesprávná cesta nebo poškozený soubor), vrátí tato funkce chybu, která musí být zpracována.

Dalším krokem je načtení každého exportovaného symbolu pomocí metody vyhledávání. Nepatrnou nepříjemností je, že musíte každou exportovanou funkci načíst zvlášť. Můžete však kombinovat více funkcí stejným způsobem, jako tomu bylo u symbolu VermanCipher. Jakmile načtete všechny symboly, které chcete použít, musíte je přetypovat na správný typ. Golang je staticky psaný jazyk, takže neexistuje žádný jiný způsob, jak tyto symboly použít bez obsazení. Pamatujte, že když exportujete proměnnou, která implementuje několik metod, musíte ji přetypovat na správný typ rozhraní (k tomu jsem musel definovat šifrovací rozhraníEngine). \ Newline \ newline

Pro kompilaci a spuštění aplikace použijte následující příkaz:

jít sestavit app.go
./aplikace

Ve výstupu byste měli vidět šifrovaný a dešifrovaný text jako důkaz, že algoritmus pracuje správně.

Použijte plugin v AWS lambda

Chcete-li použít náš plugin v AWS Lambda, musíme provést několik úprav v naší aplikaci:

  • AWS Lambda připojuje vrstvy do adresáře / opt v kontejneru lambda, takže musíme z tohoto adresáře načíst náš plugin.
  • Potřebujeme vytvořit funkci obsluhy, kterou bude motor Lambda používat při zpracování naší testovací události.

Následující úryvek obsahuje naši aplikaci upravenou pro použití v Lambdě:

Jak vidíte, implementace je velmi podobná předchozí. Změnili jsme pouze adresář, ze kterého jsme načtili náš plugin, a místo tiskových hodnot jsme přidali funkční odezvu. Pokud se chcete dozvědět více o psaní Lambdas v golang, podívejte se do dokumentace AWS.

Nasazení AWS Lambda

Existují dva způsoby nasazení funkcí a vrstev AWS Lambda. Balíček se zipem můžete vytvořit a nahrát ručně nebo použít pokročilejší rámec, což je mnohem jednodušší a rychlejší. Pro většinu svých projektů používám framework Serverless, takže jsem již připravil jednoduchý konfigurační soubor serverless.yml pomocí tohoto nástroje:

služba: cipherService
frameworkVersion: "> = 1.28.0 <2.0.0"
poskytovatel:
  jméno: aws
  runtime: go1.x
vrstvy:
  cipherLayer:
    cesta: bin / plugin
    kompatibilníRuntimes:
      - go1.x
funkce:
  motor:
    popisovač: bin / cipherEngine
    balík:
      vyloučit:
        - ./**
      zahrnout:
        - ./bin/cipherEngine
    vrstvy:
      - {Ref: CipherLayerLambdaLayer}

V sekci vrstvy jsme definovali jednu vrstvu s cestou k již vytvořenému pluginu - bude nasazen společně s funkcí lambda. Můžete definovat až 5 různých vrstev, jejichž pořadí je opravdu důležité. Jsou připojeny ke stejnému adresáři / opt, takže vrstvy s vyšším počtem mohou přepsat soubory z dříve připojených vrstev. Pro každou vrstvu musíte zadat alespoň 2 parametry: cestu k adresáři obsahujícímu zdroj vrstvy (cesta k binárnímu pluginu ve vašem případě) a seznam kompatibilních runtime.

Další část funkcí je místo, kde můžete definovat seznam funkcí, které mají být nasazeny. Pro každou funkci musíte poskytnout alespoň cestu ke kompilované aplikaci. Kromě toho musíme definovat parametr vrstvy s odkazem na vrstvu definovanou výše. Během nasazení se vrstva automaticky připojí k naší funkci Lambda. Legrační je, že musíte převést název vrstvy lambda na název TitleCased a přidat příponu LambdaLayer, pokud se chcete na tento zdroj odkazovat. Zdá se, že tým Serverless ho implementoval tímto způsobem, aby vyřešil konflikt s odkazem na různé typy zdrojů.

Jakmile je náš konfigurační soubor serverless.yml připraven, poslední věcí, kterou musíte udělat, je zkompilovat naši aplikaci, plugin a nasadit ji. K tomu můžeme použít jednoduchý Makefile:

.PHONY: build buildPlugin čisté nasazení
stavět:
 dep zajistit -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
čistý:
 rm -rf ./bin ./vendor Gopkg.lock
nasadit: clean buildPlugin build
 sls nasadit - verbose

Funkci můžete vytvořit a nasadit spuštěním následujícího příkazu:

provést nasazení

Vyzkoušejte AWS Lambda

Jak jsem již zmínil dříve, AWS Lambda v reakci na událost provede kód. Nenastavili jsme však žádné spouštěče událostí, takže nebude vyvoláno bez naší pomoci. Musíme to udělat ručně pomocí frameworku bez serveru nebo nástroje awscli:

sls invoke -f function_name
aws lambda invoke - název-funkce název_výstupu výstupní_soubor

V odpovědi byste měli vidět stejný výstup jako dříve, což dokazuje, že naše funkce lambda funguje správně a načte plugin z další vrstvy. Nyní můžete vytvořit další funkce, které budou používat stejnou vrstvu nebo je dokonce sdílet s jinými účty AWS.

souhrn

Bylo hodně legrace používat moduly Golang a otestovat, jak je integrovat do nově vydaných vrstev AWS Lambda Layers. Knihovna pluginů je opravdu úžasná, ale vzhledem ke svým omezením a specifikaci Golang ji lze použít pouze v některých zvláštních scénářích. Domnívám se, že pro většinu vývojářů, kteří pracují na standardních projektech, nebude nutné ani možné používat pluginy. Připadají mi jen dva důvody:

  • Implementace komplikovaných algoritmů, které mohou být použity jinými aplikacemi ex. algoritmy kódování videa nebo šifrování.
  • Sdílení algoritmu s ostatními bez zveřejnění jeho kódu.