现有需求:当生产者发送新消息到消息队列后,消息队列要根据消息自动进行处理,比如将消息推给消费者等。
Amazon SQS 消息队列本身不支持当新消息到达队列后的进一步处理,但是我们可以结合 Amazon Lambda 函数来实现这一需求。
下面就以一个简单的示例介绍一下 Amazon SQS 消息队列和 Amazon Lambda 函数是怎么配合实现上述需求的。
1.创建一个队列
Lambda函数既支持标准队列,又支持FIFO队列,所以这里创建什么类型的队列都可以。简单设置一下,创建队列即可。
2.创建一个Lambda函数
简单创建一个Lambda函数,输入函数名称(截图上函数名称已存在,忽略即可),选择运行时(函数语言),然后直接创建即可。
注:
默认创建Lambda函数时,会创建一个具有基本 Lambda 权限的新角色,这个角色没有 SQS 消息队列相关的执行权限,可以后续对该角色进行权限配置。
3.给Lambda函数的执行角色配置权限
- 首先进入到刚刚创建的 Lambda 函数的详情页面,然后点击 “配置” -> “权限”,再点击执行角色的名称,跳转到该角色的角色管理页面。
- 点击 “添加内联策略”
- 服务选择 SQS,操作选择 GetQueueAttributes、ReceiveMessage、DeleteMessage 这3项即可,然后点击 “添加ARN”。
-
将我们第一步创建的消息队列的 ARN 复制粘贴过来,点击 “添加”。
-
点击右下角的 “查看策略” 来到以下页面,输入名称,点击 “创建策略” 即可。
4.给Lambda函数添加触发器
将第一步创建的消息队列设置为 Lambda 函数的触发器。
首先回到我们创建的 Lambda 函数的详情页面,点击 “添加触发器” 来到以下页面,选择 SQS,选择我们创建的队列,点击 “添加” 即可。
5.自定义Lambda函数的处理逻辑
现在,我们创建的消息队列和 Lambda 函数已经关联上了,那么当新消息到达队列后,我们怎么自定义处理逻辑呢?
Lambda 函数支持上传 .zip 和 .jar 的文件,所以我们可以先建一个项目,写好处理逻辑,然后打包上传到 Lambda 队列,这样当新消息到达队列后,就可以按照我们写好的逻辑进行处理了。
- 创建项目可直接参考 官方文档
其中 pom.xml 如下:
<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>doc-examples</groupId>
<artifactId>lambda-java-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>lambda-java-example</name>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-log4j2</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
</plugin>
</plugins>
</build>
</project>
编写处理逻辑的 Java 类(官方文档中的类名是 Hello,我创建的类名是 Handler,这个类名无所谓,只要后续在 Lambda 函数中的配置保持一致就行了)如下:
package example;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
public class Handler implements RequestHandler<SQSEvent, Void>{
public Void handleRequest(SQSEvent event, Context context)
{
for(SQSMessage msg : event.getRecords()){
System.out.println(new String(msg.getBody()));
}
return null;
}
}
- 将打包后的 .jar 文件上传到 Lambda 函数。来到 Lambda 函数详情页面,在代码源处点击上传即可。
- 最后,再修改一下 “运行时设置” 中的 “处理程序” 即可。
注:
处理程序的配置只要与我们的项目结构一致就行。
包名.类名::方法名
到此,一个简单的示例就完成了,下面可以测试一下了。
6.测试
跑一下测试用例,往我们创建的队列中发送15条消息。
然后看一下 Lambda 函数的日志,可见,消息到达队列后,确实触发了 Lambda 函数,并执行了我们自定义的处理逻辑。