摘要:原文鏈接我們推送到隊(duì)列的每個(gè)作業(yè)都存儲(chǔ)在按執(zhí)行順序排序的某些存儲(chǔ)空間中,該存儲(chǔ)位置可以是數(shù)據(jù)庫,存儲(chǔ)或像這樣的第三方服務(wù)。這個(gè)數(shù)字從開始,在每次運(yùn)行作業(yè)時(shí)不斷增加。
原文鏈接https://divinglaravel.com/queue-system/preparing-jobs-for-queue
Every job we push to queue is stored in some storage space sorted by the order of execution, this storage place could be a MySQL database, Redis store, or a 3rd party service like Amazon SQS.
我們推送到隊(duì)列的每個(gè)作業(yè)都存儲(chǔ)在按執(zhí)行順序排序的某些存儲(chǔ)空間中,該存儲(chǔ)位置可以是MySQL數(shù)據(jù)庫,Redis存儲(chǔ)或像Amazon SQS這樣的第三方服務(wù)。
Later in this dive we"re going to explore how workers fetch these jobs and start executing them, but before that let"s see how we store our jobs, here are the attributes we keep for every job we store:
在這次深入探究之后,我們將探索worker如何獲取這些作業(yè)并開始執(zhí)行這些作業(yè),但在此之前,讓我們看看我們?nèi)绾未鎯?chǔ)我們的作業(yè),這里是我們?yōu)槊總€(gè)我們存儲(chǔ)的作業(yè)所保留的屬性:
What queue it should be running through
The number of times this job was attempted (Initially zero)
The time when the job was reserved by a worker
The time when the job becomes available for a worker to pickup
The time when the job was created
The payload of the job
應(yīng)該運(yùn)行什么隊(duì)列
此作業(yè)嘗試次數(shù)(最初為零)
作業(yè)由worker保留的時(shí)間
作業(yè)時(shí)間可供worker領(lǐng)取
創(chuàng)建作業(yè)的時(shí)間
作業(yè)的有效載荷
What do you mean by queue?
你說的排隊(duì)是什么意思?
Your application sends several types of jobs to queue, by default all the jobs are put in a single queue; however, you might want to put mail jobs in a different queue and instruct a dedicated worker to run jobs only from this queue, this will ensure that other jobs won"t delay sending emails since it has a dedicated worker of its own.
您的應(yīng)用程序發(fā)送很多類型的作業(yè)到隊(duì)列,默認(rèn)情況下,所有作業(yè)都放在單個(gè)隊(duì)列中; 但是,您可能希望將郵件作業(yè)放在不同的隊(duì)列中,并指示專用worker僅從此隊(duì)列運(yùn)行作業(yè),這將確保其他作業(yè)不會(huì)延遲發(fā)送電子郵件,因?yàn)樗哂凶约旱膶S脀orker。
The number of attempts
嘗試次數(shù)
By default the queue manager will keep trying to run a specific job if it fails running, it"ll keep doing that forever unless you set a maximum number of attempts, when the job attempts reach that number the job will be marked as failed and workers won"t try to run it again. This number starts as zero but we keep incrementing it every time we run the job.
默認(rèn)情況下,如果運(yùn)行失敗,隊(duì)列管理器將繼續(xù)嘗試運(yùn)行特定的作業(yè),除非您設(shè)置了最大次數(shù),否則將繼續(xù)執(zhí)行此操作,當(dāng)作業(yè)嘗試達(dá)到該數(shù)量時(shí),該作業(yè)將被標(biāo)記為失敗,并且worker 不會(huì)再嘗試運(yùn)行它。 這個(gè)數(shù)字從0開始,在每次運(yùn)行作業(yè)時(shí)不斷增加。
The Reservation time
預(yù)約時(shí)間
Once a worker picks a job we mark it as reserved and store the timestamp of when that happened, next time a worker tries to pick a new job it won"t pick a reserved one unless the reservation lock is expired, but more on that later.
一旦worker選擇了一個(gè)作業(yè),我們將其標(biāo)記為保留,并存儲(chǔ)發(fā)生的時(shí)間戳,下一次worker嘗試選擇新的作業(yè)時(shí),除非保留鎖定已過期,否則不會(huì)選擇保留位。
The availability time
可用時(shí)間
By default a job is available once it"s pushed to queue and workers can pick it right away, but sometimes you might need to delay running a job for sometime, you can do that by providing a delay while pushing the job to queue using the later() method instead of push():
默認(rèn)情況下,一旦作業(yè)被推送到隊(duì)列,worker可以立即獲取它,但有時(shí)您可能需要延遲一段時(shí)間的運(yùn)行作業(yè),您可以通過 later() 方法而不是 push()來延遲來推送作業(yè):
Queue::later(60, new SendInvoice())
The later() method uses the availableAt() method to determine the availability time:
后者 later() 方法使用 availableAt() 方法來確定可用性時(shí)間:
protected function availableAt($delay = 0) { return $delay instanceof DateTimeInterface ? $delay->getTimestamp() : Carbon::now()->addSeconds($delay)->getTimestamp(); }
As you can see you can pass an instance of DateTimeInterface to set the exact time, or you can pass the number of seconds and Laravel will calculate the availability time for you under the hood.
您可以看到,您可以傳遞一個(gè) DateTimeInterface 的實(shí)例來設(shè)置確切的時(shí)間,或者您可以傳遞秒數(shù),Laravel會(huì)計(jì)算出您的可用時(shí)間。
The payload
有效載荷
The push() & later() methods use the createPayload() method internally to create the information needed to execute the job when it"s picked by a worker. You can pass a job to queue in two formats:
push() & later() 方法在內(nèi)部使用 createPayload() 方法來創(chuàng)建執(zhí)行作業(yè)所需的信息,當(dāng)worker選擇它時(shí)。 您可以通過兩種格式將作業(yè)傳遞給隊(duì)列:
// Pass an object Queue::push(new SendInvoice($order)); // Pass a string Queue::push("AppJobsSendInvoice@handle", ["order_id" => $orderId])
In the second example while the worker is picking the job, Laravel will use the container to create an instance of the given class, this gives you the chance to require any dependencies in the job"s constructor.
在第二個(gè)例子中,當(dāng)worker正在選擇作業(yè)時(shí),Laravel將使用該容器來創(chuàng)建給定類的實(shí)例,這樣可以讓您有機(jī)會(huì)在作業(yè)的構(gòu)造函數(shù)中包含任何依賴。
Creating the payload of a string job
創(chuàng)建字符串作業(yè)的有效負(fù)荷
createPayload() calls createPayloadArray() internally which calls the createStringPayload() method in case the job type is non-object:
createPayload()在內(nèi)部調(diào)用 createPayloadArray(),調(diào)用 createStringPayload() 方法,以防作業(yè)類型為空對(duì)象:
protected function createStringPayload($job, $data) { return [ "displayName" => is_string($job) ? explode("@", $job)[0] : null, "job" => $job, "maxTries" => null, "timeout" => null, "data" => $data, ]; }
The displayName of a job is a string you can use to identify the job that"s running, in case of non-object job definitions we use the the job class name as the displayName.
Notice also that we store the given data in the job payload.
作業(yè)的displayName 是可用于標(biāo)識(shí)正在運(yùn)行的作業(yè)的字符串,在空對(duì)象作業(yè)定義的情況下,我們使用作業(yè)類名稱作為 displayName.
Notice also that we store the given data in the job payload.
還要注意,我們將給定的數(shù)據(jù)存儲(chǔ)在作業(yè)有效載荷中。
Creating the payload of an object job
創(chuàng)建對(duì)象作業(yè)的有效負(fù)載
Here"s how an object-based job payload is created:
以下是創(chuàng)建基于對(duì)象的作業(yè)有效負(fù)載的方式:
protected function createObjectPayload($job) { return [ "displayName" => $this->getDisplayName($job), "job" => "IlluminateQueueCallQueuedHandler@call", "maxTries" => isset($job->tries) ? $job->tries : null, "timeout" => isset($job->timeout) ? $job->timeout : null, "data" => [ "commandName" => get_class($job), "command" => serialize(clone $job), ], ]; }
Since we already have the instance of the job we can extract some useful information from it, for example the getDisplayName() method looks for a displayName() method inside the job instance and if found it uses the return value as the job name, that means you can add such method in your job class to be in control of the name of your job in queue.
由于我們已經(jīng)有了這個(gè)作業(yè)的實(shí)例,我們可以從中提取一些有用的信息,例如, getDisplayName() 方法在作業(yè)實(shí)例中查找一個(gè) displayName() 方法,如果發(fā)現(xiàn)它使用返回值作為作業(yè)名稱,那么 意味著您可以在作業(yè)類中添加這樣的方法來控制隊(duì)列中作業(yè)的名稱。
protected function getDisplayName($job) { return method_exists($job, "displayName") ? $job->displayName() : get_class($job); }
We can also extract the value of the maximum number a job should be retried and the timeout for the job, if you pass these values as class properties Laravel stores this data into the payload for use by the workers later.
As for the data attribute, Laravel stores the class name of the job as well as a serialized version of that job.
如果將這些值作為類屬性傳遞,我們還可以提取作業(yè)應(yīng)該重試的最大數(shù)量和作業(yè)的超時(shí)值,Laravel將此數(shù)據(jù)存儲(chǔ)到有用的worker中以供以后使用。
對(duì)于數(shù)據(jù)屬性,Laravel存儲(chǔ)作業(yè)的類名稱以及該作業(yè)的序列化版本。
Then how can I pass my own data
那么如何傳遞我自己的數(shù)據(jù)
In case you chose to pass an object-based job you can"t provide a data array, you can store any data you need inside the job instance and it"ll be available once un-serialized.
如果您選擇傳遞基于對(duì)象的作業(yè),則無法提供數(shù)據(jù)數(shù)組,您可以在作業(yè)實(shí)例中存儲(chǔ)所需的任何數(shù)據(jù),并且一旦未序列化,它都是可用的。
Why do we pass a different class as the "job" parameter
為什么我們通過不同的類作為“作業(yè)”的參數(shù)
QueueCallQueuedHandler@call is a special class Laravel uses while running object-based jobs, we"ll look into it in a later stage.
QueueCallQueuedHandler@call 是Laravel在運(yùn)行基于對(duì)象的作業(yè)時(shí)使用的一個(gè)特殊類,我們將在稍后的階段進(jìn)行研究。
Serializing jobs
序列化作業(yè)
Serializing a PHP object generates a string that holds information about the class the object is an instance of as well as the state of that object, this string can be used later to re-create the instance.
In our case we serialize the job object in order to be able to easily store it somewhere until a worker is ready to pick it up & run it, while creating the payload for the job we serialize a clone of the job object:
序列化PHP對(duì)象會(huì)生成一個(gè)字符串,該字符串保存有關(guān)該對(duì)象是該實(shí)例的類的信息以及該對(duì)象的狀態(tài),此字符串以后可用于重新創(chuàng)建該實(shí)例。
一般情況下,我們序列化作業(yè)對(duì)象,以便能夠輕松地將其存儲(chǔ)在某個(gè)位置,直到worker準(zhǔn)備好接收并運(yùn)行它,為作業(yè)創(chuàng)建有效負(fù)載的同時(shí)我們將序列化作業(yè)對(duì)象的克隆:
serialize(clone $job);
But why a clone? why not serialize the object itself?
但為什么要克?。?為什么不序列化對(duì)象本身?
While serializing the job we might need to do some transformation to some of the job properties or properties of any of the instances our job might be using, if we pass the job instance itself transformations will be applied to the original instances while this might not be desired, let"s take a look at an example:
在序列化作業(yè)時(shí),我們可能需要對(duì)我們的作業(yè)可能使用的任何實(shí)例的某些作業(yè)屬性或?qū)傩赃M(jìn)行一些轉(zhuǎn)換,如果我們傳遞作業(yè)實(shí)例本身,轉(zhuǎn)換將應(yīng)用于原始實(shí)例,而這可能不是 期望的,讓我們來看一個(gè)例子:
class SendInvoice { public function __construct(Invoice $Invoice) { $this->Invoice = $Invoice; } } class Invoice { public function __construct($pdf, $customer) { $this->pdf = $pdf; $this->customer = $customer; } }
While creating the payload for the SendInvoice job we"re going to serialize that instance and all its child objects, the Invoice object, but PHP doesn"t always work well with serializing files and the Invoice object has a property called $pdf which holds a file, for that we might want to store that file somewhere, keep a reference to it in our instance while serializing and then when we un-serialize we bring back the file using that reference.
在為 SendInvoice 作業(yè)創(chuàng)建載荷時(shí),我們將序列化該實(shí)例及其所有子對(duì)象,發(fā)票, 但PHP并不總是能很好地處理序列化文件,并且發(fā)票對(duì)象具有稱為 $pdf 的屬性,該屬性包含 文件,因?yàn)槲覀兛赡芟胍獙⒃撐募鎯?chǔ)在某個(gè)地方,在序列化期間保留對(duì)我們實(shí)例的引用,然后當(dāng)我們進(jìn)行非序列化時(shí),我們使用該引用返回文件。
class Invoice { public function __construct($pdf, $customer) { $this->pdf = $pdf; $this->customer = $customer; } public function __sleep() { $this->pdf = stream_get_meta_data($this->pdf)["uri"]; return ["customer", "pdf"]; } public function __wakeup() { $this->pdf = fopen($this->pdf, "a"); } }
The __sleep() method is automatically called before PHP starts serializing our object, in our example we transform our pdf property to hold the path to the PDF resource instead of the resource itself, and inside __wakup() we convert that path back to the original value, that way we can safely serialize the object.
Now if we dispatch our job to queue we know that it"s going to be serialized under the hood:
在PHP開始序列化我們的對(duì)象之前,__sleep() 方法被自動(dòng)調(diào)用,在我們的示例中,我們將我們的pdf屬性轉(zhuǎn)換為保存到PDF資源的路徑而不是資源本身,而在__wakup() 中,我們將該路徑轉(zhuǎn)換回原始值,這樣我們可以安全地序列化對(duì)象。
現(xiàn)在如果我們分發(fā)作業(yè)到隊(duì)列,將被序列化:
$Invoice = new Invoice($pdf, "Customer #123"); Queue::push(new SendInvoice($Invoice)); dd($Invoice->pdf);
However, if we try to look at the Invoice pdf property after sending the job to queue we"ll find that it holds the path to the resource, it doesn"t hold the resource anymore, that"s because while serializing the Job PHP serialized the original Invoice instance as well since it was passed by reference to the SendInvoice instance.
然而,如果我們?cè)诎l(fā)送作業(yè)到隊(duì)列后嘗試查看發(fā)票pdf屬性,我們會(huì)發(fā)現(xiàn)它擁有資源的路徑,它不再占用資源,這是因?yàn)樾蛄谢鳂I(yè)時(shí)PHP已經(jīng)序列化了原始發(fā)票實(shí)例,因?yàn)樗ㄟ^引用傳遞給SendInvoice實(shí)例。
Here"s when cloning becomes handy, while cloning the SendInvoice object PHP will create a new instance of that object but that new instance will still hold reference to the original Invoice instance, but we can change that:
以下是克隆handy時(shí),克隆 SendInvoice 對(duì)象時(shí)PHP將創(chuàng)建該對(duì)象的新實(shí)例,但新的實(shí)例仍將保留對(duì)原始Invoice實(shí)例的引用,但是我們可以更改:
class SendInvoice { public function __construct(Invoice $Invoice) { $this->Invoice = $Invoice; } public function __clone() { $this->Invoice = clone $this->Invoice; } }
Here we instruct PHP that whenever it clones an instance of the SendInvoice object it should use a clone of the invoice property in the new instance not the original one, that way the original Invoice object will not be affected while we serialize.
這里我們介紹PHP只要克隆 SendInvoice 對(duì)象的一個(gè)實(shí)例,它應(yīng)該使用新實(shí)例中的Invoice屬性的克隆,而不是原始實(shí)例,那么原始Invoice對(duì)象在序列化時(shí)不會(huì)受到影響。
轉(zhuǎn)載請(qǐng)注明:?轉(zhuǎn)載自Ryan是菜鳥 | LNMP技術(shù)棧筆記
如果覺得本篇文章對(duì)您十分有益,何不 打賞一下
本文鏈接地址:?剖析Laravel隊(duì)列系統(tǒng)--準(zhǔn)備隊(duì)列作業(yè)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/23160.html
摘要:有幾種有用的方法可以使用將作業(yè)推送到特定的隊(duì)列在給定的秒數(shù)之后推送作業(yè)延遲后將作業(yè)推送到特定的隊(duì)列推送多個(gè)作業(yè)推送特定隊(duì)列上的多個(gè)作業(yè)調(diào)用這些方法之后,所選擇的隊(duì)列驅(qū)動(dòng)會(huì)將給定的信息存儲(chǔ)在存儲(chǔ)空間中,供按需獲取。 原文鏈接https://divinglaravel.com/queue-system/pushing-jobs-to-queue There are several ways...
摘要:一旦這一切完成,方法會(huì)運(yùn)行在類屬性在命令構(gòu)造后設(shè)置容器解析實(shí)例,在中我們?cè)O(shè)置了將使用的緩存驅(qū)動(dòng),我們也根據(jù)命令來決定我們調(diào)用什么方法。作業(yè)只在以上起效在上也無效處理作業(yè)方法調(diào)用觸發(fā)事件觸發(fā)事件。 譯文GitHub https://github.com/yuansir/diving-laravel-zh 原文鏈接https://divinglaravel.com/queue-system...
摘要:配有內(nèi)置的隊(duì)列系統(tǒng),可幫助您在后臺(tái)運(yùn)行任務(wù),并通過簡單的來配置系統(tǒng)在不同情況下起作用。您可以在中管理隊(duì)列配置,默認(rèn)情況下它有使用不同隊(duì)列驅(qū)動(dòng)的幾個(gè)連接,您可以看到項(xiàng)目中可以有多個(gè)隊(duì)列連接,也可以使用多個(gè)隊(duì)列驅(qū)動(dòng)程序。 原文鏈接https://divinglaravel.com/queue-system/before-the-dive Laravel receives a request...
摘要:所以在這里創(chuàng)建一個(gè)事件的兩個(gè)實(shí)際方法是通過調(diào)用或,第一個(gè)提交一個(gè)的實(shí)例,后者提交來做一些特殊處理。那么會(huì)用表達(dá)式檢查命令是否到期嗎恰恰相反,使用庫來確定命令是否基于當(dāng)前系統(tǒng)時(shí)間相對(duì)于我們?cè)O(shè)置的時(shí)區(qū)。 譯文GitHub https://github.com/yuansir/diving-laravel-zh 原文鏈接 https://divinglaravel.com/task-sche...
摘要:搶占式優(yōu)先權(quán)調(diào)度算法在這種方式下,系統(tǒng)同樣是把處理機(jī)分配給優(yōu)先權(quán)最高的進(jìn)程,使之執(zhí)行。多級(jí)反饋隊(duì)列調(diào)度算法應(yīng)設(shè)置多個(gè)就緒隊(duì)列,并為各個(gè)隊(duì)列賦予不同的優(yōu)先級(jí)。showImg(https://user-gold-cdn.xitu.io/2019/5/22/16adb237e3568dd3); 一 優(yōu)先調(diào)度算法 1.先來先服務(wù)調(diào)度算法(FCFS) 當(dāng)在作業(yè)調(diào)度中采用該算法時(shí),每次調(diào)度都是從后備作...
閱讀 3446·2021-11-23 09:51
閱讀 3722·2021-10-13 09:39
閱讀 2660·2021-09-22 15:06
閱讀 978·2019-08-30 15:55
閱讀 3254·2019-08-30 15:44
閱讀 1936·2019-08-30 14:05
閱讀 3538·2019-08-29 15:24
閱讀 2448·2019-08-29 12:44