pthreads(三)配合redis实现消息队列

* * * * * /usr/local/php/bin/php /data/www/hjserver/shell/order_list.php >> /order_list.log
* * * * * sleep 1; /usr/local/php/bin/php /data/www/hjserver/shell/order_list.php >> /order_list.log
* * * * * sleep 2; /usr/local/php/bin/php /data/www/hjserver/shell/order_list.php >> /order_list.log
~ sleep 59; ~
<?php
// 线程类
class myThread extends Thread {
    public $post; // 要推送的数据
    public $res; // 推送结果 boolen
    public $url;

    public function __construct($url, $post){
    	$this->url=$url;
        $this->post=$post;
    }

    public function run(){
    	$this->res=http_post($this->url, $this->post);
    }
}

// 发送http_post 请求
function http_post($url, $post) {
	$c = curl_init();
	
	// 
	$header[] = "Content-type: application/x-www-form-urlencoded;charset=UTF-8";
	curl_setopt($c, CURLOPT_HTTPHEADER, $header);
	
	curl_setopt($c, CURLOPT_TIMEOUT, 15);
	curl_setopt($c, CURLOPT_URL, $url);
	curl_setopt($c, CURLOPT_POST, true);
	curl_setopt($c, CURLOPT_POSTFIELDS, $post);
	curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
	$data = curl_exec($c);
	$info = curl_getinfo($c);
	curl_close($c);
	if ($data === false || $info['http_code'] != 200) {
		return false;
	}
	return $data;		
}

// post 数据格式化
function order_format($data){
	unset($data['notice_url']);
	unset($data['notice_times']);
	unset($data['notice_time']);
	
	return my_http_build_query($data); // urlencode
}

// 防止 http_build_query 自动urlencode
function my_http_build_query($data){
	$arr=[];
	foreach($data as $k => $v) {
		$arr[] = "$k=$v";
	}
	$str = implode('&', $arr);
	return $str;
}

// @param $times ; notice times already
function next_time($time, $times){
	switch ($times) {
		case '1':
			$time+=30; // 30s
			break;
		case '2':
			$time+=300; // 5 min
			//$time+=50; // test
			break;
		case '3':
			$time+=1800; // 30 min
			//$time+=80; // test 
			break;
		case '4':
			$time+=7200; // 2 h
			//$time+=100; // test
			break;
		case '5':
			$time+=43200; // 12 h
			break;
		case '6':
			$time+=86400; // 24 h
			break;
		
		default:
			# code...
			break;
	}
	return $time;
}

/////////////////////////////////////////// 业务逻辑 /////////////////////////////////////////////////

define('ORDER_LIST', 'order_list');
define('ORDER_TIMEOUT', 259200);

$current_timestamp = time();
$current_time = date('Y-m-d H:i:s', $current_timestamp);

// redis 持久连接
$redis=new redis();
$connect_redis=$redis->pconnect('*', 6379); //
if(!$connect_redis){
	exit($current_time." ERROR_CON_REDIS\n"); // log
}

// mysql 持久连接
try{
	$dbh = new PDO('mysql:host=*;dbname=*', '*', '*', array(
		PDO::ATTR_PERSISTENT => true
	));
}catch(PDOException $e){
	//echo 'Connection failed: ' . $e->getMessage();
	exit($current_time." ERROR_CON_MYSQL\n"); // log
}

// 队列长度
$len_list=$redis->lLen(ORDER_LIST);
if($len_list == 0){                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
	exit($current_time." NULL_L \n"); // log
}

// 队列报警
if($len_list > 1000){                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
	// Warning
}

// 初始化数组 // key 和order_list_arr一致
$order_list_arr=[];
$myThreads=[];
$post_data_arr=[];
$res=[];

// 限制并发数
$len_list=($len_list > 100) ? 100 : $len_list;

// 操作队列 左进右出
for($i=0;$i<$len_list;$i++){
    $v_json=$redis->rPop(ORDER_LIST);
    $v_arr=json_decode($v_json, true);

    if($current_timestamp >= $v_arr['notice_time']){
	    $order_list_arr[]=$v_arr;
	}else{
		$redis->lPush(ORDER_LIST, $v_json);
	}
}

if(empty($order_list_arr)){
	// contab
	exit($current_time." NULL_T \n"); // log
}

// 调起线程发起请求
foreach($order_list_arr as $key => $v_arr){
	$post_data=order_format($v_arr);
	$myThreads[$key]=new myThread($v_arr['notice_url'], $post_data);
	$myThreads[$key]->start();
	
	$post_data_arr[$key]=$post_data;
}

// 线程同步
foreach($myThreads as $key => $mythread){
	if($mythread->join()){
        $res[$key] = $mythread->res;
    }
}

// 通知结果 统一处理
foreach($res as $key => $v){
	$notice_times = $order_list_arr[$key]['notice_times'] + 1;
	
	$channel=$order_list_arr[$key]['HJChannel'];
	$app_id=$order_list_arr[$key]['HJAppId'];
	$order_id=$order_list_arr[$key]['HJOrderId'];

	$res_notice=0;
	$res_update='NULL'; // NULL 1 0
	$sql_update='NULL'; //

	$v_arr = json_decode($v, true);
	if($v_arr && isset($v_arr['retCode']) && $v_arr['retCode']==0){ // notice success
		$res_notice=1;
		$sql_update="UPDATE hj_order SET `status`=2, callbackSuccessTime='$current_time' WHERE orderId=". $order_id;
		$res_update_order = $dbh->exec($sql_update);

		if($res_update_order !== false){
			$res_update=1;
			// update cache
			$sql_query='SELECT * FROM hj_order WHERE orderId='.$order_id;
			$result=$dbh->query($sql_query);
			if($result){
				$order=$result->fetch(PDO::FETCH_ASSOC);
				$key_redis='order:'.$order_id;
				$order_json=json_encode($order);
				$redis->set($key_redis, $order_json);
				$redis->setTimeout($key_redis,  ORDER_TIMEOUT);
			}
			// del cache; hj update cache
// 			$key_redis='order:'.$order_id;
// 			$redis->del($key_redis);
		}else{
			$res_update=0;
		}
	}else{ // notice fail
		if($notice_times < 7){ // test 5 // 7
			// lPush
			$order=$order_list_arr[$key];
			$order['notice_times']=$notice_times;
			$order['notice_time']=next_time($order['notice_time'], $notice_times);
			$order_json=json_encode($order);
			$redis->lPush(ORDER_LIST, $order_json);
		}
	}

	//log
	$post_data_log=$post_data_arr[$key];
	$v_log=$v;
	
	// crontab
	echo "$current_time RUN $channel $app_id $order_id $notice_times $res_notice $res_update $v_log $post_data_log\n"; 

}


// END //




你可能感兴趣的:(redis,PHP,队列,pthreads)