AWS Study Notes (7)--Integrating SQS and Lambda

This article introduces the method of integrating SQS and Lambda, and the code is based on JAVA SDK.

 

POM configuration 

<dependencies>
    <dependency>
        <artifactId>aws-java-sdk-sqs</artifactId>
        <groupId>com.amazonaws</groupId>
    </dependency>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-lambda-java-core</artifactId>
        <version>1.2.0</version>
    </dependency>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-lambda-java-events</artifactId>
        <version>2.0.2</version>
    </dependency>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-lambda-java-log4j2</artifactId>
        <version>1.1.0</version>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-bom</artifactId>
            <version>1.11.272</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

 

SQS

China currently only supports standard Queue, not FIFO Queue. The following code uses standard Queue as an example to demonstrate the methods of creating Queue, configuring Dead Letter Queue, sending Message, receiving Message, deleting Message, and deleting Queue:

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() {
    }

    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<>();
        // wait time to receive message
        attributes.put("ReceiveMessageWaitTimeSeconds", "5");
        createQueueRequest.withAttributes(attributes);

        return sqs.createQueue(createQueueRequest).getQueueUrl();
    }

    public static String createDeadLetterQueue(String queueName) {
        String queueUrl = createQueue(queueName);
        // Use ARN when configuring Dead Letter Queue
        return getQueueArn(queueUrl);
    }

    public static void configDeadLetterQueue(String queueUrl, String deadLetterQueueArn) {
        System.out.println("Config dead letter queue for " + queueUrl);

        SetQueueAttributesRequest queueAttributes = new SetQueueAttributesRequest();
        Map<String, String> attributes = new HashMap<>();
        // The maximum number of receptions is set to 5. When the number of receptions exceeds 5, the message will be transferred to the dead letter queue if it is not processed and deleted.
        attributes.put("RedrivePolicy", "{\"maxReceiveCount\":\"5\", \"deadLetterTargetArn\":\"" + deadLetterQueueArn + "\"}");
        queueAttributes.setAttributes(attributes);
        queueAttributes.setQueueUrl (queueUrl);

        sqs.setQueueAttributes(queueAttributes);
    }

    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<>();
        // Add message properties, note that there must be DataType and 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);
        // To add MessageAttributeNames, otherwise it cannot be received
        receiveMessageRequest.setMessageAttributeNames(Arrays.asList("Hello"));

        List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
        for (Message message : messages) {
            System.out.println("Message: " + message.getBody());
            for (Map.Entry<String, MessageAttributeValue> entry : message.getMessageAttributes().entrySet()) {
                System.out.println("  Attribute");
                System.out.println("    Name:  " + entry.getKey());
                System.out.println("    Value: " + entry.getValue().getStringValue());
            }

            // Delete message
            System.out.println("Deleting a message.");
            String messageReceiptHandle = message.getReceiptHandle();
            sqs.deleteMessage(new DeleteMessageRequest(queueUrl, messageReceiptHandle));
        }
    }

    public static void deleteQueue(String queueUrl) {
        System.out.println("Deleting the queue " + queueUrl);
        sqs.deleteQueue(new DeleteQueueRequest(queueUrl));
    }

    public static String getQueueArn(String queueUrl) {
        List<String> attributes = new ArrayList<>();
        attributes.add(ARN_ATTRIBUTE_NAME);
        GetQueueAttributesResult queueAttributes = sqs.getQueueAttributes(queueUrl, attributes);
        return queueAttributes.getAttributes().get(ARN_ATTRIBUTE_NAME);
    }

}
Before running the above code, to configure credentials in the {HOME}/.aws directory, the user must have SQS permission:

[default]

aws_access_key_id = AAAAAAAAAAAAAA

aws_secret_access_key = MXXXXXXXXXXXXXXXXXXXXXX9

 

have a test:

// Create Dead Letter Queue
String deadLetterQueueArn = createDeadLetterQueue("DeadLetterQueue");
// Create Task Queue
String queueUrl = createQueue("TaskQueue");
// Configure Dead Letter Queue
configDeadLetterQueue(queueUrl, deadLetterQueueArn);
// send Message
for (int i = 0; i < 6; i++) {
    sendMessage(queueUrl, "Hello COCO " + i);
}
// receive Message
receiveMessages(queueUrl);
// delete queue
deleteQueue(queueUrl);

 

Lambda

Lambda function definitions support two ways:

  • Implement the predefined interface RequestStreamHandler or RequestHandler
    import com.amazonaws.services.lambda.runtime.RequestHandler;
    import com.amazonaws.services.lambda.runtime.Context;
    
    public class Hello implements RequestHandler<Request, Response> {
        // Request, Response are custom types
        public Response handleRequest(Request request, Context context) {
            String greetingString = String.format("Hello %s %s.", request.firstName, request.lastName);
            return new Response(greetingString);
        }
    }
  • You don't have to implement any interface, define the handler method directly
    outputType handler-name(inputType input, Context context) {
       ...
    }

inputType and outputType can be one of the following types:

  • Java primitive types such as String or int.
  • Predefined AWS event types in the aws-lambda-java-events library. Such as S3Event.
  • Own POJO class. AWS Lambda will automatically serialize and deserialize input and output JSON based on the POJO type.

The Context object in the handler method signature can be omitted if not required.

 

First write a simple test case to receive SQS messages, the input parameter input is the Queue URL:

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class Hello implements RequestHandler<String, String> {
    @Override
    public String handleRequest(String input, Context context) {
        LambdaLogger logger = context.getLogger();
        logger.log("received : " + input);
        SqsUtil.receiveMessages(input);
        return "success";
    }
}

After the program is written, how to put it into the Lambda function? It needs to be packaged into a jar package and must contain dependency packages. Add the shade plugin to the pom:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Next, create a Lambda Function through the Web Console


Note: role must have lambda, Cloudwatch Logs, and SQS permissions.

 

Then upload the jar package and configure the Handler


Then adjust the memory configuration and timeout parameters and save.

Configure the test parameters and test it first:


Successful execution output:


Modify the code below to change the input parameter type to ScheduledEvent, which will be called using the trigger CloudWatch Events.

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.ScheduledEvent;

public class Hello implements RequestHandler<ScheduledEvent, String> {
    @Override
    public String handleRequest(ScheduledEvent input, Context context) {
        LambdaLogger logger = context.getLogger();
        logger.log("received : " + input.toString() + "\n");
        SqsUtil.receiveMessages("https://sqs.cn-north-1.amazonaws.com.cn/891245999999/TaskQueue");
        return "success";
    }
}

After uploading, also test manually first, this time select the template Scheduled Event


After the test is successful, configure the CloudWatch Events trigger, and select Schedule expression for the Rule Type


After saving, you can call lambda regularly, O.

 

Integrate SQS and Lambda: serverless architecture for asynchronous workloads

Amazon Simple Queue Service Developer Guide

AWS Lambda Developer Guide

Programming Model for Authoring Lambda Functions in Java

AWS SDK for Java Developer Guide

Schedule Expressions Using Rate or Cron

AWS Video Center

Getting Started with AWS Microservices and Serverless Architecture

Quickly understand AWS Lambda and easily build serverless backend

Building AWS Lambda Applications with the Serverless Application Model

How to Meet Enterprise Needs by Running Serverless

Serverless Architecture Design Patterns and Best Practices

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326074130&siteId=291194637