アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんにちは。前提としてPHP初心者です。
現在、いろいろなサイトを参照してPHPによりSNSのカウント数をゲットさせるように試みています。

htmlファイル
--------------
~~
<body>
<?php
include_once("./count.php");
$url="http://www.google.co.jp";

$twitter_count=twitter_count($url);
$facebook_count=facebook_count($url);
$google_count=google_count($url);
$hatena_count=hatena_count($url);
?>
Twitterのカウント数:<?php echo $twitter_count ?>
facebookのカウント数:<?php echo $facebook_count ?>
googleのカウント数:<?php echo $google_count ?>
はてブのカウント数:<?php echo $hatena_count ?>

~~~以下、htmlのメインの話題~~~
</hody>
</html>
--------------

PHPのtwitter_count関数、facebook_count関数など全てカウントを取得する関数はcount.phpに記載しています。
count.php の一部twitter_count関数
--------------
<?php
function twitter_count($url){
//JSONデータを取得
$json = @file_get_contents("http://urls.api.twitter.com/1/urls/count.json?ur …

//JSONデータを連想配列に直す
$array = json_decode($json,true);

//カウント
$count = $array["count"];

return $count;
}
?>
--------------
この様にしてSNSカウントを取得して表示しているのですが、PageSpeed Insightsで調べたら”サーバーが遅い”とかなり点数が低くなってしまいました。
検索してみると確かに普通PHPは非同期処理を前提としないと書いてあって、「遅くなるんだなぁ」って思ったのですが、体感はあまり変わらないのですよね…。
ですので、twitter_count関数、facebook_count関数などカウント取得関数を並列で出来ないかなと思案している次第です。

検索するとPHPでも非同期処理をさせるためにいろいろな関数やモジュール(?https://github.com/hironobu-s/parallel-for さんのparallel-for)などもあるみたいですが、どれも配列に入れたものを何か操作する見たくて全くイメージがつかめません。
私のカウント取得関数を配列からどう動作させるの???みたいな感じです。

どうにかして非同期処理を出来ないでしょうか?

そのうちMySQLも使用したいと思っているので非同期処理をマスターしたいです。

よろしくお願いいたします!

(P.S. jqueryのajaxでの取得もいろいろ参照させて頂いて試みました。それぞれ.js外部ファイルを作って、htmlファイルの最後の方で呼び出しているのでPageSpeed Insightsは高いのですがPHPでの取得時より体感的に重いです…それにfeedlyは5月くらいからパイプ?での取得のjqueryでは無理となったみたいで…。)

A 回答 (5件)

仮に1つのスクリプト内で、それぞれを件数取得を非同期で行えたとしても、すべてが取得し終わってから、後続処理を行う必要があると思うので、どれか1つの件数取得が何らかの原因でやたら遅かった場合、結果的にレスポンスが遅いことになると思いますよ。


(今よりは早くなるでしょうが、瞬時ではない)
逆に、件数取得を待たずに画面を表示するならば、そのタイミングで件数を取得する必要性もないと思います。

完全にリアルタイムである必要がないのならば、1スクリプトですべてを担う方法ではなく、サーバ側のcronなどを使って定期的に件数を取得させるようにしておいて、表示側はただ予め取得されている件数を表示するだけ、とかの方がよくないですか?

その上で、まさに今時点での件数が見たいんだ、というアプローチを件数更新画面などを設けて作るとか。
その時にはexec()コマンドで叩きます。
http://se-suganuma.blogspot.jp/2009/02/php_27.html

なので、とりあえずぱっと思いついた方法論は以下の2つ
【方法1】
スクリプトA
 予め取得済みの件数を表示するのみ。
cron
 exec()を叩くアドレスに対して定期的にリクエストを投げ、
 件数を取得・保持する。

【方法2】
スクリプトA
 予め取得済みの件数を表示する。
 JS(jQuery)でクライアントにAjaxを頑張ってもらって、exec()を
 叩くアドレスへリクエストを投げ、定期的に件数を取得・保持
 しに行き、JSON形式などで件数をクライアントへ受け取り、
 画面に表示されている件数を変更する。
cron
 exec()を叩くアドレスに対して定期的にリクエストを投げ、
 件数を取得・保持する。

それらの過程でデータベースでも使えばいいんじゃないですかね。
簡単に、
id:bigint, autoincrement
name:varchar(128)
url:varchar(256)
status:int(1) 0:未リクエスト、1:リクエスト中
hit_count:unsigned int
とか定義して、
1.exec()で走行した直後にstatusを確認して、リクエスト中なら
  現在保持してる件数を返す。
2.statusをリクエスト中に更新。
3.対象URLへアクセスして件数を取得。
4.hit_countに件数、statusを未リクエストに更新。

とか?
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
お返事遅れまして申し訳ございません。とても役に立ちました。
現状、今のサーバーではDBが使えませんので引っ越しします。DBを使える環境になったらまた質問させて下さい。
本当にお優しいですね。感謝しています!!!

お礼日時:2015/07/26 03:36

>仰るとおりに、巡回処理と結果表示を別にやりました。

ありがとうございます。
>ですが、並列処理のやり方が分からなく、150個のURL処理に5分かかってしまいます。

どうも話しのニュアンスがうまく伝わっていないようで
わたしの書き方がわるかったのか申し訳ないです

巡回処理と結果表示を別にやれば
巡回処理がべつに5分かかろうが1時間かかろうがどうでもよい話で
150か所の巡回をしたとして結果を逐次プールしているのですから
結果表示時点で最終巡回したデータは常に一瞬で表示できますよね?

一番単純な並行処理はexecなどでバックグラウンドのコマンドを1処理ずつまわすことです
CLIで処理してもwgetなどで自分自身をhttp経由でゲットしてもどちらでもよいでしょう。
    • good
    • 0
この回答へのお礼

再度のご回答ありがとうございます。

>どうも話しのニュアンスがうまく伝わっていないようで
>わたしの書き方がわるかったのか申し訳ないです

とんでもないです、yambejpさんは何も悪くないです。
私はyambejpさんの仰ることを理解して、そして発展して巡回処理も早くできたら良いと考えたのです。私の方こそ申し訳ございません。

何とかご指摘なさった方法で出来ました。

500程のURLで実行したらPCがかなり重くなりました(汗)
それにSNS側の制限もあるみたいで取得できないカウントも出てきたりしたので、
並列を少なくしたいと思います。これではサーバー側で泊められてしまいます。迷惑はかけられません。

本当にありがとうございました。

お礼日時:2015/07/23 13:13

ざっとみた感じ今回の命題SNSの巡回処理と結果表示を分けた方がよいでしょう。


SNS巡回は定期処理で行えば、巡回した時点での最新データを表示することができるので
リードタイムはほぼなくなり瞬時に表示されます
    • good
    • 0
この回答へのお礼

yambejpさん、ご回答ありがとうございます。

仰るとおりに、巡回処理と結果表示を別にやりました。ありがとうございます。
ですが、並列処理のやり方が分からなく、150個のURL処理に5分かかってしまいます。

仕組みとしては、urlリストの中からurlを配列に渡してurl1つをゲットして単純に、
$twitter_count=twitter_count($url);
$facebook_count=facebook_count($url);
$pocket_count=pocket_count($url);
と直列に(?)やって1つのurlにつき1つのファイルにまとめて書き出して、それを$urlを変えてwhileで回しています。

希望としては、1つのurlでそれぞれのカウント数を並列に取得して、そのurlにつき全部取得できたと分かったらファイルに書き込み、次のurlに遷るということをしたいです。

MySQLを学ぶためにも並列処理は是非必要です。

原理的には
echo "wow"; //これを10000回表示する関数
echo "465"; //これを10000回表示する関数
を並列にやることと同じと思います。

やり方はありますでしょうか?

よろしくお願いいたします。

お礼日時:2015/07/23 08:54

>ajaxでやるばあいはどの様にしたらよろしいでしょうか?


ググれ

>PHPでも是非非同期処理をしてみたいので何かありませんでしょうか。
http://www.php.net/manual/ja/book.pthreads.php
このモジュールを使ってマルチスレッド処理を書く。
    • good
    • 0
この回答へのお礼

再度のご回答ありがとうございます。

>>ajaxでやるばあいはどの様にしたらよろしいでしょうか?
>ググれ
すみません。検索をしてもやり方が分かりませんでした。
是非、教えて下さい。

>>PHPでも是非非同期処理をしてみたいので何かありませんでしょうか。
>http://www.php.net/manual/ja/book.pthreads.php
>このモジュールを使ってマルチスレッド処理を書く。
上記のモジュールですが使おうとしたのですが意味が分かりませんでした。

http://qiita.com/rana_kualu/items/02f380f2f3d502 … さんから拝借すると、
<?php
class TestThread extends Thread{
/**
* @Overide
* startしたときに呼ばれる
*/
public function run(){
// 時間のかかる処理
sleep(10);

// このスレッドのIDを確認
print($this->getThreadId());
// これを呼び出したスレッドのIDを確認
print($this->getCreatorId());
}
}

// TestThreadを別スレッドで起動
$testThread1 = new TestThread();
$testThread1->start();
$testThread2 = new TestThread();
$testThread2->start();
~~~
とありますが、run()に私のtwitter_count関数、facebook_count関数を併記しても意味ないと思います。
別スレッドで起動しても"同じ並列処理を非同期処理する"と思うので。

run()内の書き方を是非教えて下さい!これからMySQLでも非同期処理が是非したいのです。

よろしくお願いいたします!

お礼日時:2015/07/21 04:49

ajaxで処理した方が楽。

    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
http://nelog.jp/get-feedly-count にあるのですが、
>これを回避するためには、やはりfeedlyから直接PHPで購読者数を取得するしかないようです。

ajaxでやるばあいはどの様にしたらよろしいでしょうか?

あと、PHPでも是非非同期処理をしてみたいので何かありませんでしょうか。
よろしくお願いいたします。

お礼日時:2015/07/20 14:24

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!