swoole是如何实现任务定时自动化调度的?

swoole是如何实现任务定时自动化调度的?

https://www.muzilong.cn/article/117

开发环境

环境:lnmp下进行试验。

框架:laravel5

 

问题描述

这几天做银行对帐接口时,踩了一个坑,具体需求大致描述一下。

银行每天凌晨后,会开始准备昨天的交易流水数据,需要我们这边请求拿到。

因为他们给的是一个base64加密的zip压缩流,解开以后可以得到txt文件,里面就是我们需要的数据了。

业务程序写好以后,随手丢了一个定时任务就去睡觉了。

哪知道第二天上班的时候,检查。发现并没有拿到数据,查询一下日志的时候发现,凌晨服务端请求的时候,银行接口返回了:系统错误信息。

咨询银行那边后,银行那边相关人员建议我们多请求几次,但是在多次请求中,我发现银行那边是有频率限制的,最后得知,此接口只能半个小时才能请求一次。这就比较尴尬了,因为我不知道银行那边什么时候能返回数据给我。

于是这个问题怎么解决呢?理想的情况是,服务端请求数据,银行那边没有返回。然后程序等半个小时后,再请求一次,这样一直到银行那边返回正确的数据中止。

 

问题分析

这个功能换作别的语言也许不难,但是通过php实现的话,那就比较麻烦了。通常的话,我们可以搭配linux下的cron来实现,比如我们可以在凌晨到6:00之间做一个定时任务,每半个小时扫描一次php脚本,如果发现银行那边的状态依旧为失败的话,我们就执行一次php脚本去请求数据。直到请求到正确的数据,然后把状态更新为成功。

这不失为一种方法,但太傻了。比如说银行那边比较正常,凌晨,也就是第一次请求的时候,就已经返回了正确的数据,那么我们的cron脚本还傻傻的每个半个小时执行一次,好蠢!~

或者我们可以尝试使用linux下的at命令,但感觉还是不够优雅。

解决问题

于是决定给laravel扩展一个swoole插件来解决此问题,swoole的定时任务很完美的解决了我们目前的问题。

首先我们需要把swoole扩展安装好,具体过程略。
装好以后,我们写一个swoole简易的服务端测试脚本,注意,此脚本是放在app/Console/Commands/下的,笔者是放在了app/Console/Commands/Swoole/swoole.php下,具体代码为

<?php

namespace App\Console\Commands\Swoole;

use Illuminate\Console\Command;

class swoole extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'swoole {action}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = "Let's use swoole !";

    private $serv;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $arg = $this->argument('action');
        switch ($arg) {
            case 'start':
                $this->info('swoole server started');
                $this->start();
                break;
            case 'stop':
                $this->info('stoped');
                $this->stop();
                break;
            case 'restart':
                $this->info('restarted');
                break;
        }
    }

    private function start()
    {
        $this->serv = new \swoole_server("127.0.0.1", 9501);
        $this->serv->set(array(
            'worker_num' => 8,
            'daemonize' => false,
            'max_request' => 10000,
            'dispatch_mode' => 2,
            'task_worker_num' => 8,
            'task_ipc_mode' => 3,
            'log_file' => storage_path('logs/taskqueue.log'),
        ));

        $this->serv->on('Receive', array($this, 'onReceive'));
        $this->serv->on('Task', array($this, 'onTask'));
        $this->serv->on('Finish', array($this, 'onFinish'));
        $this->serv->start();

    }

    public function onReceive(\swoole_server $serv, $fd, $from_id, $data)
    {
        $serv->task($data);
    }

    public function onTask($serv, $task_id, $from_id, $data)
    {
        $timeon = (3) * 1000;
        if ($timeon > 0) {
            $serv->after($timeon, function () {
                //业务逻辑处
                exec('php /path/to/root/artisan Test:Command');
            });
        }
        return date('Y-m-d H:i:s') . "第一次执行";
    }

    public function onFinish($serv, $task_id, $data)
    {

        echo "Task finish\n";
    }

    private function stop()
    {
        exec('/usr/bin/killall php');
    }

}

 

 

这是服务端,我们主要用到了after方法,模拟的话,是三秒一执行。实际应该是三十分钟

然后我们随便写一个客户端连接类

<?php
/**
 * Created by PhpStorm.
 * User: nosay
 * Date: 4/13/18
 * Time: 9:27 PM
 */

namespace App\Extension\php\Swoole;


class swoole{

    private $data;
    private $client;

    public function __construct($data){
        $this->data = $data;
        $this->client = new \swoole_client(SWOOLE_SOCK_TCP);
    }

    public function connect(){


        if( !$this->client->connect("127.0.0.1", 9501 , 1) ) {
            echo "Error";
        }


        $this->client->send($this->data);
    }



}

于是我们在银行脚本中就可以去执行了

<?php

namespace App\Console\Commands\Test;

use App\Extension\php\Swoole\swoole;
use Illuminate\Console\Command;

class TestCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'Test:Command';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command Test';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //这里是业务逻辑
        //如果银行那边返回的为false的话,那么我们把他交给swoole的定时脚本
        $status = false;

        if(!$status)
        {
            $swoole = new swoole("hehe");
            $swoole->connect();
        }



    }
}

https://mp.weixin.qq.com/s/e_ophgURO6qRvfKd3YDJXQ

 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/112700.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 公网IP、私网IP、动态IP、静态IP

    公网IP、私网IP、动态IP、静态IPIP地址这个词我们经常听到,它具体是个什么东西这里就不谈了,建议去看一下本系列文章的《IP地址和MAC地址简介》一文。本文主要来区分一下公网IP、私网IP、动态IP、静态IP这四个概念。先说公网IP和私网IP。我们都听过IP地址,但对公网IP和私网IP可能就比较挠头了。把IP的问题放在一边,我们先说一下什么是公网,什么是私网。公网又名广域网、外网,指的就是我们平时说的互联网。私网又名内网、局域网,指的是路由器或交换机下创建的局部互联网络。网络的功能说的简单些就是使多台计算机实现互联,可以互相传输数据。广

    2022年6月7日
    28
  • SWD应用接口

    SWD应用接口随着ARM公司对Cortex系列的推出,采样SWD方式调试成了大家的首选。SWD不仅速度可以与JTAG媲美,而且使用的调试线少得多。很多人在采样SWD方式进行调试时,一般都是采用4线:①VCC     –    电源②GND    –   地线③SWDIO-   数据④SWCLK-  时钟       在对NXP的LPC111

    2022年4月25日
    58
  • 移位寄存器专题(verilog HDL设计)

    移位寄存器专题(verilog HDL设计)目录移位寄存器简介分类4位右移位寄存器工作原理1、16位右移位寄存器2、16位左移寄存器3、串行输入并行输出寄存器4、并行输入串行输出移位寄存器移位寄存器简介移位寄存器内的数据可以在移位脉冲(时钟信号)的作用下依次左移或右移。移位寄存器不仅可以存储数据,还可以用来实现数据的串并转换、分频,构成序列码发生器、序列码检测器,进行数值运算以及数据处理等,它也…

    2022年7月16日
    12
  • SpringMVC 查询参数接收时间戳转Date方法[通俗易懂]

    SpringMVC 查询参数接收时间戳转Date方法[通俗易懂]Springmvc通过@RequestParam接收参数指定类型为Date时,接口传入时间戳会默认为string类型,无法转为Date,可在controller中添加如上转换器。@InitBinderpublicvoidinitBinder(finalWebDataBinderwebdataBinder){webdataBinder.reg…

    2022年6月18日
    31
  • java %08d_总结Java中String.format()的使用[通俗易懂]

    java %08d_总结Java中String.format()的使用[通俗易懂]快速入门介绍Java中强大的String.format()前言从Java5.0开始,String类新增了一个强大的字符串格式化方法format()。这个方法到现在用的人还是不多,实在是一种浪费。本文带你快速过一遍这个方法的功能,将来你要用到格式化文本的时候,可能就不需要再借用第三方类库或自己去实现了。首先看一个简单例子:Stringformatted=String.format(“…

    2022年7月8日
    26
  • 西门子scl语言编程教程_西门子scl编程

    西门子scl语言编程教程_西门子scl编程《在西门子PLC中使用SCL语言编程的技巧》由会员分享,可在线阅读,更多相关《在西门子PLC中使用SCL语言编程的技巧(6页珍藏版)》请在人人文库网上搜索。1、在西门子PLC中使用SCL语言编程的技巧前言:两年半前我就在工控网上发表了有关SCL编程的知识#lt;#lt;在S型PLC中使用高级语言编程#gt;#gt;,但发表完后,即使我自己都从没有把任何使用SCL编写的程序用到实际控制中,当时的感觉…

    2022年10月7日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号