laravel⾼并发排队_使⽤事件和排队事件优化Laravel项⽬laravel⾼并发排队
It is amazing how supporting features in Laravel turn out to be as important as the "important" features. When creating an app, our basic flow is structure the models, create routes, handle them in a controller, and return nicely styled views.
令⼈惊奇的是,Laravel中的⽀持功能与“重要”功能⼀样重要。 创建应⽤程序时,我们的基本流程是构建模型,创建路线,在控制器中处理它们并返回样式精美的视图。
But what do we do when our code base starts growing unexpectedly and things start falling apart. Situations where we need to implement a particular logic more often, handle heavy HTTP requests, or deal with some other heavy tasks will arise when our projects start growing. Trust me on this one, controllers cannot take it alone, they will need support.
但是,当我们的代码库开始意外增长并且事情开始崩溃时,我们该怎么办。 当我们的项⽬开始发展时,就会出现需要更频繁地实现特定逻辑,处理⼤量HTTP请求或处理其他繁重任务的情况。 相信我这⼀点,控制者不能孤单,他们将需要⽀持。
Laravel has some nice features to make life easier for both the end users and developers. Features lik
e Queues and Events. Events , just like the name says, provide an observer pattern for implementing logic by listening for something else to happen. That sounds a little vague upfront, but the idea will be clear by the end of this article.
Laravel具有⼀些不错的功能,可以使最终⽤户和开发⼈员的⽣活更加轻松。 队列和事件等功能。 顾名思义, 事件通过侦听发⽣的其他事件为实现逻辑提供了观察者模式。 这听起来有些模糊,但是到本⽂结尾时,这个想法将很清楚。
We will discuss (with a practical example) how Events:
我们将(通过⼀个实际⽰例)讨论事件如何:
1. Support the DRY rule
⽀持DRY规则
2. Make our code easier to review and understand
使我们的代码更易于查看和理解
3. Lead to better performance with queued events.
排队事件导致更好的性能。
( )
To better appreciate what Events and Queued Events do, we will look at a typical controller and analyze the limitations. To do so, setup your .env to use Mailtrap for Emails and database driver for Queues:
为了更好地了解事件和排队事件的作⽤,我们将研究典型的控制器并分析其局限性。 为此,请将您的.env设置为对电⼦邮件使⽤Mailtrap,对队列使⽤database驱动程序:
QUEUE_DRIVER=database
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=MAILTRAP-INBOX-USERNAME
MAIL_PASSWORD=MAILTRAP-INBOX-PASSWORD
MAIL_ENCRYPTION=null
MAIL_FROM=YOUR@EMAIL.COM
MAIL_NAME=YOUR-NAME
迁移与模型 (Migrations and Models)
We need just two migrations, one for the articles table and the other for the queues:
我们只需要进⾏两次迁移,⼀次⽤于articles表,另⼀次⽤于队列:
php artisan make:migration create_articles_table --create=articles
php artisan queue:table
php artisan migrate
For this tutorial, we need just two models: a User model and an Article model. The User model has already been created by Laravel so all we need do is create one for the article:
对于本教程,我们只需要两个模型:⼀个User模型和⼀个Article模型。 Laravel已经创建了User模型,因此我们需要为⽂章创建⼀个模型:php artisan make:model Article
数据库播种器 (Database Seeders)
We will be sending emails to sample users, so it would be nice to seed the users database, which is created by Laravel. Create a new seed file at database/seeds named UsersTableSeeder by running:
我们将向⽰例⽤户发送电⼦邮件,因此最好为Laravel创建的users数据库添加种⼦。 通过运⾏以下命令在名
为UsersTableSeeder的database/seeds创建⼀个新的种⼦⽂件:
php artisan make:seeder UsersTableSeeder
And add the following in the run() method as seen below:
并在run()⽅法中添加以下内容,如下所⽰:
public function run()
{
factory(App\User::class, 10)->create();
}
Laravel looks for seeds in database/seeds/DatabaseSeeder.php so we can't just run the seed command now. Let us call the UsersTableSeeder in it's run():
Laravel在database/seeds/DatabaseSeeder.php寻种⼦,所以我们现在不能只运⾏种⼦命令。 让我们在run()调⽤UsersTableSeeder :
public function run()
{
Model::unguard();
$this->call(UsersTableSeeder::class);
Model::reguard();
}
We can now run the seed command
现在我们可以运⾏seed命令
php artisan db:seed
控制器和路线 (Controller and Routes)
We'll create two routes for this tutorial: one that presents us with a button to create an Article and another to actually create an article:
我们将为本教程创建两条路线:⼀条为我们提供创建⽂章的按钮,另⼀条为实际创建⽂章的按钮:
Route::get('/',  'ArticleController@index');
Route::get('/create',  'ArticleController@create');
We have created two routes pointing to a controller and controller actions that do not exists. To create the controller, run:
我们创建了两个路由,这些路由指向不存在的控制器和控制器动作。 要创建控制器,请运⾏:
php artisan make:controller ArticleController
Create an index() action method for the home page that just returns a view:
为仅返回视图的主页创建⼀个index()操作⽅法:
public function index()
{
return view("article.index");
}
The index() action method is returning a view called index in articles folder of the views directory generated by Laravel. Create the file with this small piece:
index()操作⽅法将在Laravel⽣成的views⽬录的articles⽂件夹中返回⼀个称为index的视图。 ⽤这个⼩⽚段创建⽂件:
<div class="container">
<div class="main">
<a href="/create" class="btn btn-default">Create Article</a>
如何运行php项目
</div>
</div>
The second action method, create() will handle the logic for creating a new article:
第⼆种操作⽅法create()将处理创建新⽂章的逻辑:
public function create()
{
$article_title = "Hi random title with " . str_random(10);
$users = User::all();
$article = new Article;
$article->title = $article_title;
$article->save();
foreach($users as $user){
Mail::raw("Checkout Scotch's new article titled: " . $article_title, function ($message) use ($user) {
$message->from('chris@scotch.io', 'Chris Sevilleja');
$message->to($user->email);
});
}
}
问题 (The problem)
Everything runs fine with this controller, so where is the problem? Although this code seems lean, what happens when we want to share the article we create on Facebook, Twitter and Google Plus? As we add more logic, our code will get twisted and confusing to our team members.
使⽤此控制器,⼀切运⾏正常,那么问题出在哪⾥呢? 尽管这段代码看起来很精简,但是当我们想分享在Facebook,Twitter和Google Plus上创建的⽂章时会发⽣什么? 随着我们添加更多逻辑,我们的代码将变得混乱并给我们的团队成员带来混乱。
There is also a very good chance that we will go against the DRY principle as we will most likely want to use certain logic in different places.
我们极有可能违反DRY原则,因为我们很可能希望在不同的地⽅使⽤某些逻辑。
Furthermore, the request takes huge amount of time to complete on a local PC. Over 30 seconds to dispatch just 10 mails as seen below.
此外,该请求需要花费⼤量时间才能在本地PC上完成。 在30秒内仅发送10封邮件,如下所⽰。
[2016-02-24 15:15:36] local.INFO: Request fired
[2016-02-24 15:16:10] local.INFO: Request ended
With Events and Queued Events, we can make a better project with a huge performance boost.
借助事件和排队事件,我们可以通过提⾼性能来制作更好的项⽬。
( )
It is time to add events to our simple app. Events are made up of two classes, the event class and the listener class. The event class is what is fired and the listener class is called once an event is fired.
现在是将事件添加到我们的简单应⽤程序的时候了。 事件由两个类组成, event类和listener类。 event类是触发事件,事件触发后将调
⽤listener类。
产⽣事件 (Generating Events)
Creating events in Laravel is simple. Laravel generates an EventServiceProvider for us to register our events at app/Providers. In the file, replace the listen with the following:
在Laravel中创建事件很简单。 Laravel为我们⽣成⼀个EventServiceProvider ,以便在app/Providers上注册我们的事件。 在⽂件中,
将listen替换为以下内容:
protected $listen = [
'App\Events\ArticleWasPublished' => [
'App\Listeners\SendNewsletter',
],
];
ArticleWasPublished is the event we want to fire after creating an article and SendNewsletter is the listener that will be called when the event is fired.
ArticleWasPublished是我们要在创建⽂章后触发的事件,⽽SendNewsletter是触发事件时将调⽤的侦听器。
We generate the event classes by running:
我们通过运⾏以下命令⽣成事件类:
php artisan event:generate
射击事件 (Firing Events)
To make use of our events, we need to adjust the create action method to fire the event after an article has been created:
为了利⽤我们的事件,我们需要调整create action⽅法以在create⽂章后触发事件:
public function create()
{
Log::info("Request fired");
$article_title = "Hi random title with " . str_random(10);
$article = new Article;
$article->title = $article_title;
$article->save();
Event::fire(new ArticleWasPublished($article_title));
Log::info("Request ended");
}
The mail sending logic has been moved out and we are just firing the event with the Event facade and passing the article title to it:
邮件发送逻辑已被移出,我们只是使⽤Event外观触发事件并将⽂章标题传递给它:
Event::fire(new ArticleWasPublished($article_title));
We are injecting the article title into the event so we need to edit the ArticleWasPublished class as well:
我们将⽂章标题注⼊到事件中,因此我们还需要编辑ArticleWasPublished类: