PHP异步 fsockopen篇
程序员文章站
2024-01-28 11:26:16
...
项目中遇到发布一个信息后需要给关联用户推送模板消息,这个想都不用想肯定是要抛异步任务的
可是PHP不能异步,可怜我又不会其他语言,swoole我还没有用过,也来不及现在研究,而且还有装扩展的,实在是太麻烦
百度了下可以说是可以用fsockopen,在项目中已经实现了,今天来做下笔记
// 先看下网上找的例子
// 例1
<?php
/*利用php的系统调用,开启新的进程来实现。
php 提供了fsockopen函数,此函数的功能为初始化一个套接字连接到指定主机,默认情况下将以阻塞模式开启套接字连接。当然你可以通过stream_set_blocking()将它转换到非阻塞模式。这是关键。所以,思路就是:开启一个非阻塞的套接字连接到本机,本机收到之后作一些耗时处理。
类似这样的处理代码(文件posttest.php):*/
$fp = fsockopen($php_Path,80);
if (!$fp) {
LMLog::error("fsockopen:err" );
} else {
$out = "GET /album/action/album_write_friends_thread_record.php?key=&u= HTTP/1.1\r\n";
$out .= "Host: ".$php_Path."\r\n";
$out .= "Connection: Close\r\n\r\n";
stream_set_blocking($fp,true);
stream_set_timeout($fp,1);
fwrite($fp, $out);
usleep(1000);
fclose($fp);
}
/*这里,usleep(1000) 非常关键,它能保证这个请求能发出去。*/
?>
<?php
/*我们在来看处理的代码逻辑(文件album_write_friends_thread_record.php)*/
/**
* 客户端调用服务器接口页面
* user: guwen
*/
sleep(20);// 睡眠20s
?>
// 例2
<?php
$url = 'http://www.example.com/doRequest.php';
$param = array(
'name'=>'fdipzone',
'gender'=>'male',
'age'=>30
);
doRequest($url, $param);
function doRequest($url, $param=array()){
$urlinfo = parse_url($url);
$host = $urlinfo['host'];
$path = $urlinfo['path'];
$query = isset($param)? http_build_query($param) : '';
$port = 80;
$errno = 0;
$errstr = '';
$timeout = 10;
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
$out = "POST ".$path." HTTP/1.1\r\n";
$out .= "host:".$host."\r\n";
$out .= "content-length:".strlen($query)."\r\n";
$out .= "content-type:application/x-www-form-urlencoded\r\n";
$out .= "connection:close\r\n\r\n";
$out .= $query;
fputs($fp, $out);
fclose($fp);
}
//注意:当执行过程中,客户端连接断开或连接超时,都会有可能造成执行不完整,因此需要加上
ignore_user_abort(true); // 忽略客户端断开
set_time_limit(0); // 设置执行不超时
例子的原贴地址
例1 https://www.cnblogs.com/JDtech/p/6418438.html
例2 http://www.php.cn/php-weizijiaocheng-383499.html
下面是我在yii1的使用部分代码
<?php
/**
* 模板消息发送api
* User: lewiss
* Date: 2018/8/24
* Time: 17:12
*/
class TempController extends Api_pubController {
public function actionIndex() {
$limit = 50;
$get_last_id = !empty($_GET['last_id']) ? (int)$_GET['last_id'] : 0;
$list = Yii::app()->db->createCommand()
->select("user.id,user.wxopenid,member.m_name")
->from("{{school_member}} member")
->join("{{user}} user", "member.user_id=user.id")
->where("class_id=:class_id and member.type=3 and user.id>:last_id",
[":class_id" => (int)$_GET['class_id'], ':last_id' => $get_last_id])
->order("user.id")
->limit($limit)
->queryAll();
$data = [
"school_id" => $_GET['school_id'],
"class_id" => $_GET['class_id'],
"class_name" => $_GET['class_name'],
"teacher" => $_GET['teacher'],
"title" => $_GET['title'],
];
$school_id = Fun_filter::wwy_md5_set($_GET["school_id"]);
$last_id = 0;
foreach ($list as $value) {
$last_id = $value['id'];
$data['openid'] = $value['wxopenid'];
$data['m_name'] = $value['m_name'];
$data['url'] = "http://ktkids.cn/kt_edu/index.php?r=wap/default/class_trends&school_id={$school_id}&trend_id={$_GET['trend_id']}&trend_class_id={$_GET['class_id']}";
$this->fso("/kt_edu/index.php?r=temp/send", $data);
}
if ($last_id) {
$data['last_id'] = $last_id;
$data['trend_id'] = $_GET['trend_id'];
$this->fso('/kt_edu/index.php?r=temp', $data);
}
}
public function actionSend() {
$m_name = Yii::app()->request->getParam('m_name');
$class_name = Yii::app()->request->getParam('class_name');
$teacher = Yii::app()->request->getParam('teacher');
$title = Yii::app()->request->getParam('title');
$openid = Yii::app()->request->getParam('openid');
$school_id = Yii::app()->request->getParam('school_id');
$url = Yii::app()->request->getParam('url');
$template_id = "SsiA1yYA2q6yq7lJiREgravOFf0ySAeOKkLiXxd_bl4";
$data = array(
'1' => array('name' => 'first', 'value' => '您好,亲爱的' . $m_name . '家长', 'color' => '#173177'),
'2' => array('name' => 'keyword1', 'value' => $class_name, 'color' => '#173177'),
'3' => array('name' => 'keyword2', 'value' => $teacher, 'color' => '#173177'),
'4' => array('name' => 'keyword3', 'value' => date("Y年m月d日 H:i"), 'color' => '#173177'),
'5' => array('name' => 'keyword4', 'value' => $title, 'color' => '#173177'),
'6' => array('name' => 'remark', 'value' => '点击查看通知详情', 'color' => '#173177'),
);
$result = Fun_temp_kt::template($school_id, $template_id, $data, $openid, $url);
Yii::log("rsp----" . json_encode($result));
}
private function fso($uri, $data) {
$param = http_build_query($data);
$host = "xxxx.cn";
$fp = fsockopen($host, 80);
$out = "GET {$uri}&{$param} HTTP/1.1\r\n";
$out .= "Host: " . $host . "\r\n";
$out .= "Connection: Close\r\n\r\n";
stream_set_blocking($fp, true);
stream_set_timeout($fp, 1);
fwrite($fp, $out);
usleep(1000);
fclose($fp);
}
}
我在本地测试时候$host写127.0.0.1是没有问题,我想在服务器上写127.0.0.1也应该没有问题,因为都是请求的本机项目,不过好像失败了,不知道是不是nginx没有配置,后来改成了域名就ok了.
这里是以上代码实例的代码码云地址