php 使用fsockopen 发送http请求
需求背景
在公司开发这么一个需求,每天三次定时催付待客服催付状态的订单,设定每天15、16、17点三次执行job任务来给一批订单打电话催付,需要三个时间点都把待客服催付的订单拨打一遍电话,根据数据组统计,大概每天需要催付的订单数量在6000左右,对接第三方电话呼叫业务,拿到订单信息来呼叫。
测试状态
拿500个订单手动执行第一波测试,发现500个订单催付完毕需要30多分钟,那么6000个订单按照需求催付时间点是完全不够的,半小时500个,一小时最多1000个。
初步排查,是由于使用php curl请求导致每一次遍历的请求时间慢,由于curl请求最短的time时间耗时是1秒,那么一小时3600秒也是不够呼完这6000单。
解决方案
一、在遍历循环的时候把每次请求的量丢入消费系统(队列),然后根据开启多个消费者来消费这些(上线迫在眉睫,来不及)
二、有没有类似curl更快的方案,发现了fsockopen,按照使用方法配置完500个订单,遍历完成只需要18秒。
需求代码
/**
* 通过订单信息组装呼叫信息
* @param array $order
* @return array
*/
private function getCallInfoByOrder ($order = [])
{
$order_ext = OrderExt::model()->getPrimary($order['order_id']);
$point = (isset($order_ext['app_ver'])&&version_compare($order_ext['app_ver'],Tools::PRICE_COMPARE_VERSION,">="));
$pay_detail = json_decode($order['pay_detail'], true);
$call_text = OrderPayRemainService::organizeHeLiText($order['create_time'], $pay_detail['cash'], $point);
return ['phone' => $order['phone'], 'call_text' => $call_text];
} //开始呼叫
private function toCall ($call_info)
{
$params = $this->formatGetParams($call_info);
EdjLog::info(__METHOD__ .'he li to call info' . json_encode($call_info));
$this->doCurlGetRequest(self::CALL_API_URL, $params, $call_info);
} //拨号请求
private function doCurlGetRequest($url, $data = [], $call_info = []){
if($url == "" || empty($data)){
return false;
}
$response = $this->fsockopen_request($url,$data); // $response_arr = explode("\r\n", $response);
//
// if (in_array(self::TOOKEN_INVALID,$response_arr)) {
// EdjLog::info(__METHOD__ .'he li accessToken expire' . json_encode($call_info));
// $this->redis->del(self::ACCESS_TONEN_CACHE_KEY);
// $this->toCall($call_info);
// } $response_arr = explode("\r\n", $response); return true;
}
private function fsockopen_request($URL,$data, $referrer="") {
EdjLog::info(__METHOD__ .'he li request url:' . $URL.'-data:'.json_encode($data));
$URL_Info = parse_url($URL);
foreach($data as $key=>$value)
$values[] = "$key=" . urlencode($value);
$data_string = implode("&",$values);
if(!isset($URL_Info["port"]))
$URL_Info["port"] = 80;
$request = '';
$request.="POST ".$URL_Info["path"]." HTTP/1.1\n";
$request.="Host: ".$URL_Info["host"]."\n";
$request.="Referer: $referrer\n";
$request.="Content-type: application/x-www-form-urlencoded\n";
$request.="Content-length: ".strlen($data_string)."\n";
$request.="Connection: close\n";
$request.="\n";
$request.=$data_string."\n";
$fp = fsockopen($URL_Info["host"],$URL_Info["port"],$errno, $errstr);
if (!$fp) {
EdjLog::info('socket_open error:'.json_encode($data). "Error: $errstr ($errno)");
} else {
stream_set_blocking($fp, true);//开启了非阻塞模式
fputs($fp, $request);
fclose($fp);
usleep(400000); //等待500ms
EdjLog::info('socket_open success:'.json_encode($data));
}
// $result = '';
// while(!feof($fp)) {
//
// $response = fgets($fp, 512);
// if (!is_numeric(trim($response))) {
// continue;
// }
// $result.= $response;
// }
// return $result;
}
完整说明
<?php
$srv_ip = '192.168.1.5';//你的目标服务地址.
$srv_port = ;//端口
$url = 'http://localhost/fsock.php'; //接收你post的URL具体地址
$fp = '';
$errno = ;//错误处理
$errstr = '';//错误处理
$timeout = ;//多久没有连上就中断
$post_str = "username=demo&password=hahaha";//要提交的内容.
//打开网络的 Socket 链接。
$fp = fsockopen($srv_ip,$srv_port,$errno,$errstr,$timeout);
if (!$fp){
echo('fp fail');
}
$content_length = strlen($post_str);
$post_header = "POST $url HTTP/1.1\r\n";
$post_header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$post_header .= "User-Agent: MSIE\r\n";
$post_header .= "Host: ".$srv_ip."\r\n";
$post_header .= "Content-Length: ".$content_length."\r\n";
$post_header .= "Connection: close\r\n\r\n";
$post_header .= $post_str."\r\n\r\n";
fwrite($fp,$post_header); $inheader = ;
while(!feof($fp)){//测试文件指针是否到了文件结束的位置
$line = fgets($fp,);
//去掉请求包的头信息
if ($inheader && ($line == "\n" || $line == "\r\n")) {
$inheader = ;
}
if ($inheader == ) {
echo $line;
}
}
fclose($fp);
unset ($line);
?>
其它博文
https://blog.csdn.net/navioo/article/details/82771663
php 使用fsockopen 发送http请求的更多相关文章
- Php 使用 fsockopen发送http请求
<?php function HTTP_Post($URL,$data, $referrer="") { // parsing the given URL $URL_Info ...
- php中使用fsockopen实现异步请求
php执行一段程序,有可能几毫秒就执行完毕,也有可能耗时较长.例如,用户下单这个事件,如果调用了些第三方服务进行发邮件.短信.推送等通知,可能导致前端一直在等待.而有的时候,我们并不关心这些耗时脚本的 ...
- 【荐】怎么用PHP发送HTTP请求(POST请求、GET请求)?
file_get_contents版本: <?php /** * 发送post请求 * @param string $url 请求地址 * @param array $post_data pos ...
- php发送http请求方法实例及详解
http请求有get,post. php发送http请求有三种方式[我所知道的有三种,有其他的告诉我]. file_get_contents();详情见:http://www.whosmall.com ...
- PHP模拟发送POST请求之四、加强file_get_contents()发送POST请求
使用了笨重fsockopen()方法后,我们开始在PHP函数库里寻找更简单的方式来进行POST请求,这时,我们发现了PHP的文件函数也具有与远程URL交互的功能. 最简单的是fopen()和fread ...
- HTTP 笔记与总结(3 )socket 编程:发送 GET 请求
使用 PHP + socket 模拟发送 HTTP GET 请求,过程是: ① 打开连接 ② 构造 GET 请求的数据:写入请求行.请求头信息.请求主体信息(GET 请求没有主体信息) ③ 发送 GE ...
- 怎么用PHP发送HTTP请求(转载)
本文转自:http://blog.snsgou.com/blog/161.html file_get_contents版本: /** * 发送post请求 * @param string $url ...
- socket编程发送GET请求
可以根据几根url地址,分析出主机,地址,协议等,然后用封装成的类拼接成GET请求信息,用fsockopen连接主机,进行读取操作,获取响应信息,打印 <?php //http连接接口 inte ...
- php发送http请求
http请求有get,post. php发送http请求有三种方式[我所知道的有三种,有其他的告诉我]. file_get_contents();详情见:http://www.cnblogs.com/ ...
随机推荐
- E203 itcm
E203 itcm是64Kb,所以地址总线为16位,2^16=64Kb, 数据线宽度为64 bits(8 bytes),所以address width是16-3=13bit,ram depth 是2^ ...
- Dynamics CRM 客户端程序开发:自定义系统标准按钮的可用性
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复125或者20140414可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 一般是新建一个解决方案用于客制化 ...
- element-ui修改表单自带验证的样式
1.比如重写在表单自带验证的样式 .el-form-item__error是对应是的文字的类名,图标我是通过伪元素插进去的 下面是伪元素代码 基本上要重写样式的,到控制台看样式名,因为是封装的,所以有 ...
- 查看UNDO 表空间使用情况
Select Sum(bytes / (1024 * 1024)), a.status From dba_undo_extents a Group By a.status Select fi ...
- javascript 生成指定范围内的随机数
js 生成任意2个区间内的随机整数,js 生成两个数之间的随机数 function random(m,n) { return Math.floor(Math.random() * (n - m)) + ...
- nginx 图片访问404 (使用location中使用 root,alias的区别)
问题描述: 在/data/code_img/文件下有很多验证码图片,想将他们展示出来 希望通过 http://127.0.0.1/img/1.png 这种形式访问到对应图片,刚开始nginx中配置如下 ...
- 【转】带栗子的GDB教程
带栗子的GDB教程 原文链接:http://www.cprogramming.com/gdb.html作者:Manasij Mukherjee 一个好的调试软件是一个程序猿的工具箱里最重要的工具之一, ...
- 执行DOS命令并返回结果
public static String excuteCommand(String command){ Runtime runtime = Runtime.getRuntime(); try { Pr ...
- 201871010111-刘佳华《面向对象程序设计(java)》第6-7周学习总结
201871010111-刘佳华<面向对象程序设计(java)>第6-7周学习总结 实验六 继承定义与使用 实验时间 2019-9-29 第一部分:理论部分. 1.继承:已有类来构建新类的 ...
- 2019年最新50道java基础部分面试题
[软帝学院]1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法. 1.一个".j ...