2017-02-21 2 views
4

Ich bin auf der Suche nach der Möglichkeit, eine Lambda-Funktion programmgesteuert zu planen, um ein einzelnes Mal mit einer anderen Lambda-Funktion auszuführen. Zum Beispiel habe ich eine Anfrage an myFirstFunction mit date und time Parameter, und dann zu diesem Datum und Uhrzeit, haben mySecondFunction ausführen. Ist das nur mit staatenlosen AWS-Diensten möglich? Ich versuche, eine immer aktive ec2-Instanz zu vermeiden.Kann ich eine Ausführung einer Lambda-Funktion mit einer Lambda-Funktion planen?

Die meisten Ergebnisse, die ich für die Planung von Lambda-Funktionen finde, haben mit Cloudwatch und regelmäßig geplanten Ereignissen zu tun, nicht mit Ad-hoc-Ereignissen.

Antwort

0

Ich würde entscheiden, verzögerte Arbeit an SQS unter Verwendung message timers in myFirstFunction in die Warteschlange einzureihen.

Momentan können Sie SQS nicht als Lambda-Ereignisquelle verwenden. Sie können mySecondFunction jedoch regelmäßig planen, um die Warteschlange über geplante CloudWatch-Ereignisse (etwas von einer Variante der anderen gefundenen Optionen) zu überprüfen oder ein CloudWatch-Alarm auf der ApproximateNumberOfMessagesVisible, um eine SNS-Nachricht an ein Lambda auszulösen und eine ständige Abfrage für Warteschlangen zu vermeiden, die häufig für lange Zeit inaktiv sind.

1

UPDATE - Ich würde diesen Ansatz nicht empfehlen. Die Dinge änderten sich, wenn TTL-Löschungen passieren und sie nicht nahe bei der TTL-Zeit sind. Die einzige Garantie ist, dass der Artikel nach dem TTL gelöscht wird. Danke @Mentor für die Hervorhebung dieses.

Vor 2 Monaten hat AWS DynamoDB Element TTL angekündigt, mit dem Sie ein Element einfügen und markieren können, wenn Sie es löschen möchten. Es wird automatisch gelöscht, wenn die Zeit gekommen ist.

Sie können diese Funktion in Verbindung mit DynamoDB-Streams verwenden, um Ihr Ziel zu erreichen - Ihre erste Funktion fügt ein Element in eine DynamoDB-Tabelle ein. Die Datensatz-TTL sollte zu dem Zeitpunkt sein, an dem das zweite Lambda ausgelöst werden soll. Richten Sie einen Stream ein, der Ihr zweites Lambda auslöst. In diesem Lambda identifizieren Sie Löschungsereignisse und wenn das ein Löschen ist, dann führen Sie Ihre Logik aus.

Bonuspunkt - Sie können das Tabellenelement als Mechanismus für das erste Lambda verwenden, um Parameter an das zweite Lambda zu übergeben.

über DynamoDB TTL: https://aws.amazon.com/blogs/aws/new-manage-dynamodb-items-using-time-to-live-ttl/

+1

Wie [Dokumente sagen] (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html): _DynamoDB löscht in der Regel abgelaufene Elemente innerhalb von 48 Stunden nach Ablauf._ So ist dies keine Lösung. – Mentor

+0

@Mentor - du hast Recht. Als ich das schrieb, enthielt die Dokumentation, soweit ich mich erinnere, das nicht. Darüber hinaus kann ich bestätigen, dass ich kürzlich festgestellt habe, dass TTL-Deletionen tatsächlich viel mehr als zuvor benötigen. Ich kann nicht sagen, was sich geändert hat, aber ich kann bestätigen, dass es nicht so nahe an der TTL-Zeit liegt wie früher. Danke für den Kommentar. – justabuzz

0

Was Sie Tring Dienstleistungen zu tun (Zeitplan Lambda von Lambda) ist es nicht möglich, mit den aktuellen AWS.

, um so eine Always-on-EC2-Instanz zu vermeiden, gibt es andere Möglichkeiten:

1) Verwenden Sie AWS standardmäßigen oder benutzerdefinierten Metriken. Sie können z. B. ApproximateNumberOfMessagesVisible oder CPUUtilization verwenden (wenn Ihre Anwendung beim Verarbeiten einer Anforderung eine große CPU-Auslastung auslöst). Sie können auch einen benutzerdefinierten Messwert erstellen und ihn auslösen, wenn Ihre Instanz inaktiv ist (abhängig von der App, die in Ihrer Instanz ausgeführt wird).

Das Problem mit dieser Option ist, dass Sie bereits bezahlte Minuten verschwenden (AWS berechnet immer eine volle Stunde, unabhängig davon, ob Sie Ihre Instanz 15 Minuten lang verwendet haben).

2) Eine bessere Option, meiner Meinung nach, wäre, eine Lambda-Funktion einmal pro Minute auszuführen, um zu überprüfen, ob Ihre Instanzen inaktiv sind, und sie nur dann herunterzufahren, wenn sie nahe der vollen Stunde sind.

import boto3 
from datetime import datetime 

def lambda_handler(event, context): 
    print('ManageInstances function executed.') 
    environments = [['instance-id-1', 'SQS-queue-url-1'], ['instance-id-2', 'SQS-queue-url-2'], ...] 
    ec2_client = boto3.client('ec2') 
    for environment in environments: 
     instance_id = environment[0] 
     queue_url = environment[1] 
     print 'Instance:', instance_id 
     print 'Queue:', queue_url 
     rsp = ec2_client.describe_instances(InstanceIds=[instance_id]) 
     if rsp: 
      status = rsp['Reservations'][0]['Instances'][0] 
      if status['State']['Name'] == 'running': 
       current_time = datetime.now() 
       diff = current_time - status['LaunchTime'].replace(tzinfo=None) 
       total_minutes = divmod(diff.total_seconds(), 60)[0] 
       minutes_to_complete_hour = 60 - divmod(total_minutes, 60)[1] 
       print 'Started time:', status['LaunchTime'] 
       print 'Current time:', str(current_time) 
       print 'Minutes passed:', total_minutes 
       print 'Minutes to reach a full hour:', minutes_to_complete_hour 
       if(minutes_to_complete_hour <= 2): 
        sqs_client = boto3.client('sqs') 
        response = sqs_client.get_queue_attributes(QueueUrl=queue_url, AttributeNames=['All']) 
        messages_in_flight = int(response['Attributes']['ApproximateNumberOfMessagesNotVisible']) 
        messages_available = int(response['Attributes']['ApproximateNumberOfMessages']) 
        print 'Messages in flight:', messages_in_flight 
        print 'Messages available:', messages_available 
        if(messages_in_flight + messages_available == 0): 
         ec2_resource = boto3.resource('ec2') 
         instance = ec2_resource.Instance(instance_id) 
         instance.stop() 
         print('Stopping instance.') 
      else: 
       print('Status was not running. Nothing is done.') 
     else: 
      print('Problem while describing instance.') 
0

Ich denke, vielleicht können Sie these instructions verwenden.

Aber ich habe diese Anweisungen ausprobiert und es hat nicht funktioniert, wenn ich manuell in die Konsole ging, um die Regel mit dem Ziel zu verknüpfen. (Trotz Senden eines API-Aufrufs put_target)

Auch ich verstehe nicht, was der letzte Schritt in diesen Anweisungen ist. Ich habe es nicht gemacht, weil es nicht anwendbar schien, aber vielleicht funktioniert das auch nicht.

Verwandte Themen