• Akademia
  • Blog
  • O Serverless
  • O stronie

Amazon EventBridge API Destinations - integracja z RESTowymi endpointami bez funkcji Lambda


Amazon EventBridge API Destinations
Uwielbiam ÔŁĄ´ŞĆ prac─Ö z us┼éug─ů Amazon EventBridge. Nie jest to du┼╝ym zaskoczeniem, gdy┼╝ jest ona uwielbiana przez spo┼éeczno┼Ť─ç. Jednak dla mnie to nie tylko czysta techniczna doskona┼éo┼Ť─ç tego rozwi─ůzania o tym decyduje.

Ilekro─ç my┼Ťl─Ö o EventBridge s┼éysz─Ö w g┼éowie s┼éynne s┼éowa z filmu TRON. Zosta┼éy one nawet ponownie u┼╝yte na samym pocz─ůtku sequela TRON: Legacy.

I tried to picture clusters of information as they moved through the computer.
What do they look like? Ships? Motorcycles?
Were the circuits like freeways?
I kept dreaming of a world I thought IÔÇÖd never see.
And then, one dayÔÇŽ
I got in.

Mimo, ┼╝e s┼éowa te zosta┼éy wypowiedziane o sprz─Öcie komputerowym, a nie o magistrali komunikacyjnej per se, moim zdaniem doskonale si─Ö do niej odnosz─ů.

Za ka┼╝dym razem, gdy pracuj─Ö z EventBridge towarzyszy mi uczucie ekscytacji science-fiction, kt├│re pochodzi z tego filmu.

Mam nadzieję, że Tobie też udzieli się ten vibe po przeczytaniu artykułu!

Czego nauczysz się z artykułu

Ten tutorial nie jest tylko o integracji z Mailchimpem. Powiniene┼Ť go przeczyta─ç, je┼Ťli chcesz dowiedzie─ç si─Ö, jak:

  • skonfigurowa─ç Amazon EventBridge API Destinations, aby wysy┼éa─ç ┼╝─ůdania REST do dowolnego endpointu 3rd party w internecie.
  • u┼╝ywa─ç parametr├│w ┼Ťcie┼╝ki HTTP do uruchamiania r├│┼╝nych endpoint├│w na podstawie tre┼Ťci wiadomo┼Ťci. Jest to bardzo wa┼╝ne, poniewa┼╝ prawie zupe┼énie tego nie wyja┼Ťniono w dokumentacji i nie ma ┼╝adnych przyk┼éad├│w w internecie opisuj─ůcych t─Ö funkcjonalno┼Ť─ç - o ile mi wiadomo jestem pierwszy ­čśë
  • skonfigurowa─ç i wdro┼╝y─ç przyk┼éadowy projekt wykorzystuj─ůcy Serverless Framework, aby ┼éatwo potestowa─ç na w┼é─ůsn─ů r─Ök─Ö na swoim koncie AWS
  • zintegrowa─ç go z Mailchimpem, aby tagowa─ç u┼╝ytkownik├│w na podstawie wiadomo┼Ťci na szynie zdarze┼ä (EventBus).
  • i wreszcie, co zrobi─ç, gdy co┼Ť nie dzia┼éa (jak debugowa─ç integracje API Destinations)?

Tło biznesowe

Ten tutorial jest oparty na moich do┼Ťwiadczeniach podczas wdra┼╝ania integracji API Destinations z Mailchimpem.

Mam ma┼é─ů platform─Ö e-commerce Akademia Serverless Polska, kt├│ra sprzedaje kursy online. Za ka┼╝dym razem, gdy klient kupi kt├│ry┼Ť z produkt├│w, chc─Ö zaznaczy─ç t─Ö informacj─Ö w moim systemie do maili (Email Service Provider - ESP). Moim ESP jest Mailchimp i chc─Ö nada─ç klientowi konkretny tag zwi─ůzany z produktem, aby w przysz┼éo┼Ťci nie wysy┼éa─ç mu promocyjnych e-maili o produktach, kt├│re ju┼╝ posiada. Niestety, moja platforma e-commerce nie jest w stanie tagowa─ç u┼╝ytkownik├│w w Mailchimp, wi─Öc musia┼éem to zaimplementowa─ç samodzielnie.

Oczywi┼Ťcie wykorzysta┼éem serverless i jak zawsze by┼éa to ┼Ťwietna zabawa i du┼╝o nauki ­čśâ

Architektura wysokopoziomowa

Sp├│jrz na poni┼╝szy diagram

Architektura wysokopoziomowa

Pobieranie zam├│wie┼ä z platformy e-commerce jest poza zakresem tego artyku┼éu. Skupimy si─Ö na EventBridge i integracji z Mailichimp za pomoc─ů API Destinations. Zak┼éadam, ┼╝e wiesz jak wys┼éa─ç nowe zdarzenie do custom Event Bus. A jak nie to si─Ö dowiesz ­čśë

Co to jest API Destinations?

API Destinations to stosunkowo nowa funkcjonalno┼Ť─ç Amazon EventBridge, kt├│ra pozwala nam na integracj─Ö z endpointami REST firm trzecich w Internecie bezpo┼Ťrednio bez u┼╝ycia funkcji Lambda!

Wszystko co musisz zrobi─ç, to skonfigurowa─ç us┼éug─Ö zamiast pisa─ç w┼éasny kod. Jak zobaczysz, trzeba napisa─ç sporo CloudFormation. Jednak w por├│wnaniu z w┼éasn─ů implementacj─ů uzyskasz znacznie lepszy efekt.

Ta aktualizacja jest zgodna z pryncypium AWS wygłoszonym przez Chrissa Munnsa podczas re:Invent 2019 używaj funkcji do przekształcania, a nie transportu danych (use functions to transform, not transport).
Chriss Munns podczas re:Invent 2019
I to wyja┼Ťnia ca┼é─ů ide─Ö, kt├│ra za tym stoi. Zostawmy przyziemne zadanie wywo┼éywania 3rd party endpointu AWSowi (transport danych). Wymieniamy kod (w┼éasna implementacja funkcji Lambda) na konfiguracj─Ö us┼éugi. W zamian dostajemy niezawodne rozwi─ůzanie:

  • kt├│re zawsze dzia┼éa
  • kto┼Ť inny bierze za nie odpowiedzialno┼Ť─ç
  • kt├│re jest rozwijane przez najlepszych in┼╝ynier├│w jakich mo┼╝na znale┼║─ç. ­čśâ

Implementacja

W prawdziwym ┼╝yciu nie ma miejsca na klikanie i r─Öczne definiowanie infrastruktury. Profesjonalne projekty wymagaj─ů automatyzacji, powtarzalno┼Ťci, niezawodno┼Ťci i reu┼╝ywalno┼Ťci.

Dlatego w tym artykule zamiast zrzut├│w ekranu z konsoli AWS przedstawi─Ö fragmenty kodu b─Öd─ůc zgodnym z praktyk─ů Infrastructure as Code.

Je┼Ťli jeste┼Ť niecierpliwy, mo┼╝esz ju┼╝ teraz sprawdzi─ç ten przyk┼éadowy projekt na GitHub, kt├│ry zawiera wszystkie ┼║r├│d┼éa. W dalszej cz─Ö┼Ťci artyku┼é wyja┼Ťniam wszystko po kolei.

Komponenty rozwi─ůzania

Szyna zdarzeń - Event Bus

Aby skonfigurowa─ç API Destinations potrzebujemy nasz─ů w┼é─ůsn─ů szyn─Ö zdarze┼ä (custom Event Bus), kt├│ra jest szkieletem naszego rozwi─ůzania. Jest ona prosta do zdefiniowania za pomoc─ů CloudFormation.

1
2
3
4
EventBus:
Type: AWS::Events::EventBus
Properties:
Name: ${self:service}-${self:provider.stage}

Obie zmienne ${self:service} oraz ${self:provider.stage} pochodz─ů z Serverless Framework (SF). Pozw├│lcie, ┼╝e wyja┼Ťni─Ö, dla tych z Was, kt├│rzy nie s─ů biegli w SF. Pierwsza z nich przechowuje nazw─Ö projektu, a druga nazw─Ö stageÔÇÖa, do kt├│rego us┼éuga jest deployowana. Dzi─Öki temu nie mam konfliktu nazw, nawet wtedy gdy r├│┼╝ne stageÔÇśe tego samego projektu s─ů deployowane do tego samego regionu (lub w og├│le, bo niekt├│re zasoby s─ů globalne np. S3 buckets, IAM Roles). Osobi┼Ťcie u┼╝ywam nazw stageÔÇÖ├│w dev, test i prod w moich projektach.

Po┼é─ůczenie - Connection

Nast─Öpnie potrzebujemy obiekt AWS::Events::Connection, kt├│ry zawiera dane uwierzytelniaj─ůce (takie jak nazwa u┼╝ytkownika i has┼éo) do endpointu.

1
2
3
4
5
6
7
8
9
MailchimpConnection:
Type: AWS::Events::Connection
Properties:
Name: MailchimpConnection-${self:provider.stage}
AuthorizationType: BASIC
AuthParameters:
BasicAuthParameters:
Username: "randomUser"
Password: ${ssm:mailchimp-api-key~true}

Do logowania do Mailchimp u┼╝yjemy autoryzacji typu BASIC. W przypadku parametru Username Mailchimp dopuszcza dowolny ci─ůg znak├│w i interesuje go tylko cz─Ö┼Ť─ç Password. Z perspektywy Mailchimpa warto┼Ť─ç Password jest kluczem Api Key, kt├│ry mo┼╝na wygenerowa─ç w menu Mailchimp wybieraj─ůc Account-> Extras-> API Keys.

Autoryzacja typu BASIC spowoduje, ┼╝e do ┼╝─ůdania tworzonego przez API Destinations podczas wywo┼éywania endpointu dodany b─Ödzie nag┼é├│wek authorization. Wygl─ůda to mniej wi─Öcej tak:

1
authorization	Basic cmFuZG9tVXNlcjpZlPkmY2hpbXBIcGlQYXNzd5CyZA==

Warto┼Ť─ç parametru Password jest ustawiona na ${ssm:mailchimp-api-key~true}, co jest wbudowan─ů opcj─ů Serverless Framework. Pobiera ona warto┼Ť─ç parametru z Systems Manager Parameter Store w chmurze (prefiks ssm) podczas deploymentu. Parametr ma nazw─Ö mailchimp-api-key a ~true oznacza, ┼╝e musi by─ç odszyfrowany. Wi─Öcej na ten temat w dokumentacji Serverless Framework.

Cel (destynacja) - ApiDestination

To co mo┼╝e by─ç dla Ciebie dziwne to fakt, ┼╝e nie zdefiniowali┼Ťmy adresu URL endpointu w obiekcie po┼é─ůczenia. Robi si─Ö to w AWS::Events::ApiDestination.

1
2
3
4
5
6
7
8
MailchimpApiDestination:
Type: AWS::Events::ApiDestination
Properties:
Name: mailchimp-tag-${self:provider.stage}
ConnectionArn: !GetAtt MailchimpConnection.Arn
InvocationEndpoint: ${self:custom.mailchimp.endpoint}/lists/${self:custom.mailchimp.list}/segments/*/members
HttpMethod: POST
InvocationRateLimitPerSecond: 20

Mamy tu trzy ciekawe elementy:

  • InvocationEndpoint
  • HttpMethod
  • InvocationRateLimitPerSecond

W tej chwili chc─Ö, aby┼Ť w pe┼éni zrozumia┼é jego znaczenie. Adres URL endpointa mo┼╝e by─ç parametryzowany na podstawie payload zdarzenia wys┼éanego do EventBusa. Jest to ┼Ťwietne, poniewa┼╝ pozwala nam na ponowne u┼╝ycie pojedynczej konfiguracji ApiDestination do wysy┼éania danych do z┼éo┼╝onych endpoint├│w.

Kolejnym znakomitym dodatkiem do API Destinations jest InvocationRateLimitPerSecond. Pozwala nam na ograniczenie cz─Östotliwo┼Ťci zapyta┼ä odpalanych przez API Destination do endpointu 3rd party. Oczywi┼Ťcie jest to bardzo istotna rzecz do rozwa┼╝enia podczas integracji, poniewa┼╝ nie wszystkie systemy s─ů tak skalowalne jak rozwi─ůzania serverless na AWS. Tutaj dostajemy to za darmo i bez ┼╝adnego dodatkowego kodowania.

Mam nadziej─Ö, ┼╝e to niesamowicie przydatne ustawienie zostanie dodane do innych konstrukcji w rodzinie EventBridge. M├│g┼ébym sobie wyobrazi─ç dodanie rate limitu do istniej─ůcych cel├│w Lambda lub jeszcze nieistniej─ůcego celu Simple Email Service (co drogie AWS by┼éoby super gdyby┼Ťcie dodali ­čĄ×) ­čśë

Reguła - Rule

Ostatnim elementem uk┼éadanki specyficznym dla EventBridge jest obiekt AWS::Events::Rule, kt├│ry zawiera Target. Obiekt Rule dzia┼éa jak router lub dyspozytor. M├│wi on naszemu custom EventBusowi, kt├│re zdarzenia wys┼éa─ç gdzie. Obiekt Target definiuje cz─Ö┼Ť─ç gdzie i wi─ů┼╝e razem Rule z now─ů funkcjonalno┼Ťci─ů API Destinations.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ApiDestinationDeliveryRule:
Type: AWS::Events::Rule
Properties:
EventBusName: !Ref EventBus
Name: SendOrderEventsToApiDestinations
EventPattern:
detail-type:
- ORDER_COURSE_SERVERLESS
- ORDER_COURSE_DATALAKE
State: "ENABLED"
Targets:
- Id: MailchimpApiDestination
Arn: !GetAtt MailchimpApiDestination.Arn
RoleArn: !GetAtt ApiDestinationsTargetRole.Arn
InputTransformer:
InputPathsMap:
mcTagId: $.detail.mcTagId
email: $.detail.email
InputTemplate: >
{
"email_address": <email>
}
HttpParameters:
PathParameterValues:
- $.detail.mcTagId

W sekcji EventPattern zdefiniowane jest, do jakich zdarzeń odnosi się ta reguła. W moim przypadku jest ona ograniczona tylko do zdarzeń Order.

Teraz porozmawiajmy o targetach. Pojedyncza Rule mo┼╝e definiowa─ç ich wiele, tutaj mamy tylko jeden, nazwany MailchimpApiDestination. Target odnosi si─Ö do zdefiniowanego powy┼╝ej ApiDestination, wymaga on dedykowanej roli IAM Role.

Definiuje on r├│wnie┼╝ InputTransformer, kt├│ry pozwala nam modyfikowa─ç payload zdarze┼ä i dostosowywa─ç je do specyfikacji API docelowego endpointu. W moim przypadku jest to metoda API Mailchimpa o nazwie Add member to segment. Wymaga ona pojedynczej warto┼Ťci pod zmienn─ů email_address w przes┼éanym JSONie.

Warto┼Ťci payloadu zdarzenia s─ů dost─Öpne przez $.detail i u┼╝yte w sekcji InputTemplate do konstrukcji oczekiwanej struktury obiektu.

Ostatnia sekcja pozwala nam sparametryzowa─ç URL endpointu zdefiniowanego w obiekcie ApiDestination warto┼Ťciami z payloadu zdarzenia. PathParameterValues przyjmuje tablic─Ö warto┼Ťci, co oznacza, ┼╝e w adresie URL mo┼╝emy zdefiniowa─ç wi─Öcej ni┼╝ jeden placeholder. S─ů one ewaluowane w kolejno┼Ťci, pierwszy element w tablicy odnosi si─Ö do pierwszej * w URL, i tak dalej.

Rola - IAM Role

Musimy r├│wnie┼╝ zdefiniowa─ç Role, kt├│ra mo┼╝e by─ç przyj─Öta (assume) przez us┼éug─Ö events.amazonaws.com. Rola ta musi nadawa─ç przywilej events:InvokeApiDestination na zas├│b MailchimpApiDestination. Pe┼én─ů definicj─Ö roli mo┼╝na znale┼║─ç w przyk┼éadowym projekcie na GitHub w pliku serverless.yml.

Przyk┼éadowe wdro┼╝enie rozwi─ůzania

Przygotowa┼éem przyk┼éadowy projekt wykorzystuj─ůcy Serverless Framework, wi─Öc mo┼╝esz go wdro┼╝y─ç na swoim koncie AWS i pobawi─ç si─Ö nim.

Musisz sklonowa─ç kod, oraz zainstalowa─ç zale┼╝no┼Ťci:

1
2
3
git clone https://github.com/serverlesspolska/eventbridge-api-destinations-mailchimp.git
cd eventbridge-api-destinations-mailchimp
npm i

To wymaga node.js i npm zainstalowanych na Twojej maszynie.

Poniewa┼╝ nie ka┼╝dy korzysta z Mailchimpa, w projekcie zdefiniowa┼éem drugi cel, kt├│ry wysy┼éa ┼╝─ůdania REST do us┼éugi webhook.site. Jest to darmowa, ┼éatwa w u┼╝yciu aplikacja webowa, kt├│ra b─Ödzie dzia┼éa─ç jako nasz 3rd party endpoint.

Prosz─Ö przejd┼║ do webhook.site i skopiuj Your unique URL. Wklej ten adres URL do pliku konfiguracyjnego serverless.yml w linii 38.

Teraz jeste┼Ťmy gotowi, aby zdeployowa─ç projekt na stage dev za pomoc─ů komendy:

1
sls deploy

(Zak┼éadam, ┼╝e masz domy┼Ťlny profil AWS zdefiniowany w ~/.aws/credentials.)

Po udanym deploymencie (mo┼╝e to potrwa─ç kilka minut) mo┼╝na wywo┼éa─ç funkcj─Ö Lambda, kt├│ra wy┼Ťle przyk┼éadowe zdarzenie Order do naszego EventBusa.

1
sls invoke -f sendOrderEvent -l

W efekcie czego, powiniene┼Ť zobaczy─ç nowe ┼╝─ůdanie na stronie webhook.site. (Je┼Ťli nie to od┼Ťwie┼╝ stron─Ö)

Oznacza to, ┼╝e API Destinations w odpowiedzi na nowe zdarzenie w EventBusie, w┼éa┼Ťnie wywo┼éa┼éo ┼╝─ůdanie na zdefiniowany endpoint.

┼╗─ůdanie otrzymane przez WebHook Site

Jak debugowa─ç EventBridge API Destinations?

Je┼Ťli co┼Ť ┼║le skonfigurowa┼ée┼Ť, lub mo┼╝e Twoje dane uwierzytelniaj─ůce s─ů z┼ée nie dostaniesz ┼╝adnych komunikat├│w o b┼é─Ödach, nie ma ┼╝adnych log├│w, kt├│re m├│g┼éby┼Ť przeczyta─ç i spr├│bowa─ç okre┼Ťli─ç co si─Ö sta┼éo. Wszystko co mo┼╝esz zrobi─ç, to sprawdzi─ç system 3rd party i zobaczy─ç, czy ┼╝─ůdanie dotar┼éo do niego - dlatego w┼éa┼Ťnie u┼╝yli┼Ťmy webhook.site.

A co, je┼Ťli ┼╝─ůdanie w og├│le nie trafia do endpointu?

Na szcz─Ö┼Ťcie, API Destinations pozwala na u┼╝ycie kolejek typu Dead Letter Queues (DLQ). Dla ka┼╝dego Target zdefiniowanego pod AWS::Events::Rule mo┼╝emy okre┼Ťli─ç kolejk─Ö SQS, kt├│ra b─Ödzie zawiera─ç wiadomo┼Ťci (zdarzenia), kt├│re nie mog┼éy by─ç pomy┼Ťlnie przetworzone przez Target API Destination. Ka┼╝da wiadomo┼Ť─ç, kt├│ra trafia do DLQ jest opatrzona adnotacj─ů z informacj─ů wyja┼Ťniaj─ůc─ů pow├│d umieszczenia jej w DLQ.

Oto dwie próbki komunikatów o błędach, które udało mi się uzyskać.
zły Mailchimp API Key Ten został zwrócony, gdy ustawiłem zły Mailchimp API Key.

Brak przywilej├│w Ten by┼é spowodowany niew┼éa┼Ťciw─ů definicj─ů Roli IAM.

Podsumowanie

Mam nadziej─Ö, ┼╝e ten artyku┼é by┼é dla Ciebie pouczaj─ůcy i teraz wiesz jak u┼╝ywa─ç Amazon EventBridge API Destinations w swoich projektach. Je┼Ťli masz jakie┼Ť pytania, zadaj je poni┼╝ej lub na stronie projektu na GitHubie.

Jestem przekonany, ┼╝e API Destinations to ┼Ťwietna funkcjonalno┼Ť─ç, nawet je┼Ťli zaj─Ö┼éo mi kilka godzin, aby zrozumie─ç i wdro┼╝y─ç j─ů poprawnie za pierwszym. W d┼éu┼╝szej perspektywie zaoszcz─Ödzi mi to znacznie wi─Öcej na wdra┼╝aniu i debugowaniu funkcji Lambda, kt├│re wywo┼éuj─ů endpointy 3rd party. Takie funkcje wydaj─ů si─Ö by─ç trywialne do napisania, ale w rzeczywisto┼Ťci takie nie s─ů i nie b─Öd─Ö za nimi t─Öskni┼é. (Jak by┼Ť zaimplementowa┼é funkcjonalno┼Ť─ç InvocationRateLimitPerSecond w Lambdzie w taki spos├│b, ┼╝eby nie p┼éaci─ç za czas bezczynno┼Ťci?). Pami─Ötaj u┼╝ywaj funkcji do transformacji, a nie transportu.

Co jest naprawd─Ö fajne i warte podkre┼Ťlenia, to fakt, ┼╝e ta funkcjonalno┼Ť─ç jest w pe┼éni rozwini─Öta i dostarczana ze wszystkimi niezb─Ödnymi rzeczami. Co najwa┼╝niejsze, jest pe┼éne wsparcie CloudFormation, co musz─Ö ze smutkiem przyzna─ç, dotychczas nie zawsze mia┼éo miejsce.
Kudos dla zespo┼éu CloudFormation! ­čÖĆ

Amazon EventBridge to centralny punkt wielu rozwi─ůza┼ä serverless i ciesz─Ö si─Ö, ┼╝e wci─ů┼╝ jest rozwijany. API Destinations to ┼Ťwietny dodatek do tej us┼éugi i mam nadziej─Ö, ┼╝e w przysz┼éo┼Ťci pojawi─ů sie kolejne, r├│wnie udane.