duancong2160 2016-11-30 09:24
浏览 80

PHP + Apache2 + Ubuntu Server:如何让所有线程并行工作?

I usually work with web hosting companies but I decided to start learning working with servers to expand my knowledge.

I'll better give a real example to explain my question the best:

I have a web application that gathers data from a slow API that returns JSON data of products. I have a function running every 1AM running a lot of queries on "id"s in my database.

Crontab:

0 1 * * * cd /var/www/html/tools; php index.php aso Cli_kas kas_alert

So this creates a process for the app (please correct me here if I'm wrong) and each process creates threads, and just to be more accurate, they are multi-threads since they do more than one thing: like pulling data from the DB to get the right variables and string them to the API queries, getting the data from the API, organizing it, searching the relevant data, and then inserting new data to the database.

The main PHP functions:

// MAIN: Cron Job Function
public function kas_alert() {


    // 0. Deletes all the saved data from the `data` table 1 month+ ago. 
    // $this->kas_model->clean_old_rows();

    // 1. Get 'prod' table
    $data['table'] = $this->kas_model->prod_table();


    // 2. Go through each row -
    foreach ( $data['table'] as $row ) {

        // 2.2. Gets all vars from the first query.
        $last_row_query = $this->kas_model->get_last_row_of_tag($row->tag_id);
        $last_row       = $last_row_query[0];
        $l_aaa_id       = $last_row->prod_aaa_id;
        $l_and_id       = $last_row->prod_bbb_id;
        $l_r_aaa        = $last_row->dat_data1_aaa;
        $l_r_and        = $last_row->dat_data1_bbb;
        $l_t_aaa        = $last_row->dat_data2_aaa;
        $l_t_and        = $last_row->dat_data2_bbb;
        $tagword        = $last_row->tag_word;
        $tag_id         = $last_row->tag_id;
        $country        = $last_row->kay_country;
        $email          = $last_row->u_email;
        $prod_name      = $last_row->prod_name;
        // For the Weekly report:
        $prod_id        = $last_row->prod_id;
        $today          = date('Y-m-d');

        // 2.3. Run the tagword query again for today on each one of the tags and insert to DB. 
        if ( ($l_aaa_id != 0) || ( !empty($l_aaa_id) ) ) {
            $aaa_data_today   = $this->get_data1_aaa_by_id_and_kw($l_aaa_id, $tagword, $country);
        } else{
            $aaa_data_today['data1']       = 0;
            $aaa_data_today['data2']      = 0;
            $aaa_data_today['data3'] = 0;
        }

        if ( ($l_and_id != 0) || ( !empty($l_and_id) ) ) {
            $bbb_data_today = $this->get_data1_bbb_by_id_and_kw($l_and_id, $tagword, $country);
        } else {
            $bbb_data_today['data1']      = 0;
            $bbb_data_today['data2']    = 0;
            $bbb_data_today['data3'] = 0;
        } 

        // 2.4. Insert the new variables to the "data" table. 
        if ($this->kas_model->insert_new_tag_to_db( $tag_id, $aaa_data_today['data1'], $bbb_data_today['data1'], $aaa_data_today['data2'], $bbb_data_today['data2'], $aaa_data_today['data3'], $bbb_data_today['data3']) ){
        }


        // Kas Alert Outputs ($SEND is echoed in it's original function)
        echo "<h1>prod Name: $prod_id</h1>";
        echo "<h2>tag id: $tag_id</h2>";
        var_dump($aaa_data_today);
        echo "aaa old: ";
        echo $l_r_aaa;
        echo "<br> aaa new: ";
        echo $aaa_data_today['data1']; 

        var_dump($bbb_data_today);
        echo "<br> bbb old: ";
        echo $l_r_and;
        echo "<br> bbb new: ";
        echo $bbb_data_today['data1'];

        // 2.5. Check if there is a need to send something
        $send = $this->check_if_send($l_aaa_id, $l_and_id, $l_r_aaa, $aaa_data_today['data1'], $l_r_and, $bbb_data_today['data1']);

        // 2.6. If there is a trigger, send the email!
        if ($send) {
            $this->send_mail($l_aaa_id, $l_and_id, $aaa_data_today['data1'], $bbb_data_today['data1'], $l_r_aaa, $l_r_and, $tagword, $email, $prod_name);
        }

    }


}

For @Raptor, this is the function that get's the API data:

// aaa tag Query
// Gets aaa prod dataing by ID. 
public function get_data_aaa_by_id_and_tg($id, $tag, $query_country){

    $tag_for_url = rawurlencode($tag);

    $found = FALSE; 
    $i     = 0;
    $data  = array();       

    // Create a stream for Json. That's how the code knows what to expect to get. 
    $context_opts = array(
        'http' => array(
        'method' => "GET",
        'header' => "Accepts: application/json
"
    ));
    $context = stream_context_create($context_opts); 

    while ($found == FALSE) {

        // aaa Query
        $json_query_aaa = "https://api.example.com:443/aaa/ajax/research_tag?app_id=$id&term=$tag_for_url&page_index=$i&country=$query_country&auth_token=666";
        // Get the Json
        $json_query_aaa = file_get_contents($json_query_aaa, false, $context); 
        // Turn Json to a PHP array
        $json_query_aaa = json_decode($json_query_aaa, true);
        // Get the data2
        $data2      = $json_query_aaa['tag']['data2'];
        if (is_null($data2)){ $data2 = 0; }
        // Get data3
        $data3  = $json_query_aaa['tag']['phone_prod']['data3'];
        if (is_null($data3)){ $data3 = 0; }
        // Finally, the main prod array. 
        $json_query_aaa = $json_query_aaa['tag']['phone_prod']['app_list'];


        if ( count($json_query_aaa) > 2 ) {

            for ( $j=0; $j<count($json_query_aaa); $j++ ) {

                if ( $json_query_aaa[$j]['id'] == $id ) {
                    $found = TRUE;
                    $data  = $json_query_aaa[$j]['data'] + 1;
                    break;
                }

                if ($found == TRUE){
                    break;
                }
            }

            $i++;

        } else {

            $data = 0; 
            break;

        }
    }

    $data['data1']  = $data;
    $data['data2']  = $data2;
    $data['data3']  = $data3;

    return $data;
}

All threads are stacked one after an other, and when one thread is done, only then - the second thread can proceed, ect'. And in technical view on this, all threads wait in the RAM until the one before them is done working "inside" the CPU. (correct me if I'm wrong again :] )

This doesn't even "tickle" the servers RAM or CPU when looking at it in the process manager (I use "htop"). RAM is at 400M/4.25G and CPU at ONLY 0.7%-1.3%. Making me feel this isn't the best I can get from my current server, and getting slow results from my web app.

How do I get things done in a way that all threads work in parallel, but not to a point that my app crashes due to lacks of CPU or RAM?

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 matlab中使用gurobi时报错
    • ¥15 WPF 大屏看板表格背景图片设置
    • ¥15 这个主板怎么能扩出一两个sata口
    • ¥15 不是,这到底错哪儿了😭
    • ¥15 2020长安杯与连接网探
    • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
    • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
    • ¥16 mybatis的代理对象无法通过@Autowired装填
    • ¥15 可见光定位matlab仿真
    • ¥15 arduino 四自由度机械臂