摘要:原文鏈接我們推送到隊列的每個作業都存儲在按執行順序排序的某些存儲空間中,該存儲位置可以是數據庫,存儲或像這樣的第三方服務。這個數字從開始,在每次運行作業時不斷增加。
原文鏈接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.
我們推送到隊列的每個作業都存儲在按執行順序排序的某些存儲空間中,該存儲位置可以是MySQL數據庫,Redis存儲或像Amazon SQS這樣的第三方服務。
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如何獲取這些作業并開始執行這些作業,但在此之前,讓我們看看我們如何存儲我們的作業,這里是我們為每個我們存儲的作業所保留的屬性:
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
應該運行什么隊列
此作業嘗試次數(最初為零)
作業由worker保留的時間
作業時間可供worker領取
創建作業的時間
作業的有效載荷
What do you mean by queue?
你說的排隊是什么意思?
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.
您的應用程序發送很多類型的作業到隊列,默認情況下,所有作業都放在單個隊列中; 但是,您可能希望將郵件作業放在不同的隊列中,并指示專用worker僅從此隊列運行作業,這將確保其他作業不會延遲發送電子郵件,因為它具有自己的專用worker。
The number of attempts
嘗試次數
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.
默認情況下,如果運行失敗,隊列管理器將繼續嘗試運行特定的作業,除非您設置了最大次數,否則將繼續執行此操作,當作業嘗試達到該數量時,該作業將被標記為失敗,并且worker 不會再嘗試運行它。 這個數字從0開始,在每次運行作業時不斷增加。
The Reservation time
預約時間
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選擇了一個作業,我們將其標記為保留,并存儲發生的時間戳,下一次worker嘗試選擇新的作業時,除非保留鎖定已過期,否則不會選擇保留位。
The availability time
可用時間
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():
默認情況下,一旦作業被推送到隊列,worker可以立即獲取它,但有時您可能需要延遲一段時間的運行作業,您可以通過 later() 方法而不是 push()來延遲來推送作業:
Queue::later(60, new SendInvoice())
The later() method uses the availableAt() method to determine the availability time:
后者 later() 方法使用 availableAt() 方法來確定可用性時間:
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.
您可以看到,您可以傳遞一個 DateTimeInterface 的實例來設置確切的時間,或者您可以傳遞秒數,Laravel會計算出您的可用時間。
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() 方法在內部使用 createPayload() 方法來創建執行作業所需的信息,當worker選擇它時。 您可以通過兩種格式將作業傳遞給隊列:
// 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.
在第二個例子中,當worker正在選擇作業時,Laravel將使用該容器來創建給定類的實例,這樣可以讓您有機會在作業的構造函數中包含任何依賴。
Creating the payload of a string job
創建字符串作業的有效負荷
createPayload() calls createPayloadArray() internally which calls the createStringPayload() method in case the job type is non-object:
createPayload()在內部調用 createPayloadArray(),調用 createStringPayload() 方法,以防作業類型為空對象:
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.
作業的displayName 是可用于標識正在運行的作業的字符串,在空對象作業定義的情況下,我們使用作業類名稱作為 displayName.
Notice also that we store the given data in the job payload.
還要注意,我們將給定的數據存儲在作業有效載荷中。
Creating the payload of an object job
創建對象作業的有效負載
Here"s how an object-based job payload is created:
以下是創建基于對象的作業有效負載的方式:
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.
由于我們已經有了這個作業的實例,我們可以從中提取一些有用的信息,例如, getDisplayName() 方法在作業實例中查找一個 displayName() 方法,如果發現它使用返回值作為作業名稱,那么 意味著您可以在作業類中添加這樣的方法來控制隊列中作業的名稱。
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.
如果將這些值作為類屬性傳遞,我們還可以提取作業應該重試的最大數量和作業的超時值,Laravel將此數據存儲到有用的worker中以供以后使用。
對于數據屬性,Laravel存儲作業的類名稱以及該作業的序列化版本。
Then how can I pass my own data
那么如何傳遞我自己的數據
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.
如果您選擇傳遞基于對象的作業,則無法提供數據數組,您可以在作業實例中存儲所需的任何數據,并且一旦未序列化,它都是可用的。
Why do we pass a different class as the "job" parameter
為什么我們通過不同的類作為“作業”的參數
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在運行基于對象的作業時使用的一個特殊類,我們將在稍后的階段進行研究。
Serializing jobs
序列化作業
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對象會生成一個字符串,該字符串保存有關該對象是該實例的類的信息以及該對象的狀態,此字符串以后可用于重新創建該實例。
一般情況下,我們序列化作業對象,以便能夠輕松地將其存儲在某個位置,直到worker準備好接收并運行它,為作業創建有效負載的同時我們將序列化作業對象的克隆:
serialize(clone $job);
But why a clone? why not serialize the object itself?
但為什么要克隆? 為什么不序列化對象本身?
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:
在序列化作業時,我們可能需要對我們的作業可能使用的任何實例的某些作業屬性或屬性進行一些轉換,如果我們傳遞作業實例本身,轉換將應用于原始實例,而這可能不是 期望的,讓我們來看一個例子:
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 作業創建載荷時,我們將序列化該實例及其所有子對象,發票, 但PHP并不總是能很好地處理序列化文件,并且發票對象具有稱為 $pdf 的屬性,該屬性包含 文件,因為我們可能想要將該文件存儲在某個地方,在序列化期間保留對我們實例的引用,然后當我們進行非序列化時,我們使用該引用返回文件。
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開始序列化我們的對象之前,__sleep() 方法被自動調用,在我們的示例中,我們將我們的pdf屬性轉換為保存到PDF資源的路徑而不是資源本身,而在__wakup() 中,我們將該路徑轉換回原始值,這樣我們可以安全地序列化對象。
現在如果我們分發作業到隊列,將被序列化:
$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.
然而,如果我們在發送作業到隊列后嘗試查看發票pdf屬性,我們會發現它擁有資源的路徑,它不再占用資源,這是因為序列化作業時PHP已經序列化了原始發票實例,因為它通過引用傳遞給SendInvoice實例。
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時,克隆 SendInvoice 對象時PHP將創建該對象的新實例,但新的實例仍將保留對原始Invoice實例的引用,但是我們可以更改:
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 對象的一個實例,它應該使用新實例中的Invoice屬性的克隆,而不是原始實例,那么原始Invoice對象在序列化時不會受到影響。
轉載請注明:?轉載自Ryan是菜鳥 | LNMP技術棧筆記
如果覺得本篇文章對您十分有益,何不 打賞一下
本文鏈接地址:?剖析Laravel隊列系統--準備隊列作業
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/23160.html
摘要:有幾種有用的方法可以使用將作業推送到特定的隊列在給定的秒數之后推送作業延遲后將作業推送到特定的隊列推送多個作業推送特定隊列上的多個作業調用這些方法之后,所選擇的隊列驅動會將給定的信息存儲在存儲空間中,供按需獲取。 原文鏈接https://divinglaravel.com/queue-system/pushing-jobs-to-queue There are several ways...
摘要:一旦這一切完成,方法會運行在類屬性在命令構造后設置容器解析實例,在中我們設置了將使用的緩存驅動,我們也根據命令來決定我們調用什么方法。作業只在以上起效在上也無效處理作業方法調用觸發事件觸發事件。 譯文GitHub https://github.com/yuansir/diving-laravel-zh 原文鏈接https://divinglaravel.com/queue-system...
摘要:配有內置的隊列系統,可幫助您在后臺運行任務,并通過簡單的來配置系統在不同情況下起作用。您可以在中管理隊列配置,默認情況下它有使用不同隊列驅動的幾個連接,您可以看到項目中可以有多個隊列連接,也可以使用多個隊列驅動程序。 原文鏈接https://divinglaravel.com/queue-system/before-the-dive Laravel receives a request...
摘要:所以在這里創建一個事件的兩個實際方法是通過調用或,第一個提交一個的實例,后者提交來做一些特殊處理。那么會用表達式檢查命令是否到期嗎恰恰相反,使用庫來確定命令是否基于當前系統時間相對于我們設置的時區。 譯文GitHub https://github.com/yuansir/diving-laravel-zh 原文鏈接 https://divinglaravel.com/task-sche...
摘要:搶占式優先權調度算法在這種方式下,系統同樣是把處理機分配給優先權最高的進程,使之執行。多級反饋隊列調度算法應設置多個就緒隊列,并為各個隊列賦予不同的優先級。showImg(https://user-gold-cdn.xitu.io/2019/5/22/16adb237e3568dd3); 一 優先調度算法 1.先來先服務調度算法(FCFS) 當在作業調度中采用該算法時,每次調度都是從后備作...
閱讀 2979·2021-11-23 09:51
閱讀 3609·2021-10-13 09:39
閱讀 2493·2021-09-22 15:06
閱讀 881·2019-08-30 15:55
閱讀 3147·2019-08-30 15:44
閱讀 1778·2019-08-30 14:05
閱讀 3434·2019-08-29 15:24
閱讀 2362·2019-08-29 12:44