zoukankan      html  css  js  c++  java
  • gearman任务分发改进

    基于我上次在这里发现的问题,就是一次性投递20个消息,用sleep等待后发现,最后一个任务需要等前面19个都跑完才能执行,所以这里做一下改进。

    client.php

    <?php
    $client = new GearmanClient();
    $client->addServer('127.0.0.1', 4730);
    for ($i=0; $i < 20; $i++) {
      $ret[$i] = $client->doBackground('runLaterJob', json_encode(array(
        'uid' => 'test user id '.$i,
        'title' => '添加一个需要延时处异步执行的代码标题',
        'body' => '执行这个异步的具体内容',
        'run_time' => time() + 2,
      )));
    }

    worker.php

    <?php
    
    $worker = new GearmanWorker();
    $worker->addServer('127.0.0.1', 4730);
    $worker->addFunction('runLaterJob', function($job) {
      $data = json_decode($job->workload(), true);
      if (isset($data['run_time']) && $data['run_time'] > time()) {
        // 如果需要延时还没到时间就下次再处理
        add_work($data);
      }
      else {
        echo "处理任务 uid:{$data['uid']}--title:{$data['title']}--body:{$data['body']} 成功
    ";
      }
    });
    while($worker->work());
    
    function add_work($data = []) {
      $client = get_client();
      $client->doBackground('runLaterJob', json_encode($data));
    }
    
    function get_client() {
      static $client = NULL;
      if (!$client) {
        $client = new GearmanClient();
        $client->addServer('127.0.0.1', 4730);
      }
      return $client;
    }

    核心思路是,加入任务的时候就计算好自己什么时候执行,然后在执行任务这里不断的判断是不是到时间了 到时间就执行,否则就再次加入任务,这样就能避免最后一个任务被sleep给阻塞住了。虽然这里一直加入任务感觉会很傻瓜,不过可以稍微做个改进,用usleep(1000)这样每毫秒去跑一次,这样就既能控制在毫秒级别,又能减轻循环压力。

    说干就干,接下来是改进的代码。

    client.php

    <?php
    $client = new GearmanClient();
    $client->addServer('127.0.0.1', 4730);
    $sleep_time = [2, 0.001, 0.005, 0.8, 0.007, 0.5, 1, 5, 0.1, 2, 2.03, 1.24, 0.12, 3.08, 4.77, 1.42, 2.69, 3.49, 0.29, 1.99];
    for ($i=0; $i < 20; $i++) {
      $ret[$i] = $client->doBackground('runLaterJob', json_encode(array(
        'uid' => 'test user id '.$i,
        'title' => '添加一个需要延时处异步执行的代码标题',
        'body' => '执行这个异步的具体内容',
        'run_time' => microtime(true) + $sleep_time[$i],
      )));
    }

    worker.php

    <?php
    
    $worker = new GearmanWorker();
    $worker->addServer('127.0.0.1', 4730);
    $worker->addFunction('runLaterJob', function($job) {
      $data = json_decode($job->workload(), true);
      if (isset($data['run_time']) && $data['run_time'] > microtime(true)) {
        // 如果需要延时还没到时间就下次再处理
        usleep(1000);
        add_work($data);
      }
      else {
        echo "处理任务 uid:{$data['uid']}--title:{$data['title']}--body:{$data['body']} 成功
    ";
      }
    });
    while($worker->work());
    
    function add_work($data = []) {
      $client = get_client();
      $client->doBackground('runLaterJob', json_encode($data));
    }
    
    function get_client() {
      static $client = NULL;
      if (!$client) {
        $client = new GearmanClient();
        $client->addServer('127.0.0.1', 4730);
      }
      return $client;
    }

    运行php worker.php

    然后新开一个终端运行php client.php

    控制台打印结果为

    处理任务 uid:test user id 1--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 2--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 4--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 8--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 12--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 18--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 5--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 3--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 6--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 11--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 15--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 19--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 0--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 9--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 10--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 16--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 13--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 17--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 14--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功
    处理任务 uid:test user id 7--title:添加一个需要延时处异步执行的代码标题--body:执行这个异步的具体内容 成功

    可以看到确实是按照时间距离排序的,第0个元素排后面去了,第1个元素排最前面来了,因为它只需要0.001秒就要执行

  • 相关阅读:
    ORM框架
    js获取浏览器和元素对象的尺寸
    js中的兼容问题
    JS页面上的流氓广告功能
    JS计算1到10的每一个数字的阶乘之和
    JS中 有一个棋盘,有64个方格,在第一个方格里面放1粒芝麻重量是0.00001kg,第二个里面放2粒,第三个里面放4,棋盘上放的所有芝麻的重量
    JS中99乘法表
    JS 中计算 1
    JS中判断一个数是否为质数
    JS水仙花数
  • 原文地址:https://www.cnblogs.com/lizhaoyao/p/15497350.html
Copyright © 2011-2022 走看看