Laravel Ononeserver

移植onOneServer方法至Laravel5.2

如果您的应用程序在多个服务器上运行,则你可能会想限制计划任务仅在单个服务器上执行。 例如,您有一个计划任务,每个星期五晚上都会生成一个新报告。 如果在三台服务器上运行,则将在所有三台服务器上运行并生成三次报告。 这样不好!

为了让计划任务只在一台服务器上运行,在定义计划任务时可使用 onOneServer 方法。原理是获取到该任务的第一台服务器将对该任务加上原子锁,以防止其他服务器同时运行相同的任务。

这是laravel-china文档上的说明。

onOneServer()这个方法,在5.6才有,但是在我们的服务分布式部署情况下,却是十分需要的。

原理

非常简单,第一个执行的节点对该任务加上原子锁。

实现

如何能够达到原子锁,那么最好使用redis。

在Laravel中的核心命令是: Redis::add()

转换为Redis核心命令为:setnx

该命令意义为:如果不存在,那么就SET。

该命令是原子性的,也就是说当第一个任务SET了值之后,后边其他相同的任务都会无法执行。

代码

  1. 对Event类添加onOneServer方法及参数。

    vendor/laravel/framework/src/Illuminate/Console/Scheduling/Event.php

     class Event
     {
         // ...
         // 判断参数
         public $onOneServer = false;
        
         // 设置函数
         public function onOneServer()
         {
             $this->onOneServer = true;
        
             return $this;
         }
     }
        
    
  2. 运行时执行真正操作

    vendor/laravel/framework/src/Illuminate/Console/Scheduling/ScheduleRunCommand.php

     /**
      * Execute the console command.
      *
      * @return void
      */
     public function fire()
     {
         // ...
         foreach ($events as $event) {
             if (! $event->filtersPass($this->laravel)) {
                 continue;
             }
        
             if ($event->onOneServer) { // 是否只能运行在单个节点上
                 $this->runSingleServerEvent($event);
             } else {
                 $this->runEvent($event);
             }
        
             ++$eventsRan;
         }
         // ...
     }
        
     /**
      * 将事件进行上锁处理
      *
      * @param Event $event
      * @return void
      * @author vogan <[email protected]>
      */
     protected function runSingleServerEvent($event)
     {
         if ($this->schedule->serverShouldRun($event)) {
             $this->runEvent($event);
         } else {
             $this->line('<info>Skipping command (has already run on another server):</info> '.$event->getSummaryForDisplay());
         }
     }
    

    vendor/laravel/framework/src/Illuminate/Console/Scheduling/Schedule.php

     public function serverShouldRun($event)
     {
         // 创建一个锁,返回是否成功
         return $this->schedulingMutex->create($event);
     }
    

    vendor/laravel/framework/src/Illuminate/Console/Scheduling/SchedulingMutex.php

     /**
      * 对事件创建任务锁
      *
      * @param Event $event
      * @return bool
      * @author vogan <[email protected]>
      */
     public function create($event)
     {
         // 最终调用的即是cache->add()方法,
         // key名为锁的名称,value为true,
         // 另外设置一个超时时间,防止任务执行失败,造成了一个死锁不释放。
         return $this->cache->add(
             $event->mutexName(), true, $event->expiresAt
         );
     }
    

上手群晖218+

平时喜欢看电影,同事赠送了一个pt站的邀请码,手头正好有2个盘,1条内存,然后心里长草需求就入手NAS。

初识nginx 了解反向代理

昨天打了一下午的游戏。晚上没事干想到那天在网上看到有人用自己在墙外能访问Google的vps搭建了一个反向代理,用来简单的进行google搜索。

Finalspeed安装测试

昨天在V2EX看到一篇帖子,说到有的黑科技出现了,可以让vps跑到满速,另外看见评论中说到搬瓦工的架构也能使用,所以马上试试。

树莓派 做了一个aria2下载机+迅雷离线下载

当初看了异次元软件的一片小文章说到树莓派,神智不清的情况下过了短时间就买了。本来天真的以为真的像小电脑一样,至少能装个ubuntu系统在宿舍看看视频啥的是吧,回头还买了个二手的显示器放在了宿舍。结果就是堆灰。其实树莓派还是和真正的电脑有区别的,还是有限制。