SQS
Amazon Simple Queue Service (SQS) 是一项可靠、可扩展、完全托管的消息队列服务。Amazon SQS支持标准队列和 FIFO 队列,中国区目前仅支持标准队列。
Amazon SQS 的主要优势:
- 安全性 – 可以控制谁能向Amazon SQS队列发送消息以及谁能从队列接收消息。利用服务端加密 (SSE),可以通过使用在 AWS Key Management Service (AWS KMS) 中管理的密钥保护队列中消息的内容来传输敏感数据。
- 持久性 – 为确保消息的安全,Amazon SQS 将消息存储在多个服务器上。
- 可用性 – Amazon SQS 使用冗余基础设施来支持生成和消费消息的高并发访问和高可用。
- 可扩展性 – Amazon SQS 可独立处理各个缓冲的请求,并可透明扩展以处理任何负载增加或峰值,无需任何预配置指令。
- 可靠性 – Amazon SQS 在处理期间锁定消息,以便多个生成者可同时发送消息,多个消费者可同时接收消息。
- 自定义 – 队列不必完全相同,例如,您可以设置队列的默认延迟。可以使用 Amazon Simple Storage Service (Amazon S3) 或 Amazon DynamoDB 存储大于 256 KB 的消息内容,Amazon SQS 保留指向 Amazon S3 对象的指针,您也可以将一个大消息拆分为几个小消息。
下面以标准Queue为例,演示Java创建Queue、配置Dead Letter Queue、发送Message、接收Message、删除Message、删除Queue的方法。
配置AWS账户
在{HOME}/.aws目录下配置AWS账户信息,用户要有SQS权限:
[default]
aws_access_key_id = AAAAAAAAAAAAAA
aws_secret_access_key = MXXXXXXXXXXXXXXXXXXXXXX9
POM依赖
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-sqs</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bom</artifactId>
<version>1.11.431</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.7</version>
</dependency>
</dependencies>
</dependencyManagement>
示例代码
import com.amazonaws.regions.Regions;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
import com.amazonaws.services.sqs.model.*;
import java.util.*;
public class SqsUtil {
private static final String ARN_ATTRIBUTE_NAME = "QueueArn";
private static AmazonSQS sqs;
static {
sqs = AmazonSQSClientBuilder.standard().withRegion(Regions.CN_NORTH_1).build();
}
private SqsUtil() {
}
// 根据Queue Name查询Url
public static String getQueueUrl(String queueName) {
return sqs.getQueueUrl(queueName).getQueueUrl();
}
// 创建Queue
public static String createQueue(String queueName) {
System.out.println("Creating a new SQS queue called " + queueName);
CreateQueueRequest createQueueRequest = new CreateQueueRequest(queueName);
Map<String, String> attributes = new HashMap<>();
// 接收消息等待时间
attributes.put("ReceiveMessageWaitTimeSeconds", "30");
createQueueRequest.withAttributes(attributes);
return sqs.createQueue(createQueueRequest).getQueueUrl();
}
// 创建死信Queue
public static String createDeadLetterQueue(String queueName) {
String queueUrl = createQueue(queueName);
// 配置Dead Letter Queue时使用ARN
return getQueueArn(queueUrl);
}
// 配置死信Queue
public static void configDeadLetterQueue(String queueUrl, String deadLetterQueueArn) {
System.out.println("Config dead letter queue for " + queueUrl);
Map<String, String> attributes = new HashMap<>();
// 最大接收次数设为5,当接收次数超过5后,消息未被处理和删除将被转到死信队列
attributes.put("RedrivePolicy", "{\"maxReceiveCount\":\"5\", \"deadLetterTargetArn\":\"" + deadLetterQueueArn + "\"}");
sqs.setQueueAttributes(queueUrl, attributes);
}
// 发送消息
public static void sendMessage(String queueUrl, String message) {
System.out.println("Sending a message to " + queueUrl);
SendMessageRequest request = new SendMessageRequest();
request.withQueueUrl(queueUrl);
request.withMessageBody(message);
Map<String, MessageAttributeValue> messageAttributes = new HashMap<>();
// 添加消息属性,注意必须要有DataType和Value
messageAttributes.put("Hello", new MessageAttributeValue().withDataType("String").withStringValue("COCO"));
request.withMessageAttributes(messageAttributes);
sqs.sendMessage(request);
}
// 接收消息
public static void receiveMessages(String queueUrl) {
System.out.println("Receiving messages from " + queueUrl);
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl);
receiveMessageRequest.setMaxNumberOfMessages(5);
receiveMessageRequest.withWaitTimeSeconds(10);
// 要添加MessageAttributeNames,否则不能接收
receiveMessageRequest.setMessageAttributeNames(Arrays.asList("Hello"));
List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
for (Message message : messages) {
System.out.println("Message: " + message.getBody());