SQS maxNumberOfMessages

11

Menggunakan aplikasi klien Java saya meminta antrian SQS untuk pesan. Antrian memiliki 12.000 pesan sebagai pengaturan untuk pengujian. Saya menggunakan openJDK dengan aws-java-sdk terbaru (software.amazon.awssdk 2.10.62) pom.xml ditampilkan lebih jauh ke bawah.

Masalah yang saya lihat adalah bahwa meskipun mengatur maxNumberOfMessages (10) saya hanya mendapatkan 3. Saya mengerti bahwa ini adalah maksimum bukan jaminan jumlah pesan tetapi tidak ada keraguan dalam jumlah pesan yang dikembalikan. Itu selalu 3.

Dokumentasi AWS: MaxNumberOfMessages Jumlah maksimum pesan yang akan dikembalikan. Amazon SQS tidak pernah mengembalikan lebih banyak pesan dari nilai ini (namun, lebih sedikit pesan yang dikembalikan). Nilai yang valid: 1 hingga 10. Default: 1. Tipe: Integer Diperlukan: No

Mengkonsumsi Pesan Menggunakan Polling Pendek

Saat Anda menggunakan pesan dari antrian menggunakan polling singkat, Amazon SQS mengambil sampel sebagian dari servernya (berdasarkan distribusi acak tertimbang) dan mengembalikan pesan hanya dari server tersebut. Dengan demikian, permintaan ReceiveMessage tertentu mungkin tidak mengembalikan semua pesan Anda. Namun, jika Anda memiliki kurang dari 1.000 pesan dalam antrian Anda, permintaan berikutnya akan mengembalikan pesan Anda. Jika Anda terus mengkonsumsi dari antrian Anda, Amazon SQS mengambil sampel semua servernya, dan Anda menerima semua pesan Anda.

Jadi kami telah menguji dua klien di java menggunakan aws sdk yang lebih lama dan yang lebih baru dengan hasil yang sama. Selalu hanya 3 pesan kembali.

Menariknya jika alih-alih menjalankan aplikasi secara eksternal (di desktop saya yang perkasa) Anda menjalankannya sebagai AWS Lambda Anda mendapatkan 10 pesan. Tes lambda ini dilakukan menggunakan JavaScript oleh seorang rekan.

Jadi pertanyaannya tetap mengapa kita hanya mendapatkan 3 pesan per permintaan dan tampaknya dalam lambda Anda bisa mendapatkan 10.

Mengingat ada biaya per permintaan adalah distribusi acak tertimbang berdasarkan laba amazon =))

Metode Tes SQS:

public void SQStart()
{
    AwsBasicCredentials awsCreds = AwsBasicCredentials.create("accessKeyID", "secretKeyID");
    AwsCredentialsProvider creds = StaticCredentialsProvider.create(awsCreds);
    SqsClient sqs = SqsClient.builder().credentialsProvider(creds).region(Region.EU_WEST_1).build();
    GetQueueUrlRequest getQueueRequest = GetQueueUrlRequest.builder()
            .queueName(QUEUE_NAME)
            .build();
    String queueUrl = sqs.getQueueUrl(getQueueRequest).queueUrl();

    for (int x =1; x < 100; x++) {
        ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
                .queueUrl(queueUrl)
                .maxNumberOfMessages(10)
                .build();


        List<Message> messages = sqs.receiveMessage(receiveMessageRequest).messages();
        if (messages.size() > 3 ) {
            System.out.println("YEY More than 3 Messages: "+ messages.size());
        }
    }
}

POM.XML:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>SQSTest</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>bom</artifactId>
                <version>2.10.62</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>

            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>sqs</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.9</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.10</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>1.11.720</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.6.1</version>
        </dependency>
    </dependencies>
</project>
DevilCode
sumber
Hanya pemikiran, tetapi apakah Anda sudah memeriksa konfigurasi antrian itu sendiri di AWS? Mungkin setup dengan properti maxNumberOfMessages yang mungkin mendapatkan prioritas daripada yang Anda atur di klien java? Karena bekerja di lambda javascript, ini akan menjadi aneh, tapi masih layak dicoba :)
niekname

Jawaban:

9

Mengingat ada biaya per permintaan adalah distribusi acak tertimbang berdasarkan laba amazon =))

Jelas bahwa tujuan Anda di sini adalah untuk mengurangi biaya, apakah itu dengan mengirimkan lebih sedikit permintaan ke SQS, atau dengan memaksa SQS untuk mengirimkan jumlah maksimum pesan yang tersedia.

Seperti yang telah Anda sebutkan dalam pertanyaan Anda, SQS tidak berkewajiban untuk memberikan jumlah pesan maksimum yang tersedia. Namun, ada sesuatu yang ingin saya informasikan kepada Anda, dengan asumsi Anda belum menyadarinya.


Polling Panjang

The Panduan Pengembang dari Simple negara Antrian Layanan Amazon:

Proses mengkonsumsi pesan dari antrian tergantung pada apakah Anda menggunakan polling pendek atau panjang. Secara default, Amazon SQS menggunakan polling singkat , hanya menanyakan sebagian dari servernya (berdasarkan distribusi acak tertimbang) untuk menentukan apakah ada pesan yang tersedia untuk respons. Anda dapat menggunakan polling panjang untuk mengurangi biaya sambil memungkinkan konsumen Anda menerima pesan begitu mereka tiba di antrian.

Pesan yang Anda kirim ke SQS mungkin semuanya disimpan di server yang terpisah. Seperti yang dinyatakan dalam dokumentasi, hanya sebagian server yang dapat ditanyai jika antrian Anda diatur untuk menggunakan polling singkat . Dugaan saya adalah bahwa Anda tidak beruntung ketika memohon receiveMessagedan hanya 3dikembalikan setiap saat.

Jika kita melihat manfaat polling panjang pada halaman dokumentasi yang sama, itu menyatakan:

Polling panjang menawarkan manfaat berikut:

  • Hilangkan respons kosong dengan mengizinkan Amazon SQS menunggu hingga pesan tersedia dalam antrian sebelum mengirim respons. Kecuali jika koneksi terputus, respons terhadap permintaan ReceiveMessage berisi setidaknya satu pesan yang tersedia, hingga jumlah maksimum pesan yang ditentukan dalam tindakan ReceiveMessage.

  • Hilangkan tanggapan kosong palsu dengan menanyakan semua — alih-alih sebagian dari — server SQS Amazon.

Peluru kedua sangat penting di sini. Meskipun Anda tidak melihat respons kosong, mungkin ada lebih banyak pesan yang disimpan di server yang tidak dipertanyakan. Jika Anda mengaktifkan polling panjang, semoga Anda akan melihat peningkatan jumlah pesan yang dikembalikan, dengan asumsi ada lebih dari 3 server secara total.

Karena itu, saran saya adalah mengaktifkan polling panjang pada antrian Anda. Untuk melakukan ini, lihat halaman Menyiapkan Polling Panjang .


Seperti yang disebutkan DevilCode dalam komentarnya di bawah ini, ia dapat menyelesaikan masalahnya dengan menggunakan antrian FIFO alih-alih antrian standar, dan dengan mengaktifkan polling yang lama.

Jacob G.
sumber
Kami telah menguji hal yang sama dengan polling panjang dan mendapatkan hasil yang sama. Kami memiliki 12.000 pesan dalam antrian dan pemungutan suara diatur ke 20 detik. Kami masih hanya mendapatkan tiga pesan. Jika kami mendapatkan tiga pesan dengan jajak pendapat panjang dan pendek, tidak ada alasan untuk menggunakan jajak pendapat panjang (kecuali jika antrian kosong menunggu pesan). Sayangnya kami berusaha menyeimbangkan biaya dan kecepatan. Sayangnya kami hanya memiliki utas baca terbatas yang dapat kami gunakan (karena perangkat kerasnya) sehingga jumlah pesan yang dapat kami tarik per panggilan adalah faktor pembatas dalam seberapa cepat kami dapat memprosesnya.
DevilCode
@DevilCode Saya tidak dapat mereproduksi masalah Anda pada akhirnya dengan pemungutan suara yang lama diaktifkan. Apakah antrian Anda adalah antrian standar atau antrian FIFO? Anda mungkin juga ingin membuka tiket dukungan dengan AWS untuk melihat apakah mereka dapat melakukan perubahan pada akhirnya.
Jacob G.
Ini adalah antrian standar. Apakah Anda menjalankan kode Anda secara lokal dan apakah kami menggunakan Java?
DevilCode
@DevilCode Saya mengujinya menggunakan antrian FIFO. Dan ya, saya menggunakan AWS Java SDK v2 untuk menerima pesan dari antrian SQS saya. Kode saya tidak berjalan dalam fungsi AWS Lambda.
Yakub G.
1
OK. Menguji antrian FIFO dan kami mendapatkan 10 pesan sedangkan di antrian standar kami hanya mendapatkan tiga. Yang bisa saya simpulkan sekarang adalah bahwa dokumentasi mengacu pada antrian FIFO dan bukan antrian standar.
DevilCode
0

Saya pikir ini adalah pertanyaan serupa. Seperti yang ditunjukkan oleh Jacob, pemungutan suara yang panjang tampaknya menjadi solusi untuk masalah ini.

charbel k
sumber
0

TPS panjang:

        ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl)
              .withWaitTimeSeconds(10)     // long poll: wait 10 seconds, max is 20 seconds
              .withMaxNumberOfMessages(10);
Justin
sumber