【问题标题】:Problem with notification scheduling in WEB ApplicationsWEB应用程序中的通知调度问题
【发布时间】:2021-09-21 03:52:53
【问题描述】:

上下文

我目前正在实施一项功能,以使用 PHP 和 Firebase 通过网络表单在特定时间段内安排通知。

为了发送通知,我使用 Firebase 并将通知发送到 Android/Ios。

为了安排通知,我使用了AT linux 服务,因为它似乎比cron 更适合,因为cron 以特定频率运行而AT 没有,它在特定时间运行。

关于 AT 的手册页:man page AT

示例代码

/usr/bin/php `send_notification.php` | at 2021-07-11 15:40

这将在 linux 上创建一个文件,该文件将在 2021-07-11 15:40 期间仅运行一次。

问题

AT 服务与CRON 一样,在操作系统的目录中创建代表作业的文件。

1 - 如果 AWS 上的机器进行扩展,作业可能会重复,因此会多次发送通知。 (注:我对机器扩展了解不多,但我相信它应该会发生)

2 - 如果机器由于包含某些功能或类似的东西而处于停机状态,我相信它目前的工作方式不会被执行。

3 - 另一个问题,但不是主要问题,是如果我使用的是 docker 容器。由于 Ubuntu + PHP 在容器内,如果我重新启动容器,作业文件可能会丢失,所以在这种情况下,我相信解决方案是使用卷,但现在这不是我的问题,因为目前的应用程序仅使用 AWS EB 上的一台机器和 PHP 映像。

怀疑

  • 我有什么解决方案可以使用 PHP 解决这个重复作业问题吗?

  • 使用AT 的方法最合适吗?我看到很多人都在谈论使用CRON,但 CRON 会多次运行这项工作,对我来说,这不是我想要的。

【问题讨论】:

    标签: php cron amazon-elastic-beanstalk scheduled-tasks at-job


    【解决方案1】:

    我认为你需要一个地方来保存计划和完成的通知,独立于你使用的东西,cron 或 at。

    如果我有这样的任务,我会坚持这样的解决方案:运行特殊脚本,“scheduler.php”每 1(或更多,例如 5)分钟由 cron,这将检查一些日志文件(或远程数据库(如果是多台机器)并查看是否有任何新行。如果存在新行并且它包含过去的时间戳和“已调度”状态,则脚本将锁定它并运行您的“sender.php”。之后,它将将该行标记为“完成”。存储中的每一行都应包含要运行的时间戳以及“已调度”、“正在运行”和“已完成”三种状态之一。

    使用这种方法,您可以通过在存储中添加一条包含所需时间和“已计划”状态的行来计划新通知。请注意,计划时间和实际通知之间可能会有一点延迟,具体取决于 cron 间隔,但我认为这并不重要。

    这将允许您在不同的机器上运行任意数量的 crons,并保证每个作业都会执行一次。

    重要提示:如果您将采用此方案,请确保您的 scheduler.php 在单个原子操作中读取和更新存储,以防止多个 cron 之间的竞争条件。文件锁定,或“选择更新”即可。

    【讨论】:

    • 让我看看我是否理解,根据您的回答,将具有以下架构(时间戳、状态)的存储行 [数据库、日志文件] 类似于 crontab?示例:2021-07-12 19:43 |完成 2021-07-12 20:54 |运行时间 2021-07-12 20:56 |预定 但是对于动态的sender.php,这将如何工作?通知发送有一些不同的参数,如topictitlemessage,...我目前通过命令参数传递它并使用getopt在script.php中捕获示例:command.php --title="title xxx" --message="message xxxx"
    • 我的意思是像2021-07-14 12:30:00,scheduled 这样的格式,其中第一列是运行时间,第二列是状态。但是如果您需要为您的 sender.php 提供一些参数,您可以更改格式并添加其他列。
    • 您也可以使用更简单的解决方案:在执行实际工作之前修改您的 sender.php 以检查外部日志。将作业的唯一键(例如连接参数的哈希和当前时间)放入存储中,如果存在这样的键,则不要执行作业。然后像你一样继续使用 AT 手动运行脚本。
    • 我不太明白为什么“检查带有参数+时间戳连接的哈希”。为什么我应该在使用 AT 运行作业之前进行此检查?
    • “选择更新”还有一个更简单的替代方法:在字段上设置唯一索引,并在脚本运行时尝试插入新键。将此行包装在 try-catch 中,如果 mysql 代码 2300(“重复条目”)存在异常 - 密钥已经存在。这种技术也保证了原子性。
    猜你喜欢
    • 2021-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-22
    • 2014-05-19
    相关资源
    最近更新 更多