Detecte interrupções de instâncias spot usando o SDK do ECS, os metadados da instância ou o Cloud Monitor, e responda com um encerramento controlado ou persistência de dados.
Detectar interrupções
Consultar usando o SDK do ECS
Chame a operação DescribeInstances para consultar os detalhes da instância. verifique o campo OperationLocks retornado para determinar se a instância entrou no estado pending release.
Se a resposta estiver vazia, a instância ainda está disponível.
Se LockReason for Recycling, a instância spot foi interrompida e está com liberação pendente.
Exemplo de uso do SDK
Pré-requisitos
-
crie um accesskey
Uma conta Alibaba Cloud tem permissões totais para todos os recursos. Se o AccessKey dela for comprometido, seus recursos correrão alto risco. Em vez disso, use um AccessKey de usuário RAM com as permissões mínimas necessárias. Consulte Create an AccessKey.
-
Conceda permissões do ECS ao usuário RAM
Conceda ao usuário RAM permissões e gerencie recursos do ECS. O código de exemplo requer permissão para consultar informações da instância. Conceda a seguinte política do sistema:
Produtos cloud
Permissão concedida
Elastic Compute Service (ECS)
Política do sistema: AliyunECSFullAccess
-
Configure as credenciais de acesso
O código de exemplo lê o AccessKey das variáveis de ambiente do sistema para autenticar as solicitações. Consulte Configure environment variables on Linux, macOS, and Windows.
-
instale o SDK do ECS
Obtenha o SDK do ECS. Este exemplo usa o Maven. Para outros métodos de instalação, consulte Instalar o SDK do ECS para Java.
Inicialize o cliente
Os SDKs da Alibaba Cloud suportam vários tipos de credenciais para inicialização do cliente, como AccessKey e token STS. Para outras opções, consulte Manage access credentials. Este exemplo inicializa o cliente com um AccessKey.
import com.aliyun.ecs20140526.Client;
import com.aliyun.teaopenapi.models.Config;
public class Sample {
private static Client createClient() throws Exception {
Config config = new Config()
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set.
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set.
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// Endpoint reference: https://api.alibabacloud.com/product/Ecs
.setEndpoint("ecs.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
}
Construa o objeto de solicitação
Antes de construir a solicitação, consulte API documentation para obter detalhes sobre os parâmetros.
// Build the request object
DescribeInstancesRequest request = new DescribeInstancesRequest().setRegionId("cn-hangzhou");
Faça a chamada
Ao chamar operações da OpenAPI, configure parâmetros de tempo de execução, como timeout e configurações de proxy. Consulte Advanced configuration.
// Set runtime options
RuntimeOptions runtime = new RuntimeOptions();
// Call the DescribeInstances operation
DescribeInstancesResponse response = client.describeInstancesWithOptions(request, runtime);
System.out.println(response.body.toMap());
Trate as exceções
O SDK para Java categoriza as exceções em TeaUnretryableException e TeaException:
TeaUnretryableException: Geralmente ocorre devido a problemas de rede após o sistema atingir o número máximo de tentativas.
TeaException: Ocorre principalmente devido a erros relacionados à lógica de negócios.
Implemente um tratamento de exceções adequado, como propagar exceções, registrar erros em log ou tentar a recuperação, para garantir a robustez do sistema.
Exemplo completo
import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.DescribeInstancesRequest;
import com.aliyun.ecs20140526.models.DescribeInstancesResponse;
import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaUnretryableException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.alibaba.fastjson.JSONArray;
import java.util.Arrays;
public class Sample {
private static Client createClient() throws Exception {
Config config = new Config()
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set.
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set.
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// Endpoint reference: https://api.alibabacloud.com/product/Ecs
.setEndpoint("ecs.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
public static void main(String[] args) {
try {
Client client = Sample.createClient();
// Build the request object
// Specify one or more ECS instance IDs to query.
JSONArray instanceIds = new JSONArray();
instanceIds.addAll(Arrays.asList("i-bp145cvd0exyqj****","i-bp1gehfgfrrk4lah****"));
DescribeInstancesRequest request = new DescribeInstancesRequest()
.setRegionId("cn-hangzhou")
.setInstanceIds(instanceIds.toJSONString());
// Set runtime options
RuntimeOptions runtime = new RuntimeOptions();
while (!instanceIds.isEmpty()) {
// Call the DescribeInstances operation
DescribeInstancesResponse response = client.describeInstancesWithOptions(request, runtime);
// Get instance details from the response.
DescribeInstancesResponseBody responseBody = response.getBody();
DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstances instanceList = responseBody.getInstances();
// Check instance details and evaluate lockReason values.
if (instanceList != null && instanceList.getInstance()!= null && !instanceList.getInstance().isEmpty()) {
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : instanceList.getInstance()) {
// Print the queried instance ID and zone ID.
System.out.println("result:instance:" + instance.getInstanceId() + ",az:" + instance.getZoneId());
if (instance.getOperationLocks() != null ) {
DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstanceOperationLocks operationLocks = instance.getOperationLocks();
if(operationLocks.getLockReason()!=null && !operationLocks.getLockReason().isEmpty()){
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstanceOperationLocksLockReason lockReason : operationLocks.getLockReason()) {
// If the instance is locked, print its ID and lock reason.
System.out.println("instance:" + instance.getInstanceId() + "-->lockReason:" + lockReason.getLockReason() + ",vmStatus:" + instance.getStatus());
if ("Recycling".equals(lockReason.getLockReason())) {
// Print the ID of the instance scheduled for immediate release.
System.out.println("spot instance will be recycled immediately, instance id:" + instance.getInstanceId());
instanceIds.remove(instance.getInstanceId());
}
}
}
}
}
// If no spot instance is locked yet, query again every two minutes.
System.out.print("try describeInstances again later ...");
Thread.sleep(2 * 60 * 1000);
} else {
break;
}
}
} catch (TeaUnretryableException ue) {
// Print only for demonstration. Never ignore exceptions in production code.
ue.printStackTrace();
// Print error message
System.out.println(ue.getMessage());
// Print request details for debugging
System.out.println(ue.getLastRequest());
} catch (TeaException e) {
// Print only for demonstration. Never ignore exceptions in production code.
e.printStackTrace();
// Print error code
System.out.println(e.getCode());
// Print error message (includes RequestId)
System.out.println(e.getMessage());
// Print detailed server-side error content
System.out.println(e.getData());
} catch (Exception e) {
// Print only for demonstration. Never ignore exceptions in production code.
e.printStackTrace();
}
}
}
Resultados retornados
Quando ocorre uma liberação, a saída é:
result:instance:i-bp1i9c3qiv1qs6nc****,az:cn-hangzhou-i
instance:i-bp1i9c3qiv1qs6nc****-->lockReason:Recycling,vmStatus:Stopped
spot instance will be recycled immediately, instance id:i-bp1i9c3qiv1qs6nc****
Consultar a partir da instância usando metadados
Acesse o service de metadados a partir de uma instância ECS para verificar quando a instância spot será encerrada. Consulte Instance metadata.
Caminho dos metadados para o horário de encerramento de uma instância spot: instance/spot/termination-time
Resultados:
Se a resposta for 404, a instância ainda está disponível.
Se a resposta retornar um carimbo de data/hora UTC como
2015-01-05T18:02:00Z, a instância será recuperada nesse horário.
Exemplos:
Instância Linux
# Get a metadata service token for authentication
TOKEN=`curl -X PUT "http://100.100.100.200/latest/api/token" -H "X-aliyun-ecs-metadata-token-ttl-seconds:<metadata service token TTL>"`
# Check whether the spot instance is scheduled for interruption
curl -H "X-aliyun-ecs-metadata-token: $TOKEN" http://100.100.100.200/latest/meta-data/instance/spot/termination-time
Instância Windows
# Get a metadata service token for authentication
$token = Invoke-RestMethod -Headers @{"X-aliyun-ecs-metadata-token-ttl-seconds" = "<metadata service token TTL>"} -Method PUT -Uri http://100.100.100.200/latest/api/token
# Check whether the spot instance is scheduled for interruption
Invoke-RestMethod -Headers @{"X-aliyun-ecs-metadata-token" = $token} -Method GET -Uri http://100.100.100.200/latest/meta-data/instance/spot/termination-time
Consultar com o SDK do Cloud Monitor
Os eventos do ECS são sincronizados com o Cloud Monitor. Chame a operação DescribeSystemEventAttribute para consultar eventos de interrupção de instância spot (Instance:PreemptibleInstanceInterruption). Se o campo content contiver delete, a instância spot está programada para recuperação.
Exemplo de uso do SDK
Pré-requisitos
-
crie um accesskey
Uma conta Alibaba Cloud tem permissões totais para todos os recursos. Se o AccessKey dela for comprometido, seus recursos correrão alto risco. Em vez disso, use um AccessKey de usuário RAM com as permissões mínimas necessárias. Consulte Create an AccessKey.
-
Conceda permissões do Cloud Monitor ao usuário RAM
Conceda ao usuário RAM permissões e gerencie o Cloud Monitor (CMS). O código de exemplo requer permissão para consultar eventos do sistema. Conceda a seguinte política:
Produtos cloud
Permissão concedida
Cloud Monitor (CMS)
AliyunCloudMonitorFullAccess
-
Configure as credenciais de acesso
O código de exemplo lê o AccessKey das variáveis de ambiente do sistema para autenticar as solicitações. Consulte Configure environment variables on Linux, macOS, and Windows.
-
instale o SDK do CMS
Obtenha o SDK do CMS. Este exemplo usa o Maven. Para outros métodos de instalação, consulte Instalar o SDK do CMS para Java.
Inicialize o cliente
Os SDKs da Alibaba Cloud suportam vários tipos de credenciais para inicialização do cliente, como AccessKey e token STS. Para outras opções, consulte Manage access credentials. Este exemplo inicializa o cliente com um AccessKey.
import com.aliyun.cms20190101.Client;
import com.aliyun.teaopenapi.models.Config;
public class Sample {
private static Client createClient() throws Exception {
Config config = new Config()
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set.
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set.
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// Endpoint reference: https://api.alibabacloud.com/product/Ecs
.setEndpoint("metrics.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
}
Construa o objeto de solicitação
Configure os parâmetros de consulta para eventos de interrupção de instância spot. Para outros parâmetros, consulte DescribeSystemEventAttribute.
API | Parâmetro | Valor de exemplo |
Product | Abreviação do serviço: ECS | |
EventType | Tipo de evento: StatusNotification | |
Name | Nome do evento: Instance:PreemptibleInstanceInterruption |
// Build the request object
DescribeSystemEventAttributeRequest request = new DescribeSystemEventAttributeRequest()
.setProduct("ECS")
.setEventType("StatusNotification")
.setName("Instance:PreemptibleInstanceInterruption");
Faça a chamada
Ao chamar operações da OpenAPI, configure parâmetros de tempo de execução, como timeout e configurações de proxy. Consulte Advanced configuration.
// Set runtime options
RuntimeOptions runtime = new RuntimeOptions();
// Call the DescribeSystemEventAttribute operation
DescribeSystemEventAttributeResponse response = client.describeSystemEventAttributeWithOptions(request, runtime);
System.out.println(response.body.toMap());
Trate as exceções
O SDK para Java categoriza as exceções em TeaUnretryableException e TeaException:
TeaUnretryableException: Geralmente ocorre devido a problemas de rede após o sistema atingir o número máximo de tentativas.
TeaException: Ocorre principalmente devido a erros relacionados à lógica de negócios.
Implemente um tratamento de exceções adequado, como propagar exceções, registrar erros em log ou tentar a recuperação, para garantir a robustez do sistema.
Exemplo completo
import com.aliyun.cms20190101.Client;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.cms20190101.models.DescribeSystemEventAttributeRequest;
import com.aliyun.cms20190101.models.DescribeSystemEventAttributeResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaUnretryableException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
public class Sample {
private static Client createClient() throws Exception {
Config config = new Config()
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set.
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set.
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// Endpoint reference: https://api.alibabacloud.com/product/Ecs
.setEndpoint("metrics.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
public static void main(String[] args) {
try {
Client client = Sample.createClient();
// Build the request object
DescribeSystemEventAttributeRequest request = new DescribeSystemEventAttributeRequest()
.setProduct("ECS")
.setEventType("StatusNotification")
.setName("Instance:PreemptibleInstanceInterruption");
// Set runtime options
RuntimeOptions runtime = new RuntimeOptions();
// Call the DescribeSystemEventAttribute operation
DescribeSystemEventAttributeResponse response = client.describeSystemEventAttributeWithOptions(request, runtime);
System.out.println(response.body.toMap());
} catch (TeaUnretryableException ue) {
// Print only for demonstration. Never ignore exceptions in production code.
ue.printStackTrace();
// Print error message
System.out.println(ue.getMessage());
// Print request details for debugging
System.out.println(ue.getLastRequest());
} catch (TeaException e) {
// Print only for demonstration. Never ignore exceptions in production code.
e.printStackTrace();
// Print error code
System.out.println(e.getCode());
// Print error message (includes RequestId)
System.out.println(e.getMessage());
// Print detailed server-side error content
System.out.println(e.getData());
} catch (Exception e) {
// Print only for demonstration. Never ignore exceptions in production code.
e.printStackTrace();
}
}
}
Resultado
Interprete a resposta para identificar eventos de interrupção de instância spot.
Notificação de evento no formato JSON:
{
"ver": "1.0",
"id": "2256A988-0B26-4E2B-820A-8A********E5",
"product": "ECS",
"resourceId": "acs:ecs:cn-hangzhou:169070********30:instance/i-bp1ecr********5go2go",
"level": "INFO",
"name": "Instance:PreemptibleInstanceInterruption",
"userId": "169070********30",
"eventTime": "20190409T121826.922+0800",
"regionId": "cn-hangzhou",
"content": {
"instanceId": "i-bp1ecr********5go2go",
"action": "delete"
}
}
A seguir, a descrição do campo content. Para detalhes dos parâmetros, consulte DescribeSystemEventAttribute.
|
Campo |
Descrição |
Valor de exemplo |
|
instanceId |
O id da instância spot. |
i-bp1ecr****5go2go |
|
action |
O evento da operação. O valor delete indica que a instância foi interrompida e será recuperada à força. |
delete |
Assinar eventos do Cloud Monitor
Assine os eventos do Cloud Monitor para monitorar interrupções de instâncias spot em tempo real. O sistema envia notificações por canais como mensagens de texto, e-mail, Function Compute, Simple Message Queue ou webhook.
Fluxo de trabalho
Procedimento
-
Prepare o canal de recebimento
Fila de mensagens leve
Faça login no console do Simple Message Queue (antigo MNS).
No painel de navegação à esquerda, escolha .
Na barra de navegação superior, selecione uma região.
Na página Queues, clique em Create Queue.
-
No painel Create Queue, configure os seguintes parâmetros e clique em OK:
Name: o nome da fila.
Maximum Message Length: o tamanho máximo da mensagem enviada à fila.
Long Polling Period: a duração máxima em que o sistema mantém as solicitações de long polling após a chamada da operação ReceiveMessage.
Visibility Timeout Period: a duração em que uma mensagem permanece no estado Inactive após a sua recepção na fila.
Message Retention Period: o tempo máximo de retenção de uma mensagem na fila. Após o período que você especifique, o sistema exclua a mensagem, independentemente de sua recepção.
Message Delay Period: o período após o qual o sistema consome todas as mensagens enviadas para a fila.
Enable Logging Feature: defina se o recurso de log deve ser ativado. Se necessário, ative o log.
Após a criação, a fila aparece na página Queues.
Webhook
ImportanteImplante o service de webhook em um servidor acessível pela Internet. Certifique-se de permitir o tráfego de entrada na porta de resposta.
Código de exemplo em Java:
import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class WebhookController { @PostMapping("/callback") public ResponseEntity<String> receiveWebhook(@RequestBody String payload) { // Process the payload, such as logging or executing business logic System.out.println("Received webhook payload: " + payload); // Return a success response return ResponseEntity.ok("Webhook received"); } } -
Crie uma política de assinatura
Faça login no console do Cloud Monitor.
No painel de navegação à esquerda, escolha .
Na aba Subscription Policies, clique em Create Subscription Policy.
-
Na página Create Subscription Policy, configure os parâmetros da política.
Este exemplo aborda apenas os parâmetros relevantes para eventos de interrupção de instância spot. Para todos os parâmetros, consulte Manage event subscriptions (recommended).
Basic Information: Insira um Name e uma Description para a política de assinatura.
-
Alert Subscription:
Subscription Type: Selecione System Events.
Subscription Scope:
Service: Selecione ECS.
Event Type: Selecione Status Notification.
Event Name: Selecione Spot Instance Interruption Notification.
Event Severity: Selecione Warning.
Application Groups, Event Content e Event Resource: Deixe esses parâmetros vazios para assinar todos os eventos do sistema ECS com o nome Spot Instance Interruption Notification em todos os grupos de aplicativos da sua conta.
Noise Reduction: Use o valor padrão.
Notification: O The Custom Notification Method usa o método padrão.
Push and Integration: Clique em Add Channel. Na janela pop-up, clique em Add Channel, selecione o canal preparado na Etapa 1 como Target Type e preencha os campos restantes. Para detalhes sobre o canal de push, consulte Manage push channels.
-
Simule um evento de interrupção
As interrupções de instâncias spot ocorrem de forma passiva, dificultando a depuração do código de tratamento de interrupções. Use o recurso Debug Event Subscription para simular um evento de interrupção de instância spot.
Na aba Subscription Policies, clique em Debug Event Subscription.
-
No painel Create Event Debug, defina Service como ECS e Name como Spot Instance Interruption Notification.
O sistema gera um payload de depuração no formato JSON. Substitua os placeholders relacionados a recursos pelos valores reais da instância spot a ser simulada.
Substitua
Alibaba Cloud account UIDpelo UID da sua conta Alibaba Cloud.Substitua
<resource-id>e<instanceId>pelo ID da instância spot.-
Substitua
<region ID>pelo ID da região da instância spot.{ "product": "ECS", "resourceId": "acs:ecs:cn-shanghai:Alibaba Cloud account UID:instance/<resource-id>", "level": "WARN", "instanceName": "instanceName", "regionId": "<region ID>", "groupId": "0", "name": "Instance:PreemptibleInstanceInterruption", "content": { "instanceId": "i-2zeg014dfo4y892z***", "instanceName": "wor***b73", "action": "delete" }, "status": "Normal" }
-
Clique em OK.
O sistema exibe a mensagem The operation is successful. e envia uma notificação de alerta de teste com base na sua política de assinatura.
-
Receba e visualize notificações
Fila de mensagens leve
Faça login no console do Simple Message Queue (antigo MNS). No painel de navegação à esquerda, clique em Queues.
Na barra de navegação superior, selecione uma região. Na página Queues, encontre a fila de destino e clique em Action > Send Messages.
Opcional: Na página Send/Receive Messages Quick Experience, clique em Edit Parameters of Receiving Messages e edite os parâmetros. No painel Edit Parameters of Receiving Messages, defina Receive Times e Polling Period e clique em OK.
Na página Queue Send/Receive Messages Quick Experience, clique em Receive Message. A lista de mensagens aparece na seção Received Messages.
Opcional: Na lista de mensagens, encontre a mensagem de destino, clique em Details na coluna Actions e visualize o conteúdo da mensagem na caixa de diálogo Message Details.
Webhook
Verifique os logs de invocação e o conteúdo da notificação no seu aplicativo de webhook implantado.
Responder a interrupções
Sua estratégia de resposta depende do seu cenário de negócios. Teste seu aplicativo para garantir que ele lide com interrupções de instâncias spot de forma controlada. Considere as seguintes abordagens:
-
Tratamento controlado de interrupções
Responda prontamente aos sinais de interrupção: salve o progresso da tarefa, limpe os recursos e encerre a execução.
-
Persistência de dados e checkpoints
Salve periodicamente o progresso da tarefa e os resultados intermediários em um armazenamento persistente, como arquivos locais ou bancos de dados, para preservar dados críticos de negócios. Consulte Data retention and recovery for spot instances.
-
Teste o sucesso da integração
Acione um evento de teste no Cloud Monitor para verificar se o seu programa responde conforme o esperado. Consulte Handle interruption events with SMQ.