服务器A 是一个API端点,仅接收来自远程源的呼叫。根据呼叫,它会将作业添加到RabbitMQ服务器(服务器B ),然后由服务器C 处理/监听。
服务器A 包含由 Server C 处理的完全相同作业的本地副本。作业处理程序代码和构造函数如下所示(作业代码)。
问题: 服务器A无法序列化作业并将其添加到队列,因为它尝试访问有关仅存在于数据库B( Server C )中的监视器的信息。 服务器A 具有该模型的副本,但不包含实际的数据库表或记录,因为它对它们没有用处 - 它只是用于序列化作业并说“&#34” ;这就是你(服务器C )应该做的事情。"
但是,在发布作业时,它还试图获取数据库信息(可能会序列化所需的确切数据),但由于记录不存在而无法完成。
我对Laravel的SerializesModels
的理解是,它只会序列化模型调用本身,而不会实际执行任何与数据库相关的操作。这似乎不起作用,或者我误解/误用它 - 尽管很少有文档可用。
变通方法:一种可能的解决方法是在 Server C 上简单地授予 Server A 对数据库的访问权限。在这种情况下,这不是一个选项,因为它会破坏旨在实现高可用性的设计(API端点和队列永远不可用,但队列处理器可能不可用)。
相关职位代码
// 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的队列机制?
一如既往地有责任!
答案 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作业,它具有实际执行的所有逻辑。