SQS maxNumberOfMessages

11

Используя клиентское приложение Java, я запрашиваю очередь сообщений SQS. В очереди 12 000 сообщений в качестве настройки для тестирования. Я использую openJDK с последней версией aws-java-sdk (software.amazon.awssdk 2.10.62). Pom.xml показан ниже.

Проблема, с которой я сталкиваюсь, заключается в том, что, несмотря на установку maxNumberOfMessages (10), я получаю только 3. Я понимаю, что это максимум, а не гарантия количества сообщений, однако колебания в количестве возвращаемых сообщений отсутствуют. Это всегда 3.

Документация AWS: MaxNumberOfMessages Максимальное количество возвращаемых сообщений. Amazon SQS никогда не возвращает больше сообщений, чем это значение (однако может быть возвращено меньше сообщений). Допустимые значения: от 1 до 10. По умолчанию: 1. Тип: Требуется целое число: Нет

Использование сообщений с помощью короткого опроса

Когда вы используете сообщения из очереди с помощью короткого опроса, Amazon SQS выбирает подмножество своих серверов (на основе взвешенного случайного распределения) и возвращает сообщения только от этих серверов. Таким образом, конкретный запрос ReceiveMessage может не вернуть все ваши сообщения. Однако, если в вашей очереди менее 1000 сообщений, последующий запрос вернет ваши сообщения. Если вы продолжаете получать из своих очередей, Amazon SQS производит выборку всех своих серверов, и вы получаете все свои сообщения.

Итак, мы протестировали двух клиентов в java, используя как старый aws sdk, так и новый с одинаковыми результатами. Всегда только 3 сообщения назад.

Интересно, что если вместо внешнего запуска приложения (на моем мощном рабочем столе) вы запускаете его как AWS Lambda, вы получаете 10 сообщений. Этот лямбда-тест был выполнен с использованием JavaScript коллегой.

Таким образом, остается вопрос, почему мы получаем только 3 сообщения на запрос, и, по-видимому, в лямбде вы можете получить 10.

Учитывая, что цена за запрос является взвешенным случайным распределением, основанным на прибыли амазонки =))

Метод испытаний 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
источник
Просто мысль, а вы проверили настройку самой очереди на AWS? Может быть, он был настроен со свойством maxNumberOfMessages, которое может получить приоритет над тем, который вы установили в клиенте java? Так как он работает в лямбда-JavaScript, это было бы странно, но все же стоит
попробовать

Ответы:

9

Учитывая, что цена за запрос является взвешенным случайным распределением, основанным на прибыли амазонки =))

Понятно, что ваша цель здесь - снизить затраты, будь то путем отправки меньшего числа запросов в SQS или путем принуждения SQS доставлять максимальное количество доступных сообщений.

Как вы указали в своем вопросе, SQS не обязана доставлять максимальное количество доступных сообщений. Тем не менее, есть кое-что, о чем я хотел бы сообщить вам, если вы еще об этом не знаете.


Длинный опрос

Руководство разработчика сервиса Amazon Simple Queue гласит:

Процесс потребления сообщений из очереди зависит от того, используете ли вы короткий или длинный опрос. По умолчанию Amazon SQS использует короткий опрос , запрашивая только часть своих серверов (на основе взвешенного случайного распределения), чтобы определить, доступны ли какие-либо сообщения для ответа. Вы можете использовать длительный опрос, чтобы сократить свои расходы, позволяя при этом потребителям получать сообщения, как только они поступят в очередь.

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

Если мы посмотрим на преимущества длинного опроса на одной странице документации, то в нем говорится:

Длинный опрос предлагает следующие преимущества:

  • Исключите пустые ответы, разрешив Amazon SQS ждать, пока сообщение не станет доступным в очереди, прежде чем отправлять ответ. Если время ожидания соединения не истекло, ответ на запрос ReceiveMessage содержит хотя бы одно из доступных сообщений, вплоть до максимального количества сообщений, указанного в действии ReceiveMessage.

  • Устраните ложные пустые ответы, запрашивая все, а не подмножество серверов Amazon SQS.

Вторая пуля здесь очень важна. Даже если вы не видите пустых ответов, на серверах может храниться больше сообщений, которые не запрашиваются. Если вы включите длительный опрос, то, надеюсь, вы увидите увеличение количества возвращаемых сообщений, если предположить, что в общей сложности более 3 серверов.

Поэтому я предлагаю включить длинный опрос в вашей очереди. Для этого см. Страницу « Настройка длинного опроса» .


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

Джейкоб Г.
источник
Мы проверили то же самое с длинным опросом и получили тот же результат. У нас было 12 000 сообщений в очереди, и опрос был установлен на 20 секунд. Мы все еще получаем только три сообщения. Если мы получим три сообщения с длинным и коротким опросом, то нет смысла использовать длинный опрос (кроме случаев, когда очередь пуста в ожидании сообщений). К сожалению, мы пытаемся сбалансировать стоимость и скорость. К сожалению, у нас есть только ограниченные потоки чтения, которые мы можем использовать (из-за аппаратного обеспечения), поэтому количество сообщений, которые мы можем обработать за вызов, является ограничивающим фактором в том, насколько быстро мы можем его обработать.
DevilCode
@DevilCode Я не смог воспроизвести вашу проблему на моем конце с включенным длинным опросом. Ваша очередь - стандартная очередь или очередь FIFO? Возможно, вы также захотите открыть заявку в службу поддержки AWS, чтобы узнать, смогут ли они внести изменения с их стороны.
Джейкоб Г.
Это стандартная очередь. Вы запускали свой код локально и использовали ли вы Java?
DevilCode
@DevilCode Я проверил это, используя очередь FIFO. И да, я использую AWS Java SDK v2 для получения сообщений из моей очереди SQS. Мой код не работает в функции AWS Lambda.
Джейкоб Г.
1
OK Протестировал очередь FIFO, и мы получили 10 сообщений, в то время как в стандартной очереди мы получили только три. Теперь я могу только заключить, что документация относится к очереди FIFO, а не к стандартной очереди.
DevilCode
0

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

Charbel K
источник
0

Длинный опрос:

        ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl)
              .withWaitTimeSeconds(10)     // long poll: wait 10 seconds, max is 20 seconds
              .withMaxNumberOfMessages(10);
Джастин
источник