

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Operazioni in batch per Amazon SQS
<a name="sqs-batch-api-actions"></a>

Amazon SQS offre azioni in batch per aiutarti a ridurre i costi e manipolare fino a 10 messaggi con una sola azione. Queste azioni in batch includono:
+ `[SendMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html)`
+ `[DeleteMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessageBatch.html)`
+ `[ChangeMessageVisibilityBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ChangeMessageVisibilityBatch.html)`

Utilizzando le azioni in batch, è possibile eseguire più operazioni in una singola chiamata API, il che aiuta a ottimizzare le prestazioni e ridurre i costi. Puoi sfruttare la funzionalità batch utilizzando l'API di interrogazione o qualsiasi AWS SDK che supporti le azioni batch di Amazon SQS.

**Dettagli importanti**
+ **Limite di dimensione dei messaggi:** la dimensione totale di tutti i messaggi inviati in una singola `SendMessageBatch` chiamata non può superare 1.048.576 byte (1 MiB)
+ **Autorizzazioni:** non è possibile impostare esplicitamente le autorizzazioni per, o. `SendMessageBatch` `DeleteMessageBatch` `ChangeMessageVisibilityBatch` Invece, imposta o `ChangeMessageVisibility` imposta le autorizzazioni per `SendMessage` le versioni batch corrispondenti delle azioni. `DeleteMessage`
+ **Supporto console:** la console Amazon SQS non supporta azioni in batch. È necessario utilizzare l'API di interrogazione o un AWS SDK per eseguire operazioni in batch.

## Raggruppamento delle azioni con messaggio
<a name="batching-message-actions"></a>

Per ottimizzare ulteriormente i costi e l'efficienza, prendi in considerazione le seguenti best practice per il raggruppamento in batch delle azioni relative ai messaggi:
+ **Azioni API in batch: utilizza le azioni** dell'[API batch di Amazon SQS](#sqs-batch-api-actions) per inviare, ricevere ed eliminare messaggi e per modificare il timeout di visibilità dei messaggi per più messaggi con una singola azione. Ciò riduce il numero di chiamate API e i costi associati.
+ **Buffering lato client e long polling:** [combina il buffering lato client con il batching delle richieste utilizzando il polling lungo insieme al client asincrono bufferizzato incluso in.](sqs-client-side-buffering-request-batching.md) AWS SDK per Java Questo approccio aiuta a ridurre al minimo il numero di richieste e ottimizza la gestione di grandi volumi di messaggi.

**Nota**  
L'Amazon SQS Buffered Asynchronous Client attualmente non supporta le code FIFO.

# Abilitazione del buffering lato client e del batching delle richieste con Amazon SQS
<a name="sqs-client-side-buffering-request-batching"></a>

[AWS SDK per Java](https://aws.amazon.com/sdkforjava/) include `AmazonSQSBufferedAsyncClient` che accede ad Amazon SQS. Questo client consente un semplice raggruppamento delle richieste utilizzando il buffering lato client. Le chiamate effettuate dal client vengono prima memorizzate nel buffer e quindi inviate come richiesta batch ad Amazon SQS.

Il buffering lato client consente di memorizzare e inviare fino a 10 richieste in batch, riducendo il costo di utilizzo di Amazon SQS e il numero di richieste inviate. `AmazonSQSBufferedAsyncClient` effettua il buffering delle chiamate sincrone e asincrone. Le richieste in batch e il supporto per il [polling lungo](sqs-short-and-long-polling.md) possono inoltre contribuire ad aumentare il throughput. Per ulteriori informazioni, consulta [Aumento del throughput utilizzando la scalabilità orizzontale e l'action batching con Amazon SQS](sqs-throughput-horizontal-scaling-and-batching.md).

Poiché `AmazonSQSBufferedAsyncClient` implementa la stessa interfaccia di `AmazonSQSAsyncClient`, la migrazione da `AmazonSQSAsyncClient` a `AmazonSQSBufferedAsyncClient` di solito richiede solo modifiche minime al codice esistente.

**Nota**  
L'Amazon SQS Buffered Asynchronous Client attualmente non supporta le code FIFO.

## Usare Amazon SQSBuffered AsyncClient
<a name="using-buffered-async-client"></a>

Prima di iniziare, completa i passaggi descritti in [Configurazione di Amazon SQS](sqs-setting-up.md). 

### AWS SDK per Java 1.x
<a name="using-buffered-async-client-java1"></a>

Per AWS SDK for Java 1.x, puoi crearne uno `AmazonSQSBufferedAsyncClient` nuovo basato sul seguente esempio:

```
// Create the basic Amazon SQS async client
final AmazonSQSAsync sqsAsync = new AmazonSQSAsyncClient();
 
// Create the buffered client
final AmazonSQSAsync bufferedSqs = new AmazonSQSBufferedAsyncClient(sqsAsync);
```

Una volta creato il nuovo `AmazonSQSBufferedAsyncClient`, è possibile utilizzarlo per l'invio di più richieste ad Amazon SQS; (proprio come con `AmazonSQSAsyncClient`), ad esempio:

```
final CreateQueueRequest createRequest = new CreateQueueRequest().withQueueName("MyQueue");
 
final CreateQueueResult res = bufferedSqs.createQueue(createRequest);
 
final SendMessageRequest request = new SendMessageRequest();
final String body = "Your message text" + System.currentTimeMillis();
request.setMessageBody( body );
request.setQueueUrl(res.getQueueUrl());
 
final Future<SendMessageResult> sendResult = bufferedSqs.sendMessageAsync(request);
 
final ReceiveMessageRequest receiveRq = new ReceiveMessageRequest()
    .withMaxNumberOfMessages(1)
    .withQueueUrl(queueUrl);
final ReceiveMessageResult rx = bufferedSqs.receiveMessage(receiveRq);
```

### Configurazione di Amazon SQSBuffered AsyncClient
<a name="configuring-buffered-async-client"></a>

`AmazonSQSBufferedAsyncClient` è preconfigurato con impostazioni che funzionano per la maggior parte dei casi d'uso. È possibile configurare ulteriormente `AmazonSQSBufferedAsyncClient`, ad esempio:

1. Crea un'istanza della classe `QueueBufferConfig` con i parametri di configurazione obbligatori.

1. Fornisci l'istanza al costruttore `AmazonSQSBufferedAsyncClient`.

```
// Create the basic Amazon SQS async client
final AmazonSQSAsync sqsAsync = new AmazonSQSAsyncClient();
 
final QueueBufferConfig config = new QueueBufferConfig()
    .withMaxInflightReceiveBatches(5)
    .withMaxDoneReceiveBatches(15);
 
// Create the buffered client
final AmazonSQSAsync bufferedSqs = new AmazonSQSBufferedAsyncClient(sqsAsync, config);
```


**QueueBufferConfig parametri di configurazione**  

| Parametro | Valore predefinito | Description | 
| --- | --- | --- | 
| longPoll | true |  Quando `longPoll` è impostato su `true`, `AmazonSQSBufferedAsyncClient` tenta di utilizzare il polling lungo durante l'utilizzo dei messaggi.  | 
| longPollWaitTimeoutSeconds | 20 s |  Il tempo massimo, in secondi, che una chiamata di `ReceiveMessage` si blocca sul server in attesa che i messaggi compaiano nella coda prima di restituire un risultato di ricezione vuoto.  Questa impostazione non ha alcun effetto se il polling lungo è disattivato.   | 
| maxBatchOpenMs | 200 ms |  Il tempo massimo, in millisecondi, che una chiamata in uscita attende altre chiamate dello stesso tipo con cui raggrupparsi. Maggiore è l'impostazione, minore è il numero di batch necessari per eseguire la stessa quantità di lavoro (tuttavia, la prima chiamata in un batch deve dedicare più tempo all'attesa). Quando questo parametro è impostato su `0`, le richieste inviate non attendono altre richieste, disabilitando effettivamente il batching.  | 
| maxBatchSize | 10 richieste per batch |  Il numero massimo di messaggi raggruppati in una singola richiesta. Maggiore è l'impostazione, minore è il numero di batch che sono necessari per eseguire la stessa quantità di richieste.  10 richieste per batch è il valore massimo consentito per Amazon SQS.   | 
| maxBatchSizeBytes | 1 MiB |  Le dimensioni massime del batch di un messaggio, in byte, che il client tenta di inviare ad Amazon SQS .  1 MiB è il valore massimo consentito per Amazon SQS.   | 
| maxDoneReceiveBatches | 10 batch |  Il numero massimo di pre-fetching e archiviazioni di batch `AmazonSQSBufferedAsyncClient` sul lato client. Maggiore è l'impostazione, più richieste di ricezione possono essere soddisfatte senza la necessità di effettuare una chiamata ad Amazon SQS (tuttavia, più messaggi sono pre-recuperati, più tempo rimangono nel buffer, il che significa che il loro timeout visibilità scade).  `0`indica che il precaricamento di tutti i messaggi è disabilitato e che i messaggi vengono consumati solo su richiesta.   | 
| maxInflightOutboundBatches | 5 batch |  Il numero massimo di batch in uscita attivi che possono essere elaborati contemporaneamente. Maggiore è l'impostazione, più rapidamente possono essere inviati i batch in uscita (in base alle altre quote, ad esempio CPU o larghezza di banda) e più thread possono essere utilizzati da `AmazonSQSBufferedAsyncClient`.  | 
| maxInflightReceiveBatches | 10 batch |  Il numero massimo di batch di ricezione attivi che possono essere elaborati contemporaneamente. Maggiore è l'impostazione e più messaggi possono essere ricevuti (in base alle quote, ad esempio CPU o larghezza di banda) e più thread possono essere utilizzati da `AmazonSQSBufferedAsyncClient`.  `0`indica che la prelettura di tutti i messaggi è disabilitata e che i messaggi vengono consumati solo su richiesta.   | 
| visibilityTimeoutSeconds | -1 |  Quando questo parametro è impostato su un valore diverso da zero, questo timeout visibilità sostituisce il timeout visibilità impostato sulla coda dalla quale vengono utilizzati i messaggi.  `-1` indica che per la coda è selezionata l'impostazione predefinita. Non è possibile impostare il timeout visibilità su `0`.   | 

### AWS SDK per Java 2.x
<a name="using-buffered-async-client-java2"></a>

Per AWS SDK for Java 2.x, puoi crearne uno `SqsAsyncBatchManager` nuovo basato sul seguente esempio:

```
// Create the basic Sqs Async Client
SqsAsyncClient sqs = SqsAsyncClient.builder() 
    .region(Region.US_EAST_1) 
    .build();

// Create the batch manager
SqsAsyncBatchManager sqsAsyncBatchManager = sqs.batchManager();
```

Una volta creato il nuovo `SqsAsyncBatchManager`, è possibile utilizzarlo per l'invio di più richieste ad Amazon SQS; (proprio come con `SqsAsyncClient`), ad esempio:

```
final String queueName = "MyAsyncBufferedQueue" + UUID.randomUUID();
final CreateQueueRequest request = CreateQueueRequest.builder().queueName(queueName).build();
final String queueUrl = sqs.createQueue(request).join().queueUrl();
System.out.println("Queue created: " + queueUrl);


// Send messages
CompletableFuture<SendMessageResponse> sendMessageFuture;
for (int i = 0; i < 10; i++) {
    final int index = i;
    sendMessageFuture = sqsAsyncBatchManager.sendMessage(
            r -> r.messageBody("Message " + index).queueUrl(queueUrl));
    SendMessageResponse response= sendMessageFuture.join();
    System.out.println("Message " + response.messageId() + " sent!");
}

// Receive messages with customized configurations
CompletableFuture<ReceiveMessageResponse> receiveResponseFuture = customizedBatchManager.receiveMessage(
        r -> r.queueUrl(queueUrl)
                .waitTimeSeconds(10)
                .visibilityTimeout(20)
                .maxNumberOfMessages(10)
);
System.out.println("You have received " + receiveResponseFuture.join().messages().size() + " messages in total.");

// Delete messages
DeleteQueueRequest deleteQueueRequest =  DeleteQueueRequest.builder().queueUrl(queueUrl).build();
int code = sqs.deleteQueue(deleteQueueRequest).join().sdkHttpResponse().statusCode();
System.out.println("Queue is deleted, with statusCode " + code);
```

### Configurazione SqsAsyncBatchManager
<a name="configuring-SqsAsyncBatchManager"></a>

`SqsAsyncBatchManager` è preconfigurato con impostazioni che funzionano per la maggior parte dei casi d'uso. È possibile configurare ulteriormente `SqsAsyncBatchManager`, ad esempio:

Creazione di una configurazione personalizzata tramite`SqsAsyncBatchManager.Builder`:

```
SqsAsyncBatchManager customizedBatchManager = SqsAsyncBatchManager.builder() 
    .client(sqs)
    .scheduledExecutor(Executors.newScheduledThreadPool(5))
    .overrideConfiguration(b -> b 
        .maxBatchSize(10)
        .sendRequestFrequency(Duration.ofMillis(200))
        .receiveMessageMinWaitDuration(Duration.ofSeconds(10))
        .receiveMessageVisibilityTimeout(Duration.ofSeconds(20)) 
        .receiveMessageAttributeNames(Collections.singletonList("*"))
        .receiveMessageSystemAttributeNames(Collections.singletonList(MessageSystemAttributeName.ALL)))
    .build();
```


**Parametri di `BatchOverrideConfiguration`**  

| Parametro | Valore predefinito | Description | 
| --- | --- | --- | 
| maxBatchSize |  10 richieste per batch  | Il numero massimo di messaggi raggruppati in una singola richiesta. Maggiore è l'impostazione, minore è il numero di batch che sono necessari per eseguire la stessa quantità di richieste.  Il valore massimo consentito per Amazon SQS è di 10 richieste per batch.  | 
| sendRequestFrequency |  200 ms  | Il tempo massimo, in millisecondi, che una chiamata in uscita attende altre chiamate dello stesso tipo con cui raggrupparsi. Maggiore è l'impostazione, minore è il numero di batch necessari per eseguire la stessa quantità di lavoro (tuttavia, la prima chiamata in un batch deve dedicare più tempo all'attesa). Quando questo parametro è impostato su `0`, le richieste inviate non attendono altre richieste, disabilitando effettivamente il batching. | 
| receiveMessageVisibilityTimeout |  -1  | Quando questo parametro è impostato su un valore diverso da zero, questo timeout visibilità sostituisce il timeout visibilità impostato sulla coda dalla quale vengono utilizzati i messaggi.   `1` indica che per la coda è selezionata l'impostazione predefinita. Non è possibile impostare il timeout visibilità su `0`.   | 
| receiveMessageMinWaitDuration |  50 ms  | La quantità minima di tempo (in millisecondi) di attesa di una `receiveMessage` chiamata prima che i messaggi disponibili vengano recuperati. Più alta è l'impostazione, minore è il numero di batch necessari per eseguire lo stesso numero di richieste.  | 

# Aumento del throughput utilizzando la scalabilità orizzontale e l'action batching con Amazon SQS
<a name="sqs-throughput-horizontal-scaling-and-batching"></a>

Amazon SQS supporta la messaggistica ad alto throughput. Per dettagli sui limiti di velocità effettiva, consulta. [Quote di messaggi Amazon SQS](quotas-messages.md)

Per massimizzare la produttività:
+ [Scala](#horizontal-scaling) produttori e consumatori orizzontalmente aggiungendo più istanze di ciascuno.
+ Utilizza l'[action batching](#request-batching) per inviare o ricevere più messaggi in un'unica richiesta, riducendo il sovraccarico delle chiamate API.

## Dimensionamento orizzontale
<a name="horizontal-scaling"></a>

Poiché accedi ad Amazon SQS attraverso un protocollo di richieste/risposte HTTP, la *latenza della richiesta* (l'intervallo di tempo compreso tra l'avvio di una richiesta e la ricezione di una risposta) limita il throughput che puoi ottenere da un singolo thread su un'unica connessione. Ad esempio, se la latenza da un client basato su Amazon EC2 ad Amazon SQS nella stessa regione è in media di 20 ms, la velocità di trasmissione effettiva massima da un singolo thread su un'unica connessione è in media di 50 TPS. 

Per *dimensionamento orizzontale* si intende aumentare il numero di produttori di messaggi (che generano richieste `[SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)`) e di consumatori di messaggi (che generano richieste `[ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)` e `[DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html)`) per aumentare il throughput complessivo della coda. È possibile dimensionare orizzontalmente in tre modi:
+ Aumentare il numero di thread per client
+ Aggiungi altri client
+ Aumentare il numero di thread per client e aggiungere altri client

Aggiungendo più client dovresti ottenere essenzialmente guadagni lineari nel throughput della coda. Ad esempio, se raddoppi il numero di clienti, puoi ottenere il doppio del throughput. 

## Raggruppare le operazioni
<a name="request-batching"></a>

Il *Raggruppamento* esegue più lavoro durante ogni round trip al servizio (ad esempio, quando invii più messaggi con una singola richiesta `SendMessageBatch`). Le operazioni Amazon SQS in batch sono `[SendMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessageBatch.html)`, `[DeleteMessageBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessageBatch.html)` e `[ChangeMessageVisibilityBatch](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ChangeMessageVisibilityBatch.html)`. Per usufruire del batching senza modificare produttori e consumatori, utilizza [Amazon SQS Buffered Asynchronous Client](sqs-client-side-buffering-request-batching.md).

**Nota**  
Poiché `[ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html)` può elaborare 10 messaggi alla volta, non c'è nessuna azione `ReceiveMessageBatch`.

Il raggruppamento distribuisce la latenza dell'operazione in batch su più messaggi in una richiesta batch, invece di accettare l'intera latenza per un solo messaggio (per esempio, una richiesta `[SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html)`). Poiché ogni round trip trasporta più lavoro, le richieste in batch fanno un utilizzo più efficiente di thread e connessioni , migliorano così il throughput.

Puoi abbinare il batching al dimensionamento orizzontale per offrire un throughput con un numero minore di thread, connessioni e richieste rispetto a quelli necessari per richieste di messaggi individuali. Puoi utilizzare le operazioni in batch di Amazon SQS per inviare, ricevere o eliminare fino a 10 messaggi alla volta. Poiché Amazon SQS addebita un costo per richiesta, il raggruppamento è in grado di ridurre in modo significativo i costi. 

Il raggruppamento può introdurre alcune complessità per la tua applicazione (ad esempio, l'applicazione deve accumulare i messaggi prima di inviarli oppure talvolta è necessario attendere di più per una risposta). Tuttavia, il raggruppamento può essere ancora efficace nei seguenti casi: 
+ La tua applicazione genera una notevole quantità di messaggi in un breve periodo di tempo, pertanto il ritardo non è mai molto lungo. 
+ Il consumatore di un messaggio recupera i messaggi da una coda a sua discrezione, a differenza dei tipici produttori di messaggi che devono inviare messaggi in risposta a eventi che non controllano. 

**Importante**  
Una richiesta di batch potrebbe avere esito positivo anche se i singoli messaggi nel batch hanno avuto esito negativo. Dopo una richiesta di batch, verifica sempre la presenza di errori di messaggio individuali e, se necessario, prova nuovamente l'operazione.

## Esempio di utilizzo di Java Working per richieste con operazioni singole e in batch
<a name="working-java-example-batch-requests"></a>

### Prerequisiti
<a name="batch-request-java-example-prerequisites"></a>

Aggiungi i pacchetti `aws-java-sdk-sqs.jar`, `aws-java-sdk-ec2.jar`e `commons-logging.jar` al percorso di classe build Java. L'esempio seguente mostra queste dipendenze in un file `pom.xml` di progetto Maven.

```
<dependencies>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-sqs</artifactId>
        <version>LATEST</version>
    </dependency>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk-ec2</artifactId>
        <version>LATEST</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>LATEST</version>
    </dependency>
</dependencies>
```

### SimpleProducerConsumer.java
<a name="batch-request-java-example-code"></a>

Il seguenti esempio di codice Java implementa un semplice modello produttore-consumatore. Il thread principale genera dinamicamente diversi thread produttore e consumatore che elaborano messaggi di 1 KB per un periodo di tempo specificato. Questo esempio include produttori e consumatori che effettuano richieste con operazioni singole e altri che effettuano richieste in batch.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

import com.amazonaws.AmazonClientException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
import com.amazonaws.services.sqs.model.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Start a specified number of producer and consumer threads, and produce-consume
 * for the least of the specified duration and 1 hour. Some messages can be left
 * in the queue because producers and consumers might not be in exact balance.
 */
public class SimpleProducerConsumer {

    // The maximum runtime of the program.
    private final static int MAX_RUNTIME_MINUTES = 60;
    private final static Log log = LogFactory.getLog(SimpleProducerConsumer.class);

    public static void main(String[] args) throws InterruptedException {

        final Scanner input = new Scanner(System.in);

        System.out.print("Enter the queue name: ");
        final String queueName = input.nextLine();

        System.out.print("Enter the number of producers: ");
        final int producerCount = input.nextInt();

        System.out.print("Enter the number of consumers: ");
        final int consumerCount = input.nextInt();

        System.out.print("Enter the number of messages per batch: ");
        final int batchSize = input.nextInt();

        System.out.print("Enter the message size in bytes: ");
        final int messageSizeByte = input.nextInt();

        System.out.print("Enter the run time in minutes: ");
        final int runTimeMinutes = input.nextInt();

        /*
         * Create a new instance of the builder with all defaults (credentials
         * and region) set automatically. For more information, see Creating
         * Service Clients in the AWS SDK for Java Developer Guide.
         */
        final ClientConfiguration clientConfiguration = new ClientConfiguration()
                .withMaxConnections(producerCount + consumerCount);

        final AmazonSQS sqsClient = AmazonSQSClientBuilder.standard()
                .withClientConfiguration(clientConfiguration)
                .build();

        final String queueUrl = sqsClient
                .getQueueUrl(new GetQueueUrlRequest(queueName)).getQueueUrl();

        // The flag used to stop producer, consumer, and monitor threads.
        final AtomicBoolean stop = new AtomicBoolean(false);

        // Start the producers.
        final AtomicInteger producedCount = new AtomicInteger();
        final Thread[] producers = new Thread[producerCount];
        for (int i = 0; i < producerCount; i++) {
            if (batchSize == 1) {
                producers[i] = new Producer(sqsClient, queueUrl, messageSizeByte,
                        producedCount, stop);
            } else {
                producers[i] = new BatchProducer(sqsClient, queueUrl, batchSize,
                        messageSizeByte, producedCount,
                        stop);
            }
            producers[i].start();
        }

        // Start the consumers.
        final AtomicInteger consumedCount = new AtomicInteger();
        final Thread[] consumers = new Thread[consumerCount];
        for (int i = 0; i < consumerCount; i++) {
            if (batchSize == 1) {
                consumers[i] = new Consumer(sqsClient, queueUrl, consumedCount,
                        stop);
            } else {
                consumers[i] = new BatchConsumer(sqsClient, queueUrl, batchSize,
                        consumedCount, stop);
            }
            consumers[i].start();
        }

        // Start the monitor thread.
        final Thread monitor = new Monitor(producedCount, consumedCount, stop);
        monitor.start();

        // Wait for the specified amount of time then stop.
        Thread.sleep(TimeUnit.MINUTES.toMillis(Math.min(runTimeMinutes,
                MAX_RUNTIME_MINUTES)));
        stop.set(true);

        // Join all threads.
        for (int i = 0; i < producerCount; i++) {
            producers[i].join();
        }

        for (int i = 0; i < consumerCount; i++) {
            consumers[i].join();
        }

        monitor.interrupt();
        monitor.join();
    }

    private static String makeRandomString(int sizeByte) {
        final byte[] bs = new byte[(int) Math.ceil(sizeByte * 5 / 8)];
        new Random().nextBytes(bs);
        bs[0] = (byte) ((bs[0] | 64) & 127);
        return new BigInteger(bs).toString(32);
    }

    /**
     * The producer thread uses {@code SendMessage}
     * to send messages until it is stopped.
     */
    private static class Producer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final AtomicInteger producedCount;
        final AtomicBoolean stop;
        final String theMessage;

        Producer(AmazonSQS sqsQueueBuffer, String queueUrl, int messageSizeByte,
                 AtomicInteger producedCount, AtomicBoolean stop) {
            this.sqsClient = sqsQueueBuffer;
            this.queueUrl = queueUrl;
            this.producedCount = producedCount;
            this.stop = stop;
            this.theMessage = makeRandomString(messageSizeByte);
        }

        /*
         * The producedCount object tracks the number of messages produced by
         * all producer threads. If there is an error, the program exits the
         * run() method.
         */
        public void run() {
            try {
                while (!stop.get()) {
                    sqsClient.sendMessage(new SendMessageRequest(queueUrl,
                            theMessage));
                    producedCount.incrementAndGet();
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("Producer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * The producer thread uses {@code SendMessageBatch}
     * to send messages until it is stopped.
     */
    private static class BatchProducer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final int batchSize;
        final AtomicInteger producedCount;
        final AtomicBoolean stop;
        final String theMessage;

        BatchProducer(AmazonSQS sqsQueueBuffer, String queueUrl, int batchSize,
                      int messageSizeByte, AtomicInteger producedCount,
                      AtomicBoolean stop) {
            this.sqsClient = sqsQueueBuffer;
            this.queueUrl = queueUrl;
            this.batchSize = batchSize;
            this.producedCount = producedCount;
            this.stop = stop;
            this.theMessage = makeRandomString(messageSizeByte);
        }

        public void run() {
            try {
                while (!stop.get()) {
                    final SendMessageBatchRequest batchRequest =
                            new SendMessageBatchRequest().withQueueUrl(queueUrl);

                    final List<SendMessageBatchRequestEntry> entries =
                            new ArrayList<SendMessageBatchRequestEntry>();
                    for (int i = 0; i < batchSize; i++)
                        entries.add(new SendMessageBatchRequestEntry()
                                .withId(Integer.toString(i))
                                .withMessageBody(theMessage));
                    batchRequest.setEntries(entries);

                    final SendMessageBatchResult batchResult =
                            sqsClient.sendMessageBatch(batchRequest);
                    producedCount.addAndGet(batchResult.getSuccessful().size());

                    /*
                     * Because SendMessageBatch can return successfully, but
                     * individual batch items fail, retry the failed batch items.
                     */
                    if (!batchResult.getFailed().isEmpty()) {
                        log.warn("Producer: retrying sending "
                                + batchResult.getFailed().size() + " messages");
                        for (int i = 0, n = batchResult.getFailed().size();
                             i < n; i++) {
                            sqsClient.sendMessage(new
                                    SendMessageRequest(queueUrl, theMessage));
                            producedCount.incrementAndGet();
                        }
                    }
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("BatchProducer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * The consumer thread uses {@code ReceiveMessage} and {@code DeleteMessage}
     * to consume messages until it is stopped.
     */
    private static class Consumer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final AtomicInteger consumedCount;
        final AtomicBoolean stop;

        Consumer(AmazonSQS sqsClient, String queueUrl, AtomicInteger consumedCount,
                 AtomicBoolean stop) {
            this.sqsClient = sqsClient;
            this.queueUrl = queueUrl;
            this.consumedCount = consumedCount;
            this.stop = stop;
        }

        /*
         * Each consumer thread receives and deletes messages until the main
         * thread stops the consumer thread. The consumedCount object tracks the
         * number of messages that are consumed by all consumer threads, and the
         * count is logged periodically.
         */
        public void run() {
            try {
                while (!stop.get()) {
                    try {
                        final ReceiveMessageResult result = sqsClient
                                .receiveMessage(new
                                        ReceiveMessageRequest(queueUrl));

                        if (!result.getMessages().isEmpty()) {
                            final Message m = result.getMessages().get(0);
                            sqsClient.deleteMessage(new
                                    DeleteMessageRequest(queueUrl,
                                    m.getReceiptHandle()));
                            consumedCount.incrementAndGet();
                        }
                    } catch (AmazonClientException e) {
                        log.error(e.getMessage());
                    }
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("Consumer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * The consumer thread uses {@code ReceiveMessage} and {@code
     * DeleteMessageBatch} to consume messages until it is stopped.
     */
    private static class BatchConsumer extends Thread {
        final AmazonSQS sqsClient;
        final String queueUrl;
        final int batchSize;
        final AtomicInteger consumedCount;
        final AtomicBoolean stop;

        BatchConsumer(AmazonSQS sqsClient, String queueUrl, int batchSize,
                      AtomicInteger consumedCount, AtomicBoolean stop) {
            this.sqsClient = sqsClient;
            this.queueUrl = queueUrl;
            this.batchSize = batchSize;
            this.consumedCount = consumedCount;
            this.stop = stop;
        }

        public void run() {
            try {
                while (!stop.get()) {
                    final ReceiveMessageResult result = sqsClient
                            .receiveMessage(new ReceiveMessageRequest(queueUrl)
                                    .withMaxNumberOfMessages(batchSize));

                    if (!result.getMessages().isEmpty()) {
                        final List<Message> messages = result.getMessages();
                        final DeleteMessageBatchRequest batchRequest =
                                new DeleteMessageBatchRequest()
                                        .withQueueUrl(queueUrl);

                        final List<DeleteMessageBatchRequestEntry> entries =
                                new ArrayList<DeleteMessageBatchRequestEntry>();
                        for (int i = 0, n = messages.size(); i < n; i++)
                            entries.add(new DeleteMessageBatchRequestEntry()
                                    .withId(Integer.toString(i))
                                    .withReceiptHandle(messages.get(i)
                                            .getReceiptHandle()));
                        batchRequest.setEntries(entries);

                        final DeleteMessageBatchResult batchResult = sqsClient
                                .deleteMessageBatch(batchRequest);
                        consumedCount.addAndGet(batchResult.getSuccessful().size());

                        /*
                         * Because DeleteMessageBatch can return successfully,
                         * but individual batch items fail, retry the failed
                         * batch items.
                         */
                        if (!batchResult.getFailed().isEmpty()) {
                            final int n = batchResult.getFailed().size();
                            log.warn("Producer: retrying deleting " + n
                                    + " messages");
                            for (BatchResultErrorEntry e : batchResult
                                    .getFailed()) {

                                sqsClient.deleteMessage(
                                        new DeleteMessageRequest(queueUrl,
                                                messages.get(Integer
                                                        .parseInt(e.getId()))
                                                        .getReceiptHandle()));

                                consumedCount.incrementAndGet();
                            }
                        }
                    }
                }
            } catch (AmazonClientException e) {
                /*
                 * By default, AmazonSQSClient retries calls 3 times before
                 * failing. If this unlikely condition occurs, stop.
                 */
                log.error("BatchConsumer: " + e.getMessage());
                System.exit(1);
            }
        }
    }

    /**
     * This thread prints every second the number of messages produced and
     * consumed so far.
     */
    private static class Monitor extends Thread {
        private final AtomicInteger producedCount;
        private final AtomicInteger consumedCount;
        private final AtomicBoolean stop;

        Monitor(AtomicInteger producedCount, AtomicInteger consumedCount,
                AtomicBoolean stop) {
            this.producedCount = producedCount;
            this.consumedCount = consumedCount;
            this.stop = stop;
        }

        public void run() {
            try {
                while (!stop.get()) {
                    Thread.sleep(1000);
                    log.info("produced messages = " + producedCount.get()
                            + ", consumed messages = " + consumedCount.get());
                }
            } catch (InterruptedException e) {
                // Allow the thread to exit.
            }
        }
    }
}
```

### Monitoraggio delle metriche di volume dall'esecuzione di esempio
<a name="batch-request-java-example-monitoring-metrics"></a>

Amazon SQS genera automaticamente i parametri di volume per i messaggi inviati, ricevuti ed eliminati. Puoi accedere a tali parametri e ad altri tramite la scheda **Monitoring (Monitoraggio)** per la coda o nella [console CloudWatch ](https://console.aws.amazon.com/cloudwatch/home).

**Nota**  
Le metriche possono diventare disponibili fino a 15 minuti dopo l'avvio della coda.