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/ ...
随机推荐
- 裸奔的支付X聊天,你还敢用吗?
- 语音消息 使用HTTP明文传输,没有任何加密措施,使用域名为up-mayi.django.t.taobao.com,从报文中可以看出,语音消息是以文件形式在网络中传输的,下图为一次语音的发送传输过 ...
- 【jQuery】jQuery基础
jQuery介绍 jQuery是一个轻量级JS库,使用十分简单: jQuery的核心是选择器,用于获取页面元素: jQuery提供了大量高效的方法,开发速度大幅提升: jQuery选择器 jQuery ...
- Java学习笔记(4)--- 变量类型,修饰符
1.变量类型: a.定义: 和C++差不多,就是: type identifier [ = value][, identifier [= value] ...]: type为Java数据类型.iden ...
- js修改对象的key值
var array = [ { id:1, name:"小明" }, { id:2, name:"小红" } ]; /**/ //旧key到新key的映射 va ...
- luoguP4343自动刷题机(二分标准题)
https://www.luogu.org/problem/P4343 参考博客:https://www.luogu.org/blog/ofnoname/solution-p4343 这真是一语点醒梦 ...
- 【第1题】 Pythonn内存管理以及垃圾回收机制
内存管理 Python解释器由c语言开发完成,py中所有的操作最终都由底层的c语言来实现并完成,所以想要了解底层内存管理需要结合python源码来进行解释. 1. 两个重要的结构体 include/o ...
- InvalidProgramException
InvalidProgramException 这tmd是个什么错,我现在都想不起这个exception是怎么触发的了. 后来google了一下,发现是.net 2.0的编译器的bug,和内存或堆栈使 ...
- hdu 6495 dp
http://acm.hdu.edu.cn/showproblem.php?pid=6495 题意 有n个挑战(1e3),假如接受,在挑战之前体力x会变成min(x,\(b[i]\)),然后会减去a[ ...
- nuxtjs踩坑指南
1.nuxt引入问题:Can't resolve 'stylus-loader' 原因在于没有安装stylus,安装即可:npm install stylus stylus-loader --save ...
- Codeforces Round #596 (Div. 2, based on Technocup 2020 Elimination Round 2) D. Power Products 数学 暴力
D. Power Products You are given n positive integers a1,-,an, and an integer k≥2. Count the number of ...