如何在PHP中并发调用Bittrex API查询代币价格
如何用PHP并发调用Bittrex API批量获取山寨币价格
嗨,我完全懂你的困扰——串行循环在币多的时候简直是效率杀手,尤其还是每分钟要跑的Cron任务,必须换成并发才行!下面我给你两种适合新手的实现方式,一步步来,保证你能搞定。
方式一:用原生cURL多句柄(无需额外扩展)
这是PHP自带的功能,不用装任何东西,最适合新手快速上手。核心思路是一次性创建多个cURL请求句柄,让它们同时发起请求,而不是等一个完成再发下一个。
完整代码示例
<?php $coins = array("BTC-LTC", "BTC-PTOY", "BTC-BLK"); // 这里可以换成你的100+币的数组 // 初始化cURL多句柄 $multiHandle = curl_multi_init(); $handles = []; // 为每个币种创建单独的cURL句柄,并添加到多句柄中 foreach ($coins as $mktCode) { $url = "https://bittrex.com/api/v1.1/public/getticker?market=" . urlencode($mktCode); $handle = curl_init($url); // 设置cURL选项:返回结果而不是直接输出,设置超时时间 curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); curl_setopt($handle, CURLOPT_TIMEOUT, 10); // 10秒超时,避免卡住 curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false); // 新手可以先关SSL验证,生产环境建议开启 // 把句柄加入多句柄,并保存到数组方便后续处理 curl_multi_add_handle($multiHandle, $handle); $handles[$mktCode] = $handle; } // 执行所有并发请求 $running = null; do { curl_multi_exec($multiHandle, $running); curl_multi_select($multiHandle); // 等待请求完成,避免CPU空转 } while ($running > 0); // 处理每个请求的返回结果 foreach ($handles as $mktCode => $handle) { $response = curl_multi_getcontent($handle); $error = curl_error($handle); if ($error) { echo "获取{$mktCode}价格失败:{$error}\n"; } else { $data = json_decode($response, true); if ($data && $data['success']) { $price = $data['result']['Last']; // 拿到最新成交价 // 这里写你的数据库存储逻辑,比如: // saveToDatabase($mktCode, $price); echo "{$mktCode}的最新价格:{$price}\n"; } else { echo "{$mktCode}返回数据异常:" . ($data['message'] ?? '未知错误') . "\n"; } } // 记得关闭单个句柄 curl_multi_remove_handle($multiHandle, $handle); curl_close($handle); } // 关闭多句柄 curl_multi_close($multiHandle); // 示例:模拟存数据库的函数 function saveToDatabase($market, $price) { // 这里写你的PDO/MySQLi代码,比如插入或更新价格记录 } ?>
关键注意事项
- API请求限制:Bittrex有请求频率限制,别一次性发100个请求!建议分批次,比如一次发20个,处理完再发下一批,避免被临时封禁。
- 超时设置:一定要加
CURLOPT_TIMEOUT,防止某个请求卡住导致整个脚本超时。 - 错误处理:每个请求都要检查错误和返回的
success字段,避免无效数据存入数据库。
方式二:用Guzzle(更简洁的HTTP客户端)
如果你能稍微学习一下Composer,Guzzle会让代码更优雅,并发处理也更简单。
步骤1:安装Guzzle
在项目根目录执行命令:
composer require guzzlehttp/guzzle
步骤2:并发请求代码示例
<?php require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Promise; $coins = array("BTC-LTC", "BTC-PTOY", "BTC-BLK"); $client = new Client(['timeout' => 10]); // 创建所有请求的Promise数组 $promises = []; foreach ($coins as $mktCode) { $url = "https://bittrex.com/api/v1.1/public/getticker?market=" . urlencode($mktCode); $promises[$mktCode] = $client->getAsync($url); } // 等待所有请求完成 $results = Promise\unwrap($promises); // 处理结果 foreach ($results as $mktCode => $response) { $data = json_decode($response->getBody(), true); if ($data && $data['success']) { $price = $data['result']['Last']; // saveToDatabase($mktCode, $price); echo "{$mktCode}的最新价格:{$price}\n"; } else { echo "{$mktCode}返回异常:" . ($data['message'] ?? '未知错误') . "\n"; } } ?>
为什么选Guzzle?
- 代码更简洁,不用手动管理cURL句柄
- 内置Promise机制,处理并发更直观
- 更好的错误处理和HTTP状态码检查
最后给新手的小建议
- 先拿3-5个币测试代码,确保能正常获取价格并存入数据库,再放大到100+
- Cron任务的执行时间:并发后脚本耗时会从几十秒降到几秒,不用担心超时,但还是要设置合理的超时时间
- 监控API返回:如果经常出现失败,可能是请求频率太高,记得调整批次大小
内容的提问来源于stack exchange,提问作者ekidhaja
相关产品推荐
相关产品推荐

