Korzystając z aplikacji klienckiej Java, pytam o kolejkę SQS. Kolejka zawiera 12 000 komunikatów w konfiguracji do testowania. Korzystam z openJDK z najnowszą wersją aws-java-sdk (software.amazon.awssdk 2.10.62) pom.xml.
Problem, który widzę, polega na tym, że pomimo ustawienia maxNumberOfMessages (10) dostaję tylko 3. Rozumiem, że to maksimum nie jest gwarancją liczby wiadomości, jednak nie ma wahania w liczbie zwracanych wiadomości. Jest zawsze 3.
Dokumentacja AWS: MaxNumberOfMessages Maksymalna liczba komunikatów do zwrócenia. Amazon SQS nigdy nie zwraca więcej wiadomości niż ta wartość (jednak może zostać zwróconych mniej wiadomości). Prawidłowe wartości: od 1 do 10. Domyślnie: 1. Typ: Liczba całkowita Wymagana: Nie
Odbieranie wiadomości za pomocą krótkiego odpytywania
Gdy konsumujesz wiadomości z kolejki przy użyciu krótkiego odpytywania, Amazon SQS próbkuje podzbiór swoich serwerów (na podstawie ważonej dystrybucji losowej) i zwraca wiadomości tylko z tych serwerów. W związku z tym określone żądanie ReceiveMessage może nie zwrócić wszystkich wiadomości. Jeśli jednak masz mniej niż 1000 wiadomości w kolejce, kolejne żądanie zwróci wiadomości. Jeśli nadal używasz kolejek, Amazon SQS pobiera próbki ze wszystkich swoich serwerów i otrzymujesz wszystkie wiadomości.
Przetestowaliśmy więc dwóch klientów w Javie, używając zarówno starszego aws sdk, jak i nowszego z tymi samymi wynikami. Zawsze tylko 3 wiadomości z powrotem.
Co ciekawe, jeśli zamiast uruchamiać aplikację zewnętrznie (na moim potężnym komputerze), uruchomisz ją jako AWS Lambda, otrzymasz 10 wiadomości. Ten test lambda został wykonany przy użyciu JavaScript przez kolegę.
Pozostaje więc pytanie, dlaczego otrzymujemy tylko 3 wiadomości na żądanie, a pozornie w lambda można uzyskać 10.
Biorąc pod uwagę, że istnieje koszt za żądanie, jest to ważona losowa dystrybucja oparta na zysku amazonu =))
Metoda testu 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>
źródło
Odpowiedzi:
Oczywiste jest, że Twoim celem jest obniżenie kosztów, czy to poprzez wysyłanie mniejszej liczby żądań do SQS, czy przez zmuszanie SQS do dostarczenia maksymalnej dostępnej liczby wiadomości.
Jak stwierdzono w swoim pytaniu, SQS nie ma obowiązku dostarczania maksymalnej dostępnej liczby wiadomości. Jest jednak coś, o czym chciałbym cię poinformować, zakładając, że jeszcze tego nie wiesz.
Długie odpytywanie
Developer Guide prostych stanach kolejki Obsługi Amazon:
Wszystkie wiadomości wysłane do SQS mogły być przechowywane na osobnych serwerach. Jak wynika z dokumentacji, można zapytać tylko o podzbiór serwerów, jeśli w kolejce ustawiono krótkie odpytywanie . Domyślam się, że miałeś pecha podczas inwokacji
receiveMessage
i3
za każdym razem wracałeś.Jeśli spojrzymy na zalety długiego odpytywania na tej samej stronie dokumentacji, stwierdza:
Druga kula jest tutaj bardzo ważna. Chociaż nie widzisz pustych odpowiedzi, może istnieć więcej wiadomości przechowywanych na serwerach, które nie są pytane. Jeśli włączysz długie odpytywanie, mam nadzieję, że zauważysz wzrost liczby zwracanych wiadomości, zakładając, że łącznie jest więcej niż 3 serwery.
Dlatego sugeruję, aby umożliwić długie odpytywanie w kolejce. Aby to zrobić, zobacz stronę Konfigurowanie długiego odpytywania .
Jak wspomniał DevilCode w swoim komentarzu poniżej, był w stanie rozwiązać swój problem, używając kolejki FIFO zamiast standardowej i umożliwiając długie odpytywanie.
źródło
Myślę, że to jest podobnym question.As wskazanych przez Jakuba długo sondowania wydaje się być rozwiązaniem tego problemu.
źródło
Długie odpytywanie:
źródło