gearman php并行任务对错误请求的响应

gearman php并行任务对错误请求的响应,php,multithreading,parallel-processing,gearman,Php,Multithreading,Parallel Processing,Gearman,我目前正在测试gearman处理来自web前端的并行任务/请求,gearman cleint通过Ajax接收带有post参数的请求,然后创建任务并将它们发送给gearman worker。工作进程的21个实例正在运行,以同时处理来自不同客户端的多个请求。一次处理一个客户机请求时,一切都正常,但是当多个客户机同时请求时,客户机将得到错误的信息结果。 例如,如果客户机A请求客户机id 123的信息,客户机B请求客户机id 456的信息,并且这两个请求同时被触发,客户机A将得到客户机B的结果,客户机B

我目前正在测试gearman处理来自web前端的并行任务/请求,gearman cleint通过Ajax接收带有post参数的请求,然后创建任务并将它们发送给gearman worker。工作进程的21个实例正在运行,以同时处理来自不同客户端的多个请求。一次处理一个客户机请求时,一切都正常,但是当多个客户机同时请求时,客户机将得到错误的信息结果。 例如,如果客户机A请求客户机id 123的信息,客户机B请求客户机id 456的信息,并且这两个请求同时被触发,客户机A将得到客户机B的结果,客户机B将得到客户机A的结果。我试图将不同工作人员的功能分开,但存在相同的问题。请帮助我查找代码中的问题

我使用的是curlmulti,没有问题(),但最近决定尝试测试gearman,看看是否可以获得更高的性能

以下是我的客户和员工代码:

客户端代码:

<?php

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");    // Date in the past
header("Cache-Control: no-store, no-cache, must-revalidate");  // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");


$order_id   = $_POST['order_id'];
$customer_id    = $_POST['customer_id'];

//some validation code here


class DataCollector extends GearmanClient{
    private $data     = array();
    private $tmpArr   = array();

    function addData($content){
        if($content){
            $this->tmpArr   = json_decode($content, true);
            $this->data     = array_merge($this->tmpArr, $this->data);
            //$this->data[] = json_decode($content, true);
        }
    }
    function getData(){
        return $this->data;
    }
    function outputData(){
        echo json_encode($this->getData());
    }

    function taskCompleted($task){

       $this->addData($task->data());

    }

}


$collector = new DataCollector();

$collector->addServer();

# set a function to be called when the work is complete
$collector->setCompleteCallback(array( $collector, "taskCompleted"));


//params to pass to worker
$queryStr = array(
      "order_id" => $order_id,
      "customer_id" => $customer_id
);

$postData = serialize( $queryStr );

# add tasks to be executed in parallel in Gearman server
$collector->addTask("getdata_orderDetails", $postData, null, "1");
$collector->addTask("getdata_customerDetails", $postData, null, "2");

# run the tasks in parallel
$collector->runTasks();


# output the data 
$collector->outputData();

?>

工人代码:

<?php

class Worker{
    private $worker;
    static $conn;

public function __construct(){

    try{
        self::$conn = oci_connect($user, $pass, $db); // create db connection
    }
    catch (Exception $e) {
        echo "ERROR: " . $e->getMessage();
    }

    $this->worker = new GearmanWorker();
    $this->worker->addServer();

    # Register functions
    $this->worker->addFunction("getdata_orderDetails",    array($this, "getdata_orderDetails_fn"));
    $this->worker->addFunction("getdata_customerDetails", array($this, "getdata_customerDetails_fn"));
}

public function run(){

    while (1) {
      //print "Waiting for job...\n";
      $this->worker->work(); 
      if ($this->worker->returnCode() != GEARMAN_SUCCESS) {
        echo "return_code: " . $this->worker->returnCode() . "\n";
        break;
      }
    }



}


static function getdata_orderDetails_fn($job){


        if(!self::$conn){
        $responseArr = array(
            'response_status'           => -1,         //failed
            'response_message'          => 'Database connection lost',
            'response_id'               => 'DatabaseConnectionErr'
            );

        return  json_encode($responseArr);
        }

    $postData = unserialize($job->workload());

    $order_id   = $postData['order_id'];
    $customer_id    = $postData['customer_id'];

    $sql = "select order_id, order_status, create_date from customer_order where order_id= :order_id";
    $stmt = oci_parse(self::$conn, $sql);
    oci_bind_by_name($stmt, ":order_id", $order_id, -1);
    oci_execute($stmt);
    oci_fetch($stmt);
    $order_id   = oci_result($stmt, 'ORDER_ID');
    $order_status   = oci_result($stmt, 'ORDER_STATUS');
    $create_date    = oci_result($stmt, 'CREATE_DATE');
    oci_free_statement($stmt);


    $responseArr = array(
        'response_status'   => 1,  
        'response_message'  => 'success',
        'response_id'       => 'order_details',
        'order_id'          => $order_id,
        'order_status'      => $order_status,
        'create_date'           => $create_date
    );

    // send result
    return  json_encode($responseArr);
}

static function getdata_customerDetails_fn($job){


        if(!self::$conn){
        $responseArr = array(
            'response_status'   => -1,         //failed
            'response_message'  => 'Database connection lost',
            'response_id'       => 'DatabaseConnectionErr'
            );

        return  json_encode($responseArr);
        }

    $postData = unserialize($job->workload());

    $order_id   = $postData['order_id'];
    $customer_id    = $postData['customer_id'];

    $sql = "select customer_id, customer_fname, customer_lname, customer_address, customer_contact where customer_id= :customer_id";
    $stmt = oci_parse(self::$conn, $sql);
    oci_bind_by_name($stmt, ":customer_id", $customer_id, -1);
    oci_execute($stmt);
    oci_fetch($stmt);
    $customer_id        = oci_result($stmt, 'CUSTOMER_ID');
    $customer_fname     = oci_result($stmt, 'CUSTOMER_FNAME');
    $customer_lname     = oci_result($stmt, 'CUSTOMER_LNAME');
    $customer_address   = oci_result($stmt, 'CUSTOMER_ADDRESS');
    $customer_contact   = oci_result($stmt, 'CUSTOMER_CONTACT');
    oci_free_statement($stmt);

    $responseArr = array(
        'response_id'       => 'customer_details',
        'response_status'   => 1,  
        'response_message'  => 'success',
        'customer_id'       => $customer_id,
        'customer_fname'    => $customer_fname,
        'customer_lname'    => $customer_lname,
        'customer_address'  => $customer_address,
        'customer_contact'  => $customer_contact
    );

    // send result
    return  json_encode($responseArr);

}

}//class


 //start worker
  $worker = new Worker();
  $worker->run();


?>

我认为问题在于您的任务ID不是唯一的。尝试为每个任务分配唯一的ID,或根本不指定任务ID:

$collector->addTask("getdata_orderDetails", $postData);
$collector->addTask("getdata_customerDetails", $postData);

# run the tasks in parallel
$collector->runTasks();

在得到gearman group的帮助后,我解决了这个问题:

我的案例的解决方案是基于$postData使每个任务都是唯一的。 这样,如果两个或多个客户端请求相同的信息(例如订单id或客户id),gearman将使用相同的唯一任务id对并发请求进行排队,并将以相同的结果答复所有客户端(即仅处理一个请求):


谢谢,你是赖特。我在这里得到了相同的答案:您的答案也是正确的,但对于我的案例场景,最好基于$postData生成任务唯一id,请参见下面我的答案。
$collector->addTask("getdata_orderDetails", $postData, null, md5($order_id);
$collector->addTask("getdata_customerDetails", $postData, null, md5($customer_id);