API-запросы с PHP медленное время загрузки

Я использую PHP для получения данных о ценах и объемах от нескольких бирж биткойнов, но когда вы загружаете страницу, это занимает около 20 секунд. Как я могу улучшить время загрузки? Я думаю, что это как-то связано с завитком.

 <?php
function getData($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$rawData = curl_exec($curl);
curl_close($curl);
return json_decode($rawData, true);
}
//BTC Volume LocalBitcoins
$BTCVolumeLocal = getData('https://localbitcoins.com/bitcoinaverage/ticker-all-currencies/');
$LocalVolume = $BTCVolumeLocal["USD"]["volume_btc"];

//BTC Volume BTCE
$BTCVolumeBTCE = getData('https://btc-e.com/api/3/ticker/btc_usd');
$BTCEVolume = $BTCVolumeBTCE["btc_usd"]["vol_cur"];

//BTC Volume Bitstamp
$BTCVolumeStamp = getData('https://www.bitstamp.net/api/ticker/');
$StampVolume = $BTCVolumeStamp["volume"];

//BTC Volume Bitfinex
$BTCVolumeFinex = getData('https://api.bitfinex.com/v1/pubticker/btcusd');
$FinexVolume = $BTCVolumeFinex["volume"];

//BTC Volume OKCoin
$BTCVolumeOK = getData('https://www.okcoin.com/api/ticker.do?ok=1');
$OKCoinVolume = $BTCVolumeOK["ticker"]["vol"];

//BTC Volume LakeBTC
$BTCVolumeLake = getData('https://www.lakebtc.com/api_v1/ticker');
$LakeVolume = $BTCVolumeLake["USD"]["volume"];

//Totals the Volumes
$TotalVolume = $LakeVolume + $FinexVolume + $OKCoinVolume + $StampVolume + $BTCEVolume + $LocalVolume;
//Percents of Total Volume
$BTCEPercent = $BTCEVolume / $TotalVolume;
$StampPercent = $StampVolume / $TotalVolume;
$FinexPercent = $FinexVolume / $TotalVolume;
$OKPercent = $OKCoinVolume / $TotalVolume;
$LakePercent = $LakeVolume / $TotalVolume;
$LocalPercent = $LocalVolume / $TotalVolume;

//BTC Price BTCE
$BTCPriceBTCE = getData('https://btc-e.com/api/3/ticker/btc_usd');
$BTCEPrice = $BTCPriceBTCE["btc_usd"]["last"];

//BTC Price Bitstamp
$BTCPriceStamp = getData('https://www.bitstamp.net/api/ticker/');
$StampPrice = $BTCPriceStamp["last"];

//BTC Price Bitfinex
$BTCPriceFinex = getData('https://api.bitfinex.com/v1/pubticker/btcusd');
$FinexPrice = $BTCPriceFinex["last_price"];

//BTC Price OKCoin
$BTCPriceOK = getData('https://www.okcoin.com/api/ticker.do?ok=1');
$OKPrice = $BTCPriceOK["ticker"]["last"];

//BTC Price LakeBTC
$BTCPriceLake = getData('https://www.lakebtc.com/api_v1/ticker');
$LakePrice = $BTCPriceLake["USD"]["last"];

//BTC Price LocalBitcoins
$BTCPriceLocal = getData('https://localbitcoins.com/bitcoinaverage/ticker-all-currencies/');
$LocalPrice = $BTCPriceLocal["USD"]["avg_1h"];

//BTC Price * Percent
$BTCEPricePercent = $BTCEPrice * $BTCEPercent;
$StampPricePercent = $StampPrice * $StampPercent;
$FinexPricePercent = $FinexPrice * $FinexPercent;
$OKPricePercent = $OKPrice * $OKPercent;
$LakePricePercent = $LakePrice * $LakePercent;
$LocalPricePercent = $LocalPrice * $LocalPercent;

//Bitcoin Price
$bitcoinPrice = round($LakePricePercent + $OKPricePercent + $FinexPricePercent + $StampPricePercent + $BTCEPricePercent + $LocalPricePercent, 2);

?>

1

Решение

Если API не реагируют достаточно быстро и не находятся под вашим контролем, вы, вероятно, не сможете изменить это.

Параллельный запрос к ним может ускорить процесс, но, как упоминалось в комментариях, с помощью PHP это обычно не так просто.

Если это просто время загрузки вашей страницы, вы можете кэшировать результат запросов API:

  • Поместите запросы API в cronjob, который вызывается автоматически каждые x минут. В зависимости от того, насколько быстро изменяются входные данные, это может быть всего 1 минута (что, к сожалению, означает, что вы создадите много трафика), или вы можете запрашивать их раз в час, если это нормально для ваших расчетов.
  • Сохраните результат в локальной базе данных или кэше (MySQL, Redis, Memcache, …)
  • Для ваших расчетов читайте только из локальной копии значений, что будет намного быстрее, чем каждый раз запрашивать услуги
4

Другие решения

У вас 12 звонков, и 20 секунд — это реально. Я не знаком с вашим приложением, но вы можете рассмотреть возможность реализации некоторого кэширования (сохранение загруженных данных в файлы и последующая загрузка из загруженных файлов).

$url = 'http://www.example.com';
$content = '';
$file_name = 'tmp/cache.txt';

if(file_exists($file_name))){
$content = file_get_contents($file_name);
}else{
$content = file_get_contents($url);
//or $content = getData($url);
file_put_contents($file_name, $content);
}


function getData($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$rawData = curl_exec($curl);
curl_close($curl);
return json_decode($rawData, true);
}
2

Многопоточность и / или кеширование, друг.

Многопоточность в PHP не сложнее, чем в любом другом языке. Вы можете найти инструкции здесь: Как можно использовать многопоточность в приложениях PHP

Вы можете использовать простое кэширование с Memcache или Redis, и в Интернете есть все виды учебных пособий и справок, чтобы использовать их для кэширования содержимого в PHP.

1

Я обнаружил, что при использовании ajax все результаты возвращались достаточно быстро, потому что запросы выполнялись асинхронно, и это пока что в процессе ….. Если другие здесь могут увидеть выгоду, я думал, что я понял, что этот подход, несомненно, они прибью это.

Идея заключается в том, что функция js отправляет серию запросов ajax в скрипт php, который затем отправляет запрос curl на различные заданные URL-адреса биткойнов. Каждый запрос настроен так, чтобы нести с собой поля, которые должны быть возвращены из запроса. Затем скрипт php просматривает данные и находит эту информацию и возвращает ее в js.

Вычисление различных процентов остается проблемой, так как вы не обязательно знаете, когда все запросы были выполнены. Похоже promises может быть полезным?

Конечно, использование ajax позволяет быстро загружать страницу — тогда результаты возвращаются «как и когда» до тех пор, пока не закончится …..

bitcoin.php
-----------
<?php
if( $_SERVER['REQUEST_METHOD']=='POST' ){

$cacert='c:\wwwroot\cacert.pem';


/* Two of the three params sent via ajax */
$url=$_POST['url'];
$fields=$_POST['fields'];

/* $fields might be a comma separated list of fields, or simply one - we want an array */
$params=( !empty( $fields ) && strstr( $fields, ',' ) ) ? explode( ',', $fields ) : (array)$fields;


$curl=curl_init( $url );

if( parse_url( $url, PHP_URL_SCHEME )=='https' ){
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, 2 );
curl_setopt( $curl, CURLOPT_CAINFO, realpath( $cacert ) );
}

curl_setopt( $curl, CURLOPT_URL, $url );
curl_setopt( $curl, CURLOPT_HEADER, false );
curl_setopt( $curl, CURLOPT_FRESH_CONNECT, true );
curl_setopt( $curl, CURLOPT_FORBID_REUSE, true );
curl_setopt( $curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 );
curl_setopt( $curl, CURLOPT_CLOSEPOLICY, CURLCLOSEPOLICY_OLDEST );
curl_setopt( $curl, CURLOPT_BINARYTRANSFER, true );
curl_setopt( $curl, CURLOPT_AUTOREFERER, true );
curl_setopt( $curl, CURLOPT_CONNECTTIMEOUT, 10 );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $curl, CURLOPT_USERAGENT, 'Bitcoin Fuzzer' );


$data=trim( curl_exec( $curl ) );
$status=curl_getinfo( $curl,CURLINFO_HTTP_CODE );
curl_close( $curl );



/* Deal with the response data */
if( $status==200 ){

$json=json_decode( $data );
/*
Hack:
there must be a better way to drill down dynamically through
an object structure but I was too tired to think straight

This simply echos back the response for javascript to deal with
but I guess one could make use of sessions to do the calculations
in php rather than js
*/
switch( count( $params ) ){
case 1:
$p1=$params[0];
print_r( $json->$p1 );
break;
case 2:
$p1=$params[0];
$p2=$params[1];
print_r( $json->$p1->$p2 );
break;
case 3:
$p1=$params[0];
$p2=$params[1];
$p3=$params[2];
print_r( $json->$p1->$p2->$p3 );
break;
}
}
}
?>

HTML-страница — заголовок:

<script type='text/javascript' charset='utf-8'>
/* simple ajax function */
function _ajax( url, options ){
var req=new XMLHttpRequest();
var callback=options.hasOwnProperty('callback') ? options.callback : false;
if( !callback ) return false;


var headers={
'Accept': "text/html, application/xml, application/json, text/javascript, "+"*"+"/"+"*"+"; charset=utf-8",
'Content-type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
};

var params=[];
if( options.hasOwnProperty('params') && typeof( options.params )=='object' ){
for( var n in options.params ) params.push( n + '=' + options.params[n] );
}
var args=options.hasOwnProperty('args') ? options.args : options;

req.onreadystatechange=function(){
if( req.readyState==4 ) {
if( req.status==200 ) options.callback.call( this, req.response, args );
else console.warn( 'Error: '+req.status+' status code returned' );
}
}

req.open( 'POST', url, true );
for( header in headers ) req.setRequestHeader( header, headers[ header ] );
req.send( params.join('&') );
}

var volumes=[];
var prices=[];
var tot_vols=0;
var tot_prices=0;

function bitcoin(){
var btc={
vols:{
'https:\/\/localbitcoins.com\/bitcoinaverage\/ticker-all-currencies\/':['USD','volume_btc'],
'https:\/\/btc-e.com\/api\/3\/ticker\/btc_usd':['btc_usd','vol_cur'],
'https:\/\/www.bitstamp.net\/api\/ticker\/':['volume'],
'https:\/\/api.bitfinex.com\/v1\/pubticker\/btcusd':['volume'],
'https:\/\/www.okcoin.com\/api\/ticker.do?ok=1':['ticker','vol'],
'https:\/\/www.lakebtc.com\/api_v1\/ticker':['USD','volume']
},
prices:{
'https:\/\/btc-e.com\/api\/3\/ticker\/btc_usd':['btc_usd','last'],
'https:\/\/www.bitstamp.net\/api\/ticker\/':['last'],
'https:\/\/api.bitfinex.com\/v1\/pubticker\/btcusd':['last_price'],
'https:\/\/www.okcoin.com\/api\/ticker.do?ok=1':['ticker','last'],
'https:\/\/www.lakebtc.com\/api_v1\/ticker':['USD','last'],
'https:\/\/localbitcoins.com\/bitcoinaverage\/ticker-all-currencies\/':['USD','avg_1h']
}
};
var url;
var vols=btc.vols;
var prices=btc.prices;

for( url in vols ){
getbitcoin.call( this, url, vols[url], 'volumes' );
}

for( url in prices ){
getbitcoin.call( this, url, vols[url], 'prices' );
}
}


function getbitcoin( url, fields, type ){
var options={
callback:cbbtc,
method:'POST',
params:{
'fields':fields,
'type':type,
'url':url
}
};
_ajax.call( this, '/test/bitcoin.php', options );
}

function cbbtc(r,o){
switch( o.params.type ){
case 'volumes':
tot_vols += parseFloat( r );
volumes.push( parseFloat( r ) );
document.getElementById('btc_vols').value=tot_vols;
break;
case 'prices':
tot_prices += parseFloat( r );
prices.push( parseFloat( r ) );
document.getElementById('btc_prices').value=tot_prices;
break;
}
}

/* launch the function when the page is ready */
document.addEventListener( 'DOMContentLoaded', bitcoin, false );
</script>

HTML страница — тело:

/* These simply receive values for testing */
<input type='text' id='btc_vols' />
<input type='text' id='btc_prices' />
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector