2017-02-21 3 views
4

Я ищу возможность программно планировать функцию лямбда, чтобы запускать один раз с другой лямбда-функцией. Например, я сделал запрос к myFirstFunction с параметрами date и time, а затем в эту дату и время выполните mySecondFunction. Возможно ли это только с помощью служб AWS без гражданства? Я пытаюсь избежать экземпляра ec2 всегда.Могу ли я планировать выполнение лямбда-функции с помощью лямбда-функции?

Большинство результатов, которые я нахожу для планирования лямбда-функций, имеют отношение к облачным и регулярным событиям, а не к событиям ad-hoc.

ответ

0

Я бы предпочел отложить отложенную работу на SQS, используя message timers в myFirstFunction.

В настоящее время вы не можете использовать SQS в качестве источника событий Lambda, но вы можете либо периодически планировать mySecondFunction, чтобы проверять очередь через запланированные события CloudWatch (несколько вариантов других параметров, которые вы нашли), либо использовать CloudWatch на ApproximateNumberOfMessagesVisible, чтобы отправить сообщение SNS на Лямбду и избежать постоянного опроса для очередей, которые часто неактивны в течение длительного времени.

1

ОБНОВЛЕНИЕ - Я бы не рекомендовал использовать этот подход. Вещи менялись, когда удаляются TTL-удаления, и они не близки к времени TTL. Единственная гарантия заключается в том, что элемент будет удален после TTL. Спасибо @Mentor за это.

2 месяца назад AWS анонсировала элемент TTL DynamoDB, который позволяет вставлять элемент и отмечать, когда вы хотите его удалить. Он будет удален автоматически, когда придет время.

Вы можете использовать эту функцию совместно с потоками DynamoDB для достижения своей цели - ваша первая функция вставляет элемент в таблицу DynamoDB. Запись TTL должна быть, когда вы хотите, чтобы вторая лямбда срабатывала. Установите поток, который запускает вашу вторую лямбду. В этой лямбде вы будете идентифицировать события удаления, и если это удаление, тогда выполните свою логику.

Бонусная точка - вы можете использовать элемент таблицы как механизм для первой лямбда для передачи параметров ко второй лямбда.

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

+1

Как [docs say] (http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html): _DynamoDB обычно удаляет истекшие элементы в течение 48 часов после истечения срока действия. Таким образом, это не решение. – Mentor

+0

@ Ментор - вы правы. Когда я писал это, документы, насколько я помню, не включали это. Кроме того, я могу подтвердить, что недавно я заметил, что удаление TTL действительно занимает гораздо больше, чем раньше. Я не могу сказать, что изменилось, но я могу подтвердить, что это не так близко к времени TTL, как раньше. Спасибо за комментарий. – justabuzz

0

Что вы Тринг делать (график Lambda от лямбда) это не представляется возможным с текущим обслуживанием АМС.

Итак, для того, чтобы избежать всегда на ec2, например, есть и другие варианты:

1) Использование AWS по умолчанию или пользовательские метрики. Вы можете использовать, например, ApproximateNumberOfMessagesVisible или CPUUtilization (если ваше приложение запускает большое использование ЦП при обработке запроса). Вы также можете создать собственную метрику и запустить ее, когда ваш экземпляр неактивен (в зависимости от приложения, которое выполняется в вашем экземпляре).

Проблема с этим вариантом заключается в том, что вы будете тратить уже оплаченные минуты (AWS всегда заряжает полный час, независимо от того, используете ли вы свой экземпляр в течение 15 минут).

2) Лучшим вариантом, на мой взгляд, было бы запустить функцию лямбда один раз в минуту, чтобы проверить, не запущены ли ваши экземпляры и закрыты ли они, только если они близки к полному часу.

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

Возможно, вы можете использовать these instructions.

Но я пробовал эти инструкции, и это не сработало, если я вручную не зашел в консоль, чтобы связать правило с целью. (Несмотря на отправку вызова API put_target)

Кроме того, я не понимаю, что такое последний шаг в этих инструкциях. Я этого не делал, потому что это казалось неприменимым, но, возможно, именно поэтому мой не работает.

Смежные вопросы