Gestione degli eventi Amazon ECS
Amazon ECS invia gli eventi secondo il criterio almeno una volta. Ciò significa che è possibile ricevere più copie di un determinato evento. Inoltre, gli eventi potrebbero non essere inviati al listener di eventi nell'ordine in cui si sono verificati.
Per ordinare correttamente gli eventi, la sezione detail di ogni evento contiene una proprietà version. Ogni volta che una risorsa cambia stato, avviene un incremento di version. Gli eventi duplicati hanno la stessa version nell'oggetto detail. Se esegui la replica dell'istanza di container Amazon ECS e dello stato del processo con EventBridge, puoi confrontare la versione di una risorsa riportata dalle API di Amazon ECS con version riportata in EventBridge per la risorsa per verificare che la versione del flusso di eventi sia corrente. Gli eventi con un numero di proprietà di versione più alto devono essere considerati come eventi successivi a quelli aventi numeri di versione più bassi.
Esempio: gestione degli eventi in una funzione AWS Lambda
Nell'esempio seguente viene riportata una funzione Lambda scritta in Python 3.9, la quale acquisisce sia eventi di modifica dello stato delle istanze di container che dei processi e li salva in una delle due tabelle Amazon DynamoDB:
-
ECSCtrInstanceState: archivia lo stato più recente di un'istanza di container. L'ID tabella è il valore
containerInstanceArndell'istanza di container; -
ECSTaskState: archivia lo stato più recente di un processo. L'ID tabella è il valore
taskArndell'attività.
import json import boto3 def lambda_handler(event, context): id_name = "" new_record = {} # For debugging so you can see raw event format. print('Here is the event:') print((json.dumps(event))) if event["source"] != "aws.ecs": raise ValueError("Function only supports input from events with a source type of: aws.ecs") # Switch on task/container events. table_name = "" if event["detail-type"] == "ECS Task State Change": table_name = "ECSTaskState" id_name = "taskArn" event_id = event["detail"]["taskArn"] elif event["detail-type"] == "ECS Container Instance State Change": table_name = "ECSCtrInstanceState" id_name = "containerInstanceArn" event_id = event["detail"]["containerInstanceArn"] else: raise ValueError("detail-type for event is not a supported type. Exiting without saving event.") new_record["cw_version"] = event["version"] new_record.update(event["detail"]) # "status" is a reserved word in DDB, but it appears in containerPort # state change messages. if "status" in event: new_record["current_status"] = event["status"] new_record.pop("status") # Look first to see if you have received a newer version of an event ID. # If the version is OLDER than what you have on file, do not process it. # Otherwise, update the associated record with this latest information. print("Looking for recent event with same ID...") dynamodb = boto3.resource("dynamodb", region_name="us-east-1") table = dynamodb.Table(table_name) saved_event = table.get_item( Key={ id_name : event_id } ) if "Item" in saved_event: # Compare events and reconcile. print(("EXISTING EVENT DETECTED: Id " + event_id + " - reconciling")) if saved_event["Item"]["version"] < event["detail"]["version"]: print("Received event is a more recent version than the stored event - updating") table.put_item( Item=new_record ) else: print("Received event is an older version than the stored event - ignoring") else: print(("Saving new event - ID " + event_id)) table.put_item( Item=new_record )
Nell'esempio seguente di Fargate viene riportata una funzione Lambda scritta in Python 3.9, la quale acquisisce eventi di modifica dello stato del processo e li salva nella tabella Amazon DynamoDB seguente:
import json import boto3 def lambda_handler(event, context): id_name = "" new_record = {} # For debugging so you can see raw event format. print('Here is the event:') print((json.dumps(event))) if event["source"] != "aws.ecs": raise ValueError("Function only supports input from events with a source type of: aws.ecs") # Switch on task/container events. table_name = "" if event["detail-type"] == "ECS Task State Change": table_name = "ECSTaskState" id_name = "taskArn" event_id = event["detail"]["taskArn"] else: raise ValueError("detail-type for event is not a supported type. Exiting without saving event.") new_record["cw_version"] = event["version"] new_record.update(event["detail"]) # "status" is a reserved word in DDB, but it appears in containerPort # state change messages. if "status" in event: new_record["current_status"] = event["status"] new_record.pop("status") # Look first to see if you have received a newer version of an event ID. # If the version is OLDER than what you have on file, do not process it. # Otherwise, update the associated record with this latest information. print("Looking for recent event with same ID...") dynamodb = boto3.resource("dynamodb", region_name="us-east-1") table = dynamodb.Table(table_name) saved_event = table.get_item( Key={ id_name : event_id } ) if "Item" in saved_event: # Compare events and reconcile. print(("EXISTING EVENT DETECTED: Id " + event_id + " - reconciling")) if saved_event["Item"]["version"] < event["detail"]["version"]: print("Received event is a more recent version than the stored event - updating") table.put_item( Item=new_record ) else: print("Received event is an older version than the stored event - ignoring") else: print(("Saving new event - ID " + event_id)) table.put_item( Item=new_record )