Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless

Hei, Habr!

Liker du Ă„ fly med fly? Jeg elsker det, men under selvisolasjonen har jeg ogsĂ„ blitt glad i Ă„ analysere data om flybilletter fra en kjent ressurs — Aviasales.

I dag skal vi gÄ gjennom hvordan Amazon Kinesis fungerer, bygge et strÞmmesystem med sanntidsanalyse, sette opp en NoSQL-database Amazon DynamoDB som hoveddatabasen, og konfigurere varsler via SMS for interessante billetter.

Alle detaljer finner du under! La oss begynne!

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless

Innledning

For eksempel trenger vi tilgang til API Aviasales. Tilgangen er gratis og uten begrensninger; du mÄ bare registrere deg under 'Utviklere' for Ä fÄ din API-token for tilgang til dataene.

HovedmÄlet med denne artikkelen er Ä gi en generell forstÄelse av hvordan informasjonsstrÞmming fungerer i AWS. Vi ser bort fra at dataene som returneres av det brukte APIet ikke nÞdvendigvis er strengt aktuelle og overfÞres fra cache, som dannes basert pÄ sÞkene til brukerne av Aviasales.ru og Jetradar.com de siste 48 timene.

Dataene om flybilletter som ble hentet via APIet, vil Kinesis-agenten som er installert pÄ produsentmaskinen, automatisk analysere og overfÞre til det riktige strÞmmen via Kinesis Data Analytics. Den ubehandlede versjonen av denne strÞmmen vil bli skrevet direkte til lagringsenheten. Den oppsatte DynamoDB-lagringen for 'rÄ' data vil tillate dypere analyse av billetter gjennom BI-verktÞy, for eksempel AWS Quick Sight.

Vi vil se pÄ to alternativer for distribusjon av hele infrastrukturen:

  • Manuell — gjennom AWS Management Console;
  • Infrastruktur fra Terraform-kode — for late automatiserere;

Arkitekturen til det utviklede systemet

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Brukte komponenter:

  • Aviasales API — dataene som returneres av dette APIet, vil bli brukt til all pĂ„fĂžlgende arbeidsprosess;
  • EC2 Producer Instance — en vanlig virtuell maskin i skyen som vil generere den innkommende datastreamen:
    • Kinesis Agent — Dette er et Java-program som installeres lokalt pĂ„ maskinen, og som gir en enkel mĂ„te Ă„ samle og sende data til Kinesis (Kinesis Data Streams eller Kinesis Firehose). Agenten overvĂ„ker kontinuerlig et sett med filer i angitte kataloger og sender nye data til Kinesis;
    • API Callerskript — et Python-skript som sender forespĂžrsel til APIet og legger svaret i en mappe som Kinesis Agent overvĂ„ker;
  • Kinesis Data Streams — en sanntidsdatastreamingstjeneste med omfattende skaleringsmuligheter;
  • Kinesis Analytics — en serverlĂžs tjeneste som forenkler sanntidsanalyse av datastrĂžmmer. Amazon Kinesis Data Analytics konfigurerer ressursene for applikasjonskjĂžring og skalerer automatisk for Ă„ hĂ„ndtere hvilke mengder innkommende data som helst;
  • AWS Lambda — en tjeneste som lar deg kjĂžre kode uten behov for Ă„ sette opp eller tildele servere. All databehandlingskraft skaleres automatisk for hver forespĂžrsel;
  • Amazon DynamoDB — en database med «nĂžkkel-verdi»-par og dokumenter, som gir en forsinkelse pĂ„ under 10 millisekunder pĂ„ ethvert nivĂ„. Med DynamoDB kreves det ingen distribusjon av servere, installasjon av oppdateringer eller vedlikehold. DynamoDB skalerer automatisk tabeller ved Ă„ justere mengden tilgjengelige ressurser og opprettholder hĂžy ytelse. Ingen systemadministrasjon kreves;
  • Amazon SNS — en fullt administrert meldingssendingstjeneste basert pĂ„ «publisher-subscriber» (Pub/Sub) modell, som lar deg isolere mikrotjenester, distribuerte systemer og serverlĂžse applikasjoner. SNS kan brukes til Ă„ sende informasjon til sluttbrukere via mobile push-varsler, SMS-meldinger og e-post.

Innledende forberedelser

For Ă„ emulere datastrĂžmmen har jeg valgt Ă„ bruke informasjon om flybilletter som tilveiebringes av API Aviasales. I dokumentasjonen et ganske omfattende utvalg av forskjellige metoder, la oss ta en av dem — «MĂ„nedens prisoversikt», som returnerer priser for hver dag i mĂ„neden, gruppert etter antall mellomlandinger. Hvis man ikke angir mĂ„neden for sĂžket i forespĂžrselen, vil informasjon for mĂ„neden etter den nĂ„vĂŠrende bli returnert.

SÄ, vi registrerer oss og fÄr vÄr token.

Eksempel pÄ forespÞrsel under:

http://api.travelpayouts.com/v2/prices/month-matrix?currency=rub&origin=LED&destination=HKT&show_to_affiliates=true&token=TOKEN_API

Metoden for Ä hente data fra API med token i forespÞrselen vil fungere, men jeg foretrekker Ä sende tilgangstoken via header, sÄ i skriptet api_caller.py vil vi bruke nettopp denne metoden.

Eksempel pÄ svar:

{{
   "success":true,
   "data":[{
      "show_to_affiliates":true,
      "trip_class":0,
      "origin":"LED",
      "destination":"HKT",
      "depart_date":"2015-10-01",
      "return_date":"",
      "number_of_changes":1,
      "value":29127,
      "found_at":"2015-09-24T00:06:12+04:00",
      "distance":8015,
      "actual":true
   }]
}

I eksemplet pĂ„ API-responsen ovenfor vises en billett fra St. Petersburg til Phuket... Åh, hvorfor drĂžmme...
Siden jeg er fra Kazan, og Phuket nÄ er "bare en drÞm" for oss, la oss se etter billetter fra St. Petersburg til Kazan.

Det forutsettes at du allerede har en konto i AWS. Jeg vil straks pÄpeke at Kinesis og sending av varsler via SMS ikke er inkludert i det Ärlige. Free Tier (gratis bruk). Men selv med dette, med tanke pÄ et par dollar, kan man godt bygge det foreslÄtte systemet og eksperimentere med det. Og selvfÞlgelig mÄ man ikke glemme Ä slette alle ressurser etter at de ikke lenger er nÞdvendige.

Heldigvis vil DynamoDb og Lambda-funksjoner vÊre betinget gratis for oss, sÄ lenge vi holder oss innen de mÄnedlige gratisgrensene. For eksempel for DynamoDB: 25 GB lagring, 25 WCU/RCU og 100 millioner forespÞrslene. Og en million kall av lambda-funksjoner per mÄned.

Manuell distribusjon av systemet

Innstilling av Kinesis Data Streams

La oss gÄ til Kinesis Data Streams-tjenesten og opprette to nye strÞmmer med én shard hver.

Hva er en shard?
En shard er den grunnleggende enheten for datatransport i Amazon Kinesis-strĂžm. Én shard gir en datainngang med en hastighet pĂ„ 1 MB/s og en utgang med en hastighet pĂ„ 2 MB/s. Én shard stĂžtter opptil 1000 PUT-forespĂžrsel per sekund. NĂ„r du oppretter en datastream, mĂ„ du angi antall shards du Ăžnsker. For eksempel kan man opprette en datastream med to shards. Denne datastreamen vil gi en datainngang med en hastighet pĂ„ 2 MB/s og en utgang med en hastighet pĂ„ 4 MB/s med stĂžtte for opptil 2000 PUT-forespĂžrsel per sekund.

Jo flere shards du har i strÞmmen, desto stÞrre blir bÄndbredden. Generelt skal strÞmmer skaleres ved Ä legge til shards. Men jo flere shards du har, desto hÞyere blir prisen. Hver shard koster 1,5 cent i timen og i tillegg 1,4 cent for hver million operationer med tillegg i strÞmmen (PUT payload units).

La oss opprette en ny strÞm med navnet airline_tickets, én shard vil vÊre mer enn tilstrekkelig:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
NĂ„ skal vi opprette en annen strĂžm med navnet special_stream:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless

Innstilling av produsent

Som dataprofil for Ă„ lĂžse oppgaven, er det tilstrekkelig Ă„ bruke en vanlig EC2-instans. Dette trenger ikke vĂŠre en kraftig og kostbar virtuell maskin, en t2.micro spot vil fungere helt fint.

Viktig merknad: For eksemplet bþr man bruke bildet – Amazon Linux AMI 2018.03.0, da dette krever férre innstillinger for rask oppstart av Kinesis Agent.

Vi gÄr til EC2-tjenesten, oppretter en ny virtuell maskin, velger Þnsket AMI med typen t2.micro, som inngÄr i Free Tier:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
For at den nyopprettede virtuelle maskinen skal kunne samhandle med Kinesis-tjenesten, mÄ vi gi den de nÞdvendige rettighetene. Den beste mÄten Ä gjÞre dette pÄ er Ä tildele en IAM role. SÄ pÄ skjermen Trinn 3: Konfigurer instansdetaljer, velg Opprett ny IAM-rolle:

Oppretting av IAM-rolle for EC2
Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
I det Äpne vinduet velger vi at vi oppretter en ny rolle for EC2 og gÄr til delen Rettigheter:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
I eksempelet kan vi unngÄ Ä gÄ inn i alle detaljene om finjustering av rettigheter for ressurser, sÄ vi velger de forhÄndskonfigurerte policyene fra Amazon: AmazonKinesisFullAccess og CloudWatchFullAccess.

Vi gir denne rollen et meningsfullt navn, for eksempel: EC2-KinesisStreams-FullAccess. Resultatet skal vÊre det samme som vist pÄ bildet nedenfor:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Etter opprettelsen av denne nye rollen, ikke glem Ă„ knytte den til den opprettede virtuelle maskinen:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Ikke gjÞr flere endringer pÄ denne skjermen og gÄ videre til de neste vinduene.

Diskinnstillingene kan stÄ som standard, og taggene ogsÄ (selv om god praksis er Ä bruke tagger, minst gi instansen et navn og spesifisere miljÞet).

NÄ er vi pÄ fanen Trinn 6: Konfigurer sikkerhetsgruppe, hvor vi mÄ opprette en ny eller spesifisere en eksisterende sikkerhetsgruppe som tillater tilkobling via ssh (port 22) til instansen. Velg der Kilde -> Min IP, og du kan starte instansen.

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
SÄ snart den gÄr over i statusen kjÞrende, kan du prÞve Ä koble til via ssh.

For Ä bruke Kinesis-agenten etter en vellykket tilkobling til maskinen, mÄ du skrive inn fÞlgende kommandoer i terminalen:

sudo yum -y update
sudo yum install -y python36 python36-pip
sudo /usr/bin/pip-3.6 install --upgrade pip
sudo yum install -y aws-kinesis-agent

Vi oppretter en mappe for Ă„ lagre API-svarene:

sudo mkdir /var/log/airline_tickets

FÞr du kjÞrer agenten, mÄ du konfigurere konfigurasjonen:

sudo vim /etc/aws-kinesis/agent.json

Innholdet i filen agent.json skal ha fĂžlgende struktur:

{
  "cloudwatch.emitMetrics": true,
  "kinesis.endpoint": "",
  "firehose.endpoint": "",

  "flows": [
    {
      "filePattern": "/var/log/airline_tickets/*log",
      "kinesisStream": "airline_tickets",
      "partitionKeyOption": "RANDOM",
      "dataProcessingOptions": [
         {
            "optionName": "CSVTOJSON",
            "customFieldNames": ["cost","trip_class","show_to_affiliates",
                "return_date","origin","number_of_changes","gate","found_at",
                "duration","distance","destination","depart_date","actual","record_id"]
         }
      ]
    }
  ]
}

Som det gÄr frem av konfigurasjonsfilen, vil agenten overvÄke filer med .log-utvidelse i katalogen /var/log/airline_tickets/, analysere dem og sende dem til strÞmmen airline_tickets.

Vi restartet tjenesten og bekrefter at den har startet og fungerer:

sudo service aws-kinesis-agent restart

NĂ„ laster vi ned Python-skriptet som skal be om data fra APIet:

REPO_PATH=https://raw.githubusercontent.com/igorgorbenko/aviasales_kinesis/master/producer

wget $REPO_PATH/api_caller.py -P /home/ec2-user/
wget $REPO_PATH/requirements.txt -P /home/ec2-user/
sudo chmod a+x /home/ec2-user/api_caller.py
sudo /usr/local/bin/pip3 install -r /home/ec2-user/requirements.txt

Skriptet api_caller.py henter data fra Aviasales og lagrer svaret i katalogen som Kinesis-agenten skanner. Implementeringen av dette skriptet er ganske standard, det finnes en klasse TicketsApi, som gjĂžr det mulig Ă„ asynkront hente data fra APIet. I denne klassen sender vi inn hodet med token og forespĂžrselparametrene:

class TicketsApi:
    """API-kallerklasse."""

    def __init__(self, headers):
        """Init-metode."""
        self.base_url = BASE_URL
        self.headers = headers

    async def get_data(self, data):
        """Hent data fra API-forspĂžrsel."""
        response_json = {}
        async with ClientSession(headers=self.headers) as session:
            try:
                response = await session.get(self.base_url, data=data)
                response.raise_for_status()
                LOGGER.info('Responsestatus %s: %s',
                            self.base_url, response.status)
                response_json = await response.json()
            except HTTPError as http_err:
                LOGGER.error('Oops! HTTP-feil oppstod: %s', str(http_err))
            except Exception as err:
                LOGGER.error('Oops! En feil oppstod: %s', str(err))
            return response_json


def prepare_request(api_token):
    """Returner hodene og forespĂžrselen for API-anropet."""
    headers = {'X-Access-Token': api_token,
               'Accept-Encoding': 'gzip'}

    data = FormData()
    data.add_field('currency', CURRENCY)
    data.add_field('origin', ORIGIN)
    data.add_field('destination', DESTINATION)
    data.add_field('show_to_affiliates', SHOW_TO_AFFILIATES)
    data.add_field('trip_duration', TRIP_DURATION)
    return headers, data


async def main():
    """KjĂžr koden."""
    if len(sys.argv) != 2:
        print('Bruk: api_caller.py ')
        sys.exit(1)
        return
    api_token = sys.argv[1]
    headers, data = prepare_request(api_token)

    api = TicketsApi(headers)
    response = await api.get_data(data)
    if response.get('success', None):
        LOGGER.info('API har returnert %s elementer', len(response['data']))
        try:
            count_rows = log_maker(response)
            LOGGER.info('%s rader har blitt lagret i %s',
                        count_rows,
                        TARGET_FILE)
        except Exception as e:
            LOGGER.error('Oops! Resultatet av forespĂžrselen ble ikke lagret i fil. %s',
                         str(e))
    else:
        LOGGER.error('Oops! API-forespĂžrsel var ikke vellykket %s!', response)

For Ă„ teste konfigurasjonen og agentens funksjonalitet, la oss gjĂžre en testkjĂžring av skriptet api_caller.py:

sudo ./api_caller.py TOKEN

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Og vi ser resultatet av arbeidet i agentens logger og i Monitoring-fanen i datastreamen airline_tickets:

tail -f /var/log/aws-kinesis-agent/aws-kinesis-agent.log

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Som syns, alt fungerer og Kinesis Agent sender data til strĂžmmen. NĂ„ konfigurerer vi forbrukeren.

Konfigurering av Kinesis Data Analytics

Vi gĂ„r videre til den sentrale komponenten i hele systemet — oppretter en ny applikasjon i Kinesis Data Analytics med navnet kinesis_analytics_airlines_app:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Kinesis Data Analytics tillater sanntidsdataanalyse fra Kinesis Streams ved hjelp av SQL. Dette er en fullt selvskalende tjeneste (i motsetning til Kinesis Streams), som:

  1. lar deg opprette nye strÞmmer (Output Stream) basert pÄ forespÞrslene til kildedataene;
  2. gir en feilstrĂžm som inneholder feil som oppsto under kjĂžringen av applikasjoner (Error Stream);
  3. kan automatisk oppdage strukturen til inngangsdataene (den kan overstyres manuelt hvis nĂždvendig).

Dette er en kostbar tjeneste — 0,11 USD per time, sĂ„ vĂŠr forsiktig med bruken og slett den ved avslutning.

Vi kobler applikasjonen til datakilden:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Vi velger strĂžmmen vi skal koble oss til (airline_tickets):

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Deretter mÄ vi legge til en ny IAM-rolle som lar applikasjonen lese fra strÞmmen og skrive til strÞmmen. Det er ikke nÞdvendig Ä endre noe i blokken med tilgangstillatelser:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
NÄ ber vi om oppdagelse av dataskjemaet i strÞmmen, sÄ vi trykker pÄ knappen «Discover schema». Resultatet vil oppdatere (opprette en ny) IAM-rolle og oppdage skjemaet fra dataene som allerede har kommet til strÞmmen:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
NĂ„ er det nĂždvendig Ă„ gĂ„ til SQL-redaktĂžren. NĂ„r vi klikker pĂ„ denne knappen, vises et vindu med spĂžrsmĂ„l om Ă„ starte applikasjonen — velg hva vi Ăžnsker Ă„ starte:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
I SQL-redaktÞren limer vi inn en enkel forespÞrsel og klikker pÄ Save and Run SQL:

CREATE OR REPLACE STREAM "DESTINATION_SQL_STREAM" ("cost" DOUBLE, "gate" VARCHAR(16));

CREATE OR REPLACE PUMP "STREAM_PUMP" AS INSERT INTO "DESTINATION_SQL_STREAM"
SELECT STREAM "cost", "gate"
FROM "SOURCE_SQL_STREAM_001"
WHERE "cost" < 5000
    and "gate" = 'Aeroflot';

I relasjonsdatabaser jobber du med tabeller ved hjelp av INSERT-operasjoner for Ă„ legge til oppfĂžringer og SELECT-operasjoner for Ă„ hente data. I Amazon Kinesis Data Analytics jobber du med strĂžmmer (STREAM) og pumper (PUMP) — kontinuerlige forespĂžrselinnsettinger som setter inn data fra Ă©n strĂžm til en annen i applikasjonen.

I SQL-forespĂžrselen ovenfor skjer det et sĂžk etter Aeroflot-billetter med en kostnad under fem tusen rubler. Alle oppfĂžringer som oppfyller disse betingelsene, vil bli lagt i strĂžmmen DESTINATION_SQL_STREAM.

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
I blokken Destination velger vi strĂžmmen special_stream, og i nedtrekkslisten In-application stream name DESTINATION_SQL_STREAM:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Som resultat av alle manipulasjoner skal vi ende opp med noe som ligner bildet nedenfor:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless

Opprettelse og abonnement pÄ SNS-emne

Vi gÄr til tjenesten Simple Notification Service og oppretter et nytt emne med navnet Airlines:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Vi oppretter et abonnement pÄ dette emnet, der vi angir mobilnummeret som SMS-varsler skal sendes til:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless

Opprettelse av tabell i DynamoDB

For Ä lagre de rÄ dataene fra strÞmmen airline_tickets, skal vi opprette en tabell i DynamoDB med samme navn. Vi bruker record_id som primÊrnÞkkel:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless

Opprettelse av Lambda-funksjonen collector

Vi lager en Lambda-funksjon kalt Collector, hvis oppgave blir Ä spÞrre strÞmmen airline_tickets, og ved funn av nye oppfÞringer, sette disse inn i DynamoDB-tabellen. Det er Äpenbart at i tillegg til standardrettighetene mÄ denne Lambda-funksjonen ha tilgang til Ä lese Kinesis-datastrÞmmen og skrive til DynamoDB.

Opprettelse av IAM-rolle for Lambda-funksjonen collector
FĂžrst oppretter vi en ny IAM-rolle for Lambda med navnet Lambda-TicketsProcessingRole:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
For dette testeksempelet er de forhÄndsinnstilte policyene AmazonKinesisReadOnlyAccess og AmazonDynamoDBFullAccess tilstrekkelige, som vist pÄ bildet nedenfor:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless

Denne Lambda-funksjonen mÄ kjÞres pÄ et utlÞser fra Kinesis nÄr nye oppfÞringer kommer inn i strÞmmen airline_stream, sÄ vi mÄ legge til en ny utlÞser:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Det gjenstÄr bare Ä sette inn koden og lagre Lambda-funksjonen.

"""Parsing the stream and inserting into the DynamoDB table."""
import base64
import json
import boto3
from decimal import Decimal

DYNAMO_DB = boto3.resource('dynamodb')
TABLE_NAME = 'airline_tickets'

class TicketsParser:
    """Parsing info from the Stream."""

    def __init__(self, table_name, records):
        """Init method."""
        self.table = DYNAMO_DB.Table(table_name)
        self.json_data = TicketsParser.get_json_data(records)

    @staticmethod
    def get_json_data(records):
        """Return deserialized data from the stream."""
        decoded_record_data = ([base64.b64decode(record['kinesis']['data'])
                                for record in records])
        json_data = ([json.loads(decoded_record)
                      for decoded_record in decoded_record_data])
        return json_data

    @staticmethod
    def get_item_from_json(json_item):
        """Pre-process the json data."""
        new_item = {
            'record_id': json_item.get('record_id'),
            'cost': Decimal(json_item.get('cost')),
            'trip_class': json_item.get('trip_class'),
            'show_to_affiliates': json_item.get('show_to_affiliates'),
            'origin': json_item.get('origin'),
            'number_of_changes': int(json_item.get('number_of_changes')),
            'gate': json_item.get('gate'),
            'found_at': json_item.get('found_at'),
            'duration': int(json_item.get('duration')),
            'distance': int(json_item.get('distance')),
            'destination': json_item.get('destination'),
            'depart_date': json_item.get('depart_date'),
            'actual': json_item.get('actual')
        }
        return new_item

    def run(self):
        """Batch insert into the table."""
        with self.table.batch_writer() as batch_writer:
            for item in self.json_data:
                dynamodb_item = TicketsParser.get_item_from_json(item)
                batch_writer.put_item(dynamodb_item)

        print('Has been added ', len(self.json_data), 'items')

def lambda_handler(event, context):
    """Parse the stream and insert into the DynamoDB table."""
    print('Got event:', event)
    parser = TicketsParser(TABLE_NAME, event['Records'])
    parser.run()

Oppretting av lambda-funksjonen notifier

Den andre lambda-funksjonen, som vil overvÄke den andre strÞmmen (special_stream) og sende en varsling til SNS, opprettes pÄ samme mÄte. Dermed mÄ denne lambda ha tilgang til Ä lese fra Kinesis og sende meldinger til den angitte SNS-topikken, som deretter distribueres av SNS-tjenesten til alle abonnenter av denne topikken (e-post, SMS, osv.).

Oppretting av IAM-rolle
FĂžrst oppretter vi IAM-rollen Lambda-KinesisAlarm for denne lambdaen, og deretter tildeler vi denne rollen til opprettet lambda alarm_notifier:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless

Denne lambdaen skal trigges ved tilfÞyelse av nye poster i strÞmmen special_stream, sÄ det er nÞdvendig Ä konfigurere triggen pÄ samme mÄte som vi gjorde for lambdaen Collector.

For Ă„ forenkle konfigurasjonen av denne lambdaen, introduserer vi en ny miljĂžvariabel — TOPIC_ARN, hvor vi setter ARN (Amazon Resource Names) til Airlines-topikken:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Og vi setter inn koden for lambdaen, den er ganske enkel:

import boto3
import base64
import os

SNS_CLIENT = boto3.client('sns')
TOPIC_ARN = os.environ['TOPIC_ARN']


def lambda_handler(event, context):
    try:
        SNS_CLIENT.publish(TopicArn=TOPIC_ARN,
                           Message='Hei! Jeg har funnet noe interessant!',
                           Subject='Alarm for flybilletter')
        print('Alarmmeldingen har blitt levert vellykket')
    except Exception as err:
        print('Leveringsfeil', str(err))

Det ser ut til at manuell systemkonfigurasjon er avsluttet. Det gjenstÄr bare Ä teste og sÞrge for at vi har konfigurert alt riktig.

Distribusjon fra Terraform-kode

NĂždvendig forberedelse

Terraform — et veldig praktisk open-source verktĂžy for distribusjon av infrastruktur fra kode. Det har sin egen syntaks som er lett Ă„ lĂŠre, og mange eksempler pĂ„ hvordan man distribuerer hva. I Atom- eller Visual Studio Code-editorene er det mange nyttige plugins som gjĂžr arbeidet med Terraform enklere.

DistributÞren kan lastes ned herfrÄ. En detaljert gjennomgang av alle muligheter i Terraform gÄr utenfor rammen av denne artikkelen, sÄ vi begrenser oss til hovedpunktene.

Hvordan starte

Hele prosjektkoden ligger i mitt repository. Klon repositoryen til din egen. FÞr du starter, mÄ du sÞrge for at du har installert og konfigurert AWS CLI, siden Terraform vil lete etter legitimations i filen ~/ .aws/credentials.

Det er god praksis fÞr distribusjon av hele infrastrukturen Ä kjÞre kommandoen plan for Ä se hva Terraform nÄ skal opprette i skyen:

terraform.exe plan

Du vil bli bedt om Ă„ oppgi telefonnummeret for Ă„ sende varsler dit. PĂ„ dette stadiet er det ikke nĂždvendig Ă„ oppgi det.

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Etter Ă„ ha analysert programmets arbeidsplan, kan vi starte opprettingen av ressurser:

terraform.exe apply

Etter at denne kommandoen er sendt, vil det igjen bli bedt om Ä oppgi telefonnummer, skriv «yes» nÄr spÞrsmÄlet om faktisk utfÞrelse av handlinger vises. Dette vil gjÞre det mulig Ä sette opp hele infrastrukturen, utfÞre all nÞdvendig konfigurasjon av EC2, distribuerer lambda-funksjoner osv.

Etter at alle ressurser er opprettet vellykket via Terraform-kode, mÄ du gÄ inn i detaljene for Kinesis Analytics-applikasjonen (dessverre fant jeg ikke ut hvordan man gjÞr dette direkte fra koden).

Start applikasjonen:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Deretter mÄ du eksplisitt angi in-application stream-navn, ved Ä velge fra nedtrekkslisten:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
NĂ„ er alt klart til bruk.

Testing av applikasjonens drift

Uansett om du distribuerte systemet manuelt eller via Terraform-kode, vil det fungere likt.

Logg inn via SSH pÄ EC2-virtuell maskin der Kinesis Agent er installert og start skriptet api_caller.py

sudo ./api_caller.py TOKEN

Bare vent pÄ SMS til ditt nummer:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
SMS-en blir sendt til telefonen din omtrent ett minutt senere:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless
Det gjenstÄr Ä sjekke om postene er lagret i DynamoDB-databasen for videre, mer detaljert analyse. Tabellen airline_tickets inneholder omtrent slike data:

Integrasjon av Aviasales API med Amazon Kinesis og enkelhet i serverless

Konklusjon

I lÞpet av arbeidet ble det bygget et system for sanntidsbehandling av data basert pÄ Amazon Kinesis. Vi vurderte alternativer for bruk av Kinesis Agent sammen med Kinesis Data Streams og sanntidsanalyse med Kinesis Analytics ved hjelp av SQL-kommandoer, samt interaksjon mellom Amazon Kinesis og andre AWS-tjenester.

Det ovennevnte systemet ble implementert pÄ to mÄter: en relativt langvarig manuell metode og en raskere fra Terraform-kode.

All kildekode for prosjektet er tilgjengelig i min repository pÄ GitHub, jeg foreslÄr at du tar en titt.

Jeg ser frem til Ä diskutere artikkelen, og venter pÄ dine kommentarer. Jeg hÄper pÄ konstruktiv kritikk.

Jeg Ăžnsker deg lykke til!

Kilde: habr.com

KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster