如何在php

时间:2017-02-16 10:43:40

标签: php multithreading codeigniter codeigniter-3 web-worker

我有一个问题: 我在codeigniter框架上有一个php的后端,我将从一个从外部C#应用程序发送的称重机器获取重量数据(不能修改该C#应用程序)。每次称重器更新值时我都会得到重量数据,所以例如它将从0,100,300,400,1000,1500,600,400,300,100开始,然后回到0(它会下降当产品不在规模时),所有这些值都会在一秒内生成一个条目,所以我会快速将它们放入,并使用此函数将其插入我的mysql数据库:

public function balance() {
    $evType = $this->input->post('eventType');
    $weight = $this->input->post('balanceWeight');

    if ($evType !== false && $weight !== false) {
        $evType = intval($evType);
        $weight = intval($weight);


        switch($this->balance_events->insert($evType, $weight)) {
            case OpResult::Ok;
                $this->_issue_success();
                    if($weight>100){
                    $insert_id = $this->db->insert_id();
                    $this->Curlsynologyapi->CURLsaveimage($insert_id);
                    }            
                break;
            case OpResult::InvalidParameters;
                $this->_issue_respond_with_reason("Not all parameters were supplied.", HttpResponse::BadRequest);
                break;
            case OpResult::Failed:
                $this->_issue_respond_with_reason("Internal server error occured while inserting the balance entry. Please try again ...", HttpResponse::InternalServerError);
                break;
            default:
                break;
        }
    }
}

因此,为了快速扩张,$ weight将保持权重值(忽略$ evType,即一些规模的平局)。并且随着新值的出现,这将必须快速保持和插入数据。现在我将有一个条件: if($ weight> 100)当为真时我转到另一个我将在上面列出的函数,它的作用是制作一个相机打印屏幕并保存该图像到我选择的文件夹上的服务器,并使用在mysql上插入的重量值id命名。在我的if语句为真之后,这就是我所说的:

public function CURLsaveimage($insert_id) {
   $datasidget = $this->curl->simple_get('blablabla this is my api login url');
   $datasid = json_decode($datasidget,true);
   $data_sid =  $datasid['data']['sid'];

   $reqUrl = "blabla this is my print screen from a live camera api url";
   $imageencode = $this->curl->simple_get($reqUrl);
   $path = "./images/$insert_id";
   write_file($path, $imageencode, $mode = 'wb');

}

从我的上一个函数执行api请求将需要30-40秒,这与我将获得的重量值(1个/秒)的速度相比要多得多。当if将触发并启动api请求时,我将错过所有权重数据,直到请求完成。事情就是我能够为每个刻度会话获得1个打印屏幕(这意味着当有人将某些东西放在秤上时,我需要在触发条件时做1个打印屏幕,然后等待下一个加权事件,称重机器不会生成不间断的数据,但是当它生成时我必须快速得到它。

我想的是要求api进程并行处理,以便重量事件的流程不会受到影响,当api请求完成后再次开始检查何时会变为真,所以on,我也想,如果我可以控制那个并行进程来使用它或其他东西。

我读了一些关于php工作者和线程的内容,我看到了redis,德语,heroku,但说实话,他们似乎有点难以理解,文档很薄,而且我认为它们太多了对于我的问题。

对于那些在php中没有先进性的人来说,问题是轻量级和平易近人吗?

非常感谢您的时间!

1 个答案:

答案 0 :(得分:1)

是的,您可以自己制作一个简单的任务队列。

每当您需要请求API时,您将创建一个任务,并将其存储在数据库中的某个自定义表中,其中只存储任务。因为我们只是将任务保存到数据库而不是在这里发出api请求,所以速度很快。

现在我们有一个队列(数据库中的一个表),要完成任务,所以现在我们需要一些php worker从队列中获取一个任务并执行它。

创建一个简单的php脚本,它将从数据库中获取一个任务(如"select * from tasks limit 1"),执行它,然后在完成后从数据库中删除此任务(或者它可以更改任务的状态)。

现在我们只有一个问题,谁将运行此脚本,何时?我们可以使用 cron 。例如,我们可以安排每分钟运行一次脚本。

例如,cron可以每分钟运行一次php脚本。

您的代码将如下所示:

       switch($this->balance_events->insert($evType, $weight)) {
            case OpResult::Ok;
                $this->_issue_success();
                    if($weight>100){
                        $insert_id = $this->db->insert_id();
                        $saveCameraImageTask = new SaveCameraImageTask($insert_id);
                        $saveCameraImageTask->save()//save it to database, we are just saving it to our database, no api request, so it is fast.
                    }            
                break;
            case OpResult::InvalidParameters;
                $this->_issue_respond_with_reason("Not all parameters were supplied.", HttpResponse::BadRequest);
                break;
            case OpResult::Failed:
                $this->_issue_respond_with_reason("Internal server error occured while inserting the balance entry. Please try again ...", HttpResponse::InternalServerError);
                break;
            default:
                break;
        }