Laravel - 要在远程系统上处理的作业的序列化

时间:2017-07-08 22:52:10

标签: php laravel laravel-5

简介/系统架构

  • 服务器A - Laravel安装,数据库A
  • 服务器B - RabbitMQ服务器
  • 服务器C - Laravel安装,数据库B

服务器A 是一个API端点,仅接收来自远程源的呼叫。根据呼叫,它会将作业添加到RabbitMQ服务器(服务器B ),然后由服务器C 处理/监听。

服务器A 包含由 Server C 处理的完全相同作业的本地副本。作业处理程序代码和构造函数如下所示(作业代码)。

问题: 服务器A无法序列化作业并将其添加到队列,因为它尝试访问有关仅存在于数据库B( Server C )中的监视器的信息。 服务器A 具有该模型的副本,但不包含实际的数据库表或记录,因为它对它们没有用处 - 它只是用于序列化作业并说“&#34” ;这就是服务器C )应该做的事情。"

但是,在发布作业时,它还试图获取数据库信息(可能会序列化所需的确切数据),但由于记录不存在而无法完成。

我对Laravel的SerializesModels的理解是,它只会序列化模型调用本身,而不会实际执行任何与数据库相关的操作。这似乎不起作用,或者我误解/误用它 - 尽管很少有文档可用。

变通方法:一种可能的解决方法是在 Server C 上简单地授予 Server A 对数据库的访问权限。在这种情况下,这不是一个选项,因为它会破坏旨在实现高可用性的设计(API端点和队列永远不可用,但队列处理器可能不可用)。

TopDown View

代码

相关职位代码

// Models
use App\UptimeMonitor;

// Notifications
use App\Notifications\StatusQueue as StatusNotification;

class StatusQueue implements ShouldQueue
{
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

        protected $monitor_source;
        protected $monitor_data;
        protected $monitor_repository;

        /**
         * Create a new job instance.
         *
         * @param string[] monitor_source (Eg: HetrixTools)
         * @param array[] monitor_data (All data passed from the source)
         *
         */
        public function __construct($monitor_source, array $monitor_data)
        {
            $this->monitor_source = $monitor_source;
            $this->monitor_data = $monitor_data;

            if($this->monitor_source === 'centric')
                    return $this->centric();

        }

        /**
         * Centric Uptime Monitoring
         */
        public function centric()
        {
                $result = ($this->monitor_data['monitor_status'] == 'online') ? 'online' : 'timeout';

                try {
                        $monitor = UptimeMonitor::where('identifier', '=', $this->monitor_data['monitor_id'])->firstOrFail();
                        $status = $monitor->status()->firstOrFail();
                        $contacts = $monitor->contacts()->get();
                } catch (Exception $e) {
                        return Log::error('[JOBS::StatusQueue::centric] - ' . $e);
                }

                $status->state = $result;

                if(!$contacts)
                        return true;

                foreach($contacts as $contact) {
                        $contact->notify(new StatusNotification($monitor, $status));
                }
        }
}

其他代码

如果您确实需要任何其他代码,请告诉我们!但是,这应该涵盖作业类本身的整个功能。除此之外,所有发生的事情都是发布这项工作 - 以及如何根据构造函数完成这项工作。

问题

所有这一切的最后一个问题:为什么这会失败(因为;为什么它不能序列化作业,而不需要数据库信息?) - 你是否看到了解决这个问题的方法,到了哪里我不需要从 Server C 访问数据库以从 Server A 排队作业,仍然使用Laravel的队列机制?

一如既往地有责任!

1 个答案:

答案 0 :(得分:0)

事实证明,最简单的解决方案几乎总是正确的。

服务器A不需要具有服务器B将处理的作业的副本 - 它可以具有相同类的完全空作业,并且服务器B仍将正确处理它。 / p>

因此,现在这是服务器A上的作业:

class AlertQueue implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $job;

    /**
     * Create a new job instance.
     *
     */
    public function __construct()
    {

    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //
    }
}

虽然服务器B也有一个AlertQueue作业,它具有实际执行的所有逻辑。