05 اسفند 1403
تست عملکرد صف های لاراول: ارسال 5000 فایل پی دی اف
In Laravel, dispatching a Job to the Queue is simple. But what about 5,000 jobs at once? Will it crash the server? How can we optimize it? We tried this experiment, and this article will tell you the results.
The task is to send THIS invoice PDF to the customer.
That is, to 5,000 customers. You know, that day of the month when you need to send monthly invoices to everyone? So yeah, we tried to mimic exactly that.
Here's the plan for this tutorial:
No Queue: will generating PDFs crash the server?
Moving to Queue and measuring the time
Optimization 1: Increase Queue Workers
Optimization 2: Bump up Server Specification
Optimization 3: Decrease Queue Workers (wait, what?)
Conclusion (for now)
At each step, we will take measurements and draw our conclusions.
Notice: In this tutorial, we measure the queues on the same server as the web application itself. We may potentially write a follow-up article on how to separate/scale queues on different servers.
Let's dive into the code and its (configuration) optimization!
1. Execute with No Queue
Here's our Controller for building PDFs for all users. For now, in a simple foreach loop, with no Queued Jobs:
Controller
class InstantGenerationExampleController extends Controller
{
public function __invoke()
{
$orders = Order::query()
->select(['id',
'user_id',
'order_number',
'total_amount',
'created_at',
])
->with([
'user:id,name,email',
'items:id,order_id,product_id,quantity,price',
'items.product:id,name',
])
->get();
$imageData = base64_encode(file_get_contents(public_path('logo-sample.png')));
$logo = 'data:image/png;base64,' . $imageData;
Benchmark::dd(function () use ($logo, $orders) {
foreach ($orders as $order) {
$pdf = PDF::loadView('orders.invoicePDF', ['order' => $order, 'logo' => $logo]);
$pdf->save(storage_path('app/public/' . $order->user_id . '-' . $order->id . '.pdf'));
}
}, 5);
}
}
Notice 1: To measure performance, in all our examples, we will use the Laravel Benchmark helper with 5 iterations. This means we will run our code 5 times and get the average time it took.
Notice 2: for now, we are running this on the cheap Digital Ocean server with these specs: