AWS-Lambda 中的多线程
AWS-Lambda 中的多线程
AWS lambda 是一种无服务器、事件驱动的计算服务。所以我们不必考虑和管理使用 AWS Lambda 的服务器。它只是关于部署和运行。
参考这个关于 如何在 AWS lambda 中使用 java .
要求
需要从第三方 API 下载大量数据并保存在 S3 存储桶中以备将来使用。 API 中允许分页。由于数据集有点大,需要检索多个页面。
解决方案
根据要求,它不是阻塞任务。它可以以异步方式实现。
所以解决方案是
- 主程序将向 AWS 队列发送消息。然后队列将触发 AWS lambda 函数。
- 该 lambda 函数包含一个 java 程序,该程序将下载大型数据集并将其存储在 S3 存储桶中。
- 为了提高程序的性能, 多线程 将处理数据下载部分。每个页面将由一个下载 单独的线程 .
执行
让我们看看上述解决方案的java实现。注意handleRequest()是程序在lambda函数中的入口点(可以配置)。
这只是对该解决方案中应该做什么的模拟。让我们运行它并查看输出。
本地机器中的程序输出
所以这工作正常。在所有线程完成任务后程序终止。
让我们将其上传到 AWS lambda 函数并查看输出。
AWS lambda 中的程序输出(第一次调用)
AWS Lambda 的行为似乎完全不同。数据下载线程的日志不存在。现在我们遇到了问题。数据下载线程发生了什么?
现在我要让主线程休眠 3000 毫秒,然后在 lambda 中查看输出。
添加了线程睡眠
主线程休眠后的 Lambda 输出(第二次调用)
在这里,我们可以看到数据下载器线程的输出。 线程 0、线程 1、线程 2 已启动并且下载也正在发生。但没有完成。稍等片刻后,让我们再次调用 lambda 函数。
Lambda 函数第三次调用
现在我们在这里有点困惑。在第 3 次调用中运行了另外 3 个新线程( 线程 3、线程 4、线程 5 )。此外,先前调用中的线程也在运行。但是之前线程的日志也显示了当前时间。不是之前的调用时间。那么这里发生了什么?
结论
当我们触发 lambda 函数时, 处理请求() 将开始执行。因此它将创建 3 个新线程用于数据下载,并立即从 处理请求() .
因为立即返回 处理请求() 方法,在第一次调用中;即使创建了 3 个数据下载线程,这些线程也没有足够的时间来执行。因此没有数据下载线程的迹象。
但是在第二次调用中,我们让主线程休眠了 3000 毫秒。因此 lambda 函数必须等待 3000 毫秒才能从 处理请求() 因为主线程处于睡眠状态。所以现在数据下载线程有机会运行 3000 毫秒,这就是为什么有来自这些线程的日志。但是这些线程没有足够的时间来完成他们的任务。
从请求返回后,Lambda 冻结执行环境。当再次调用该函数时,lambda 会抛出环境以供重用。
你可以从上面的解释中找到 AWS Lambda 文档 .
根据上面的解释和第 3 次调用的输出,我们可以看到在第 2 次调用中没有足够时间完成的线程也在第 3 次调用中被执行。这就是为什么有 6 个数据下载线程正在进行中的原因。
这可能发生在随后的 lambda 调用中( 热启动 )。但是在 lambda 函数超时(最多 15 分钟)之后,我们不能期望会发生这种情况。因为在超时之后如果发生新的调用,它将是 冷启动。 所以 lambda 会为此创建一个新的执行环境。
解决方案
为了避免在 AWS Lambda 中出现上述问题,我们必须等待数据下载线程完成它们的任务,然后再从 处理请求()。
我要使用一个 倒计时锁存器 克服这一点。让我们看看源代码的变化。
带有 CountDownLatch 更改的 handleRequest()
带有 CountDownLatch 更改的 DataDownloader.java
让我们将其上传到 AWS lambda 并查看输出。
具有最新更改的 AWS lambda 输出
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通