我们现在通过 Laravel vapor 在 AWS 无服务器基础设施上运行我们的网站。它在无服务器 Aurora 数据库上运行,并使用 Amazon SQS 作为队列驱动程序。基本上是 Laravel Vapor 部署的默认值。
我们目前遇到了一个性能问题,当我们试图解决它时,我们的头撞到了我们在旅途中遇到的其他墙壁。所以我们开始吧。
我们想做的事
我们的客户可以拥有需要续订的各种类型的订阅。这些订阅有各种风格,可以有不同的计费间隔、不同的货币和不同的价格。
在我们的客户仪表板上,我们希望向他们展示一张漂亮的卡片,告知客户他们即将进行的续订,并很好地估计费用将是多少,这样他们就可以确保他们有足够的积分:
由于我们的订阅有不同的风格,我们有一个表格来保存基本订阅详细信息,例如net_renewal_date
. 它还引用了subscriptionable_id
其中subscriptionable_type
一个与用户可以订阅的不同类型模型的变形关系。
我们的第一次尝试
在我们的第一次尝试中,我们基本上添加了一个 REST 端点来获取即将到来的更新预测。
基本上,在接下来的 30 天里,所有需要续订的订阅都被占用了。对于这些项目中的每一个,我们将以其货币计算当前价格,并添加税收计算。
然后将其返回到我们进一步用于的集合中: 1/ 计算每种货币的总数 2/ 在接下来的 14 天内过滤该集合的项目,并计算每种货币的相同总数。
然后,我们基本上只需将不同的金额转换为我们的基础货币 (EUR) 并返回其总和。
这对我们的绝大多数客户都很有效。即使是拥有 100 个订阅的客户也完全没有问题。
但随后我们将一位较大的客户迁移到了新平台。在接下来的 30 天里,他基本上有 1500 多个订阅更新,所以不太顺利......
我们的第二次尝试 因为通过上面的代码根本无法在可接受的时间内工作,我们决定我们必须将模拟计算转移到一个单独的工作中。
我们在订阅表中添加了一个属性并将其命名为“simulated_renewal_amount”
每次在以下情况下都需要运行此作业: - 价格变化 - 客户的折扣会发生变化(基于他的忠诚度,我们提供单独的价格 - 汇率变化。
所以我们的想法是监听这些变化,然后派出一个作业来重新计算任何相关订阅的模拟量。然而,这意味着例如汇率的变化可以很容易地触发 10,000 个要处理的工作。
这就是它变得棘手的地方。尽管在大多数情况下只运行一个作业只需要不到 1200 毫秒,但似乎调度大量需要为一组订阅执行相同计算的作业会导致作业在中止时运行 60 多秒。
设置这种排队作业的最佳做法是什么?我应该只创建一份工作并按顺序处理它们吗?
任何关于我们如何最好地设置它的见解,都将非常受欢迎。我们已经用它玩了很多,它似乎总是以同样的问题结束。
仅供参考 - 我们将站点托管在 laravel vapor 上,因此在 AWS 基础设施上使用 Aurora 数据库是无服务器的。