我使用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);
?>
如果api响应不够快,而且它们不在你的控制之下,你可能无法改变这一点。
并行查询它们可能会加快速度,但正如在评论中提到的,使用PHP通常不那么容易。
如果只是关于页面的加载时间,您可以缓存API查询的结果:
- 将API请求放在cronjob中,每隔x分钟自动调用一次。根据输入数据的变化速度,这可以低至1分钟(不幸的是,这意味着您将创建大量流量),或者您可以每小时查询一次,如果这对您的计算是可以的。
- 将结果保存到本地数据库或缓存(MySQL, Redis, Memcache,…)
- 对于您的计算,只从您的本地副本读取值,这将比每次查询服务快得多
你有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);
}
我发现使用ajax,所有结果都相当快地返回,因为请求是异步运行的,到目前为止,这是正在进行的工作.....如果这里的其他人能看到我认为我从这种方法中感受到的好处,毫无疑问他们会成功的。
这个想法是一个js函数向php脚本发送一系列ajax请求,然后将curl请求发送到给定的各种比特币url。每个请求都设置为携带要从请求返回的字段- php脚本然后深入研究数据并找到该信息并返回给js。计算各种百分比仍然是一个问题,因为您不一定知道所有请求何时完成。我猜promises
可能有用?
当然,使用ajax可以让页面快速加载-然后结果返回'as和when'直到完成.....
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 page - body:
/* These simply receive values for testing */
<input type='text' id='btc_vols' />
<input type='text' id='btc_prices' />
多线程和/或缓存,朋友
PHP中的多线程并不比其他语言更难。你可以在这里找到说明:如何在PHP应用程序中使用多线程你可以用Memcache或Redis使用简单的缓存,网上有各种各样的教程和帮助使用这些来缓存PHP的东西。