Use Memcached in PHP on heroku

Memcached 在網頁中可以用來加速網頁的存取速度,也可以用來減少回應相同使用者需求的時間

因為課程的關係,我使用了 Heroku 這個平台來 deploy 我的網頁,Heroku 免費的版本提供了 25 MB 大小的 Memcached,但是你必須先註冊你的信用卡資料才可以將這項服務套用至你的網頁程式中

要選用 Memcached 這樣服務,要到 Add-on 的頁面來設定

擷取.JPG
2.JPG

請選擇 MemCachier 這個項目,進去以後往下拉可以看到中間有一個區塊讓你選擇要採用多少大小的 Memcached

3.png

以免費版的為例,我們點選最後一個 Developer Free 的項目以後,右下方的有一個選項請你選擇你要套用的網頁應用程式,我選擇 cryptic-atoll-1791,接著 Add Developer for Free

如果你還沒填寫信用卡資料,在這一步驟會請你先去填完信用卡資料再回來設定
既然是免費的為什麼還需要信用卡?和 Amazon 的 AWS 一樣,如果你有 more over 的需求時,系統會藉由此信用卡先向你 charge,但是免費的就是免費的,不會收費

當設定好 Memcached 以後,就要來修改我們的程式碼,讓它具有 Memcached 的功能了,我們以一個可以找到小於使用者輸入的數字的最大質數做範例:

<?php
 
 /* include MemcacheSASL.php */
include('MemcacheSASL.php');
$m = new MemcacheSASL;
$server = explode(",", getenv("MEMCACHIER_SERVERS"));
foreach ($server as $s) {
  $parts =explode(":", $s);
  $m->addServer($parts[0], $parts[1]);
}
$m->setSaslAuthData(getenv("MEMCACHIER_USERNAME"),getenv("MEMCACHIER_PASSWORD"));
 
/* GET user input number */
if (!isset($_GET["n"])) {
  echo "Invalid numver n !";
  exit;
}
$n = intval($_GET["n"]);
if ($n <= 1) {
  echo "n should be >1!";
  exit;
} else if ($n > 1000) {
  echo "n should be <=1000!";
}
 
 /*
  * using cache here to check if the prime is exist in cache. 
  * (PHP Site uses Memcached as its class, SASL uses MemcacheSASL as its class, I use the latter one)
  */
 if(($p = $m->get($n))) {      // check cache 
    echo "Get ".$p." from memcached!";
 }
 else {        // if cache miss, find the prime
  $prime = 1;
  for ($i = $n; $i > 1; $i--){
    $is_prime = true;
    for ($j = 2; $j < $i; $j++) {
      if ($i % $j == 0){
        $is_prime = false;
        break;
      }
    }
    if ($is_prime) {
      $prime = $i;
      echo "<=".$n." has the biggest prime ".$prime."</br>";
      echo "<a href='index.php'>Back</a>";
      break;
    }
  }
 
  /*store it in cache */
  $m->set($n, $prime);
 }
?>
 

在第一部分我們引用了一個名為 PHPMemcachedSASL.php 的 library,讓我們可以操作 Memcached,這個函式庫需要到作者的 GitHub 上去下載:https://github.com/ronnywang/PHPMemcacheSASL

事實上 PHP Library 中就有 Memcached 的操作函式,可能是因為 Memcached 缺乏認證與安全管制,所以 Heroku 官方文件才會建議採用 MemcachedSASL 而不是使用 PHP 內建 Memcached Library 作為網頁 Memcached API 的原因,但是兩者的使用方式都相同,基本的 get()、set() 和 add() 都有!

第二部份我們接收來自 index.php 這張網頁的輸入值,驗證他的合法性與範圍

第三部分一開始我們呼叫 Memcached 物件 $m 的 get($key) 這個方法,來檢查看看我們要查的質數是否已經在 Cache 中,這裡的 $key 正是使用者所輸入的值,如果找到的話,我們就印出這個值數,否則會得到 False,我們才接著尋找質數

最後一部分是在進行尋找質數之後,因為我們沒有在 Cache 中找到質數,所以找到質數以後,為了讓下次有使用者輸入同樣的數要找質數時可以較快速的直接從 Cache 找而不用做運算,所以我們呼叫了 $m 的 set($key, $value) 這個方法,其中 $key 一樣是我們給使用者輸入的數,$value 就是我們找到的質數啦! 我們用使用者輸入的值當作查找 cache 的鍵值,有點像雜湊的

事實上,set($key, $value) 完整的簽名是這樣的: set($key, $value, [$expiration])
最後的 $expiration 參數是選擇性的,用來指定這筆快取頁存在 Cache 多久以後可以被清掉

memcached 使用 add, set 和 replace 的差異.png

而 set() 有一個與他簽名完全相同的攣生兄弟 add($key, $value, [$expiration])
另外還有一個沒有 $expiration 的相似方法 replace($key, $value)

(圖表來源:http://blog.roga.tw/2010/09/%E5%B0%8D-memcached-server-%E5%81%9A-add-set-replace-%E5%B7%AE%E5%88%A5/)

寫好之後重新 push 到 Heroku 上,就可以測試 Memcached 的效果囉!
http://cryptic-atoll-1791.herokuapp.com/index.php

1.JPG

假設輸入 10

2.JPG

因為沒有查找過,所以進行尋找質數的運算,並偷偷地加入的快取中

1.JPG

回到首頁在輸入一次 10

這次就 Cache Hit 了!

3.JPG

更多關於 Heroku 的使用,請見:

  1. https://www.heroku.com/about
  2. http://www.inside.com.tw/2010/09/20/heroku

[PHP] Twitter REST API (以Search API為例) – 使用 TwitterAPIExchange.php

基本上作者有一份文件,教學講得還蠻完整的,這個專案還不停的在更新。
同樣的,要使用 Search API 撈取 twitter 的歷史 tweets,必須要先到開發者網站去建立你的 Application 並取得 Consumer KeyConsumer SecretAccess Token  Access Token Secret
接著你需要到 TwitterAPIExchange 的 GitHub 上去下載這個專案回來

你會發現這個專案的檔案數目比 Phirehose 少了很多,最核心的也就只有 TwitterAPIExchange.php 這支檔案
把下載回來的原始碼資料夾放置到網頁或是應用程式的目錄下,接著開始編輯你要用來撈資料的 PHP 檔案:

1. 在檔案中引入 TwitterAPIExchange.php 這個檔案
require_once(‘TwitterAPIExchange.php’);
2. 接著你需要設定取得的 OAuth Keys
$settings = array(
    'oauth_access_token' => "YOUR_OAUTH_ACCESS_TOKEN",
    'oauth_access_token_secret' => "YOUR_OAUTH_ACCESS_TOKEN_SECRET",
    'consumer_key' => "YOUR_CONSUMER_KEY",
    'consumer_secret' => "YOUR_CONSUMER_SECRET"
);

之所以是用陣列來儲存這些 keys 的原因在於,我們稍後建立查詢物件 TwitterAPIExchange 的時候,就會直接在 Constructor 中用這四個 keys 來做物件初始化

3. 設定好了 Keys 之後,還需要設定你要存取的 API URL 和指定存取的方式為 GET 還是 POST
$url = 'https://api.twitter.com/1.1/search/tweets.json';
$requestMethod = 'GET';
4. 因為我們要取得有篩選過的資料,因此還要再多設定過濾參數
l   假如你是採用 GET 方法,直接寫成:
$getfield = '?q=Justin+AND+Singer&count=2';
(注意!有包含 “?q=" 這三個字元喔!)
l   假如你是採用 POST 方法,需要以陣列來一一儲存:
$postfields = array(
    'screen_name' => 'usernameToBlock', 
    'skip_status' => '1'
); 
5. 如此最主要的四個項目:KeyURLMethodfilter 都設定好了以後,就可以建立查詢物件 TwitterAPIExchange 來送出查詢請求
$twitter = new TwitterAPIExchange($settings);
echo $twitter->buildOauth($url, $requestMethod)
             ->setPostfields($postfields)
             ->performRequest();
new 出物件以後,利用這個物件先做驗證,然後設定查詢過濾參數,最後才發送出 request,伺服器接收以後會回傳要求存取的資料
回傳的物件多數為 JSON 格式,如果無法直接用 echo 解析(至少我無法),可以修改如下:
$json = $twitter->buildOauth($url, $requestMethod)
             ->setPostfields($postfields)
             ->performRequest();
var_dump(json_decode($json, true));
下圖為我上面使用 GET 方法像 Search API 的要求存取包含 Justin 和 Singer 兩個關鍵字的 tweets.json

你可以開啟 index.php 這支檔案試試看,那是一個作者寫的範例程式

這個作品還真的是很漂亮的一支程式

[PHP] Twitter Streaming API – 使用 Phirehose.php

要使用 Twitter Streaming API 來撈資料,首先還是要了解 Twitter Streaming API 是什麼,可以<!–看參考這裡(因為我覺的官網說明還是有點模糊),或是直接–>官網
Phirehose.php 是由 fennb (Fenn Bailey) 包裝的一個存取 Twitter Streaming API 工具,
要以使用 Twitter Streaming API,有兩個除了可解讀 PHP 的伺服器外的預備工作:

1.      下載 Phirehose:你可以直接到這個專案的 GitHub 下載 Zip 來用:https://github.com/fennb/phirehose ,下載回來的 Zip 解壓縮以後會有兩個資料夾和一些文字檔案,其中合新的檔案都在lib資料夾中的三個,example 資料夾中的檔案是作者的示範 PHP 程式,我主要以 sample.php 做測試,只會用到 lib 中的 OauthPhirehose.php 和 Phirehose.php
2.      取得認證鑰匙 Consumer KeyConsumer SecretOAuth Access Token 和 OAuth Access Secret:可以直接在開發者頁面的『My Applications』那邊取得,也可以到 Streaming API 的三個 API (PublicUserSite) 頁面中的任何一個 Endpoints 頁面,中間右邊的 bar 會有一個 OAuth Tool,那邊也會有你創建過的 Application 項目,選好 Application 按下 Generate 的按鈕,也可以得到這四個認證鑰匙。






      
     OK!

       首先將解壓縮後的整個 Phirehose 放到伺服器的根目錄(如:C:\AppServ\www),接著開 
       啟 example 中的 sample.php 檔,稍微來分析一下 sample.php 的程式結構:

1)    最開始的兩行就是引用了 Phirehose.php 和 OauthPhirehose.php 這兩個檔案,前者是主要連線存取用的類別檔案,後者是用來做 OAuth 認證的檔案類別
require_once(‘..\lib\Phirehose.php’);
require_once(‘..\lib\OauthPhirehose.php’);
2)    接下來的 SampleConsumer 是一個繼承了 OauthPhirehose 類別的作者自定義類別,如此一來我們就可以直接用 SampleConsumer 的實體來進行驗證
class SampleConsumer extends OauthPhirehose
3)      SampleConsumer 裡面主要就是將 API 回傳的 JSON 檔案解碼後印出
4)      在下來的 define,是要設定驗證的四個鑰匙
define(“TWITTER_CONSUMER_KEY", “[Yours]");
define(“TWITTER_CONSUMER_SECRET", “[Yours]");
define(“OAUTH_TOKEN", “[Yours]");
define(“OAUTH_SECRET", “[Yours]");
5)      最後作者只給了兩行
$sc = new SampleConsumer(OAUTH_TOKEN, OAUTH_SECRET, Phirehose::METHOD_FILTER);
$sc->consume();
第一行是用來進行驗證 (*1),並選擇要使用的 Streaming API (*2),作者是以 public stream 的 statuses/filter 為例,所以傳入的第三個參數是 METHOD_FILTER
第二行就是在所有的設定完成後,執行連線存取API的方法

        瞭解了 sample 結構,還無法正確的使用 filter 這個資源,因為 filter 必須指定followerlocationtrack 三種搜尋依據至少一者,我以 track 為例,也就是以關鍵字去查詢,可以打開 Phirehose 的實作,有一個setTrack的方法,就是用來設定查詢時的 track,實做中可以看到 setTrack 的參數 $trackWord 是一個 array,所以我們回到 sample.php 中,在最後一行 $sc->consume(); 前加上下面兩行:
$track = array(        “track" => “Justin");        //設定要查詢的關鍵字 (*3)
$sc->setTrack($track);                            //呼叫 setTrack() 方法設定 track
      好了!然後我們就可以打開瀏覽器來執行sample.php,或是用命令提示字元(command line, terminal)cd 到 example 這個目錄後,輸入 php sample.php (*4) 來執行這支程式

↓ Command Line 執行畫面 ↓
Microsoft Windows [版本 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.
C:\Users\Veck\Desktop>cd C:\AppServ\www\PhirehoseForStreamAPI\example
C:\AppServ\www\PhirehoseForStreamAPI\example>php sample.php
Phirehose: Connecting to twitter stream: https://stream.twitter.com/1.1/statuses
/filter.json with params: array (  ‘delimited’ => ‘length’,  ‘track’ => ‘Justin’
,)
Phirehose: Resolved host stream.twitter.com to 199.59.148.229, 199.59.148.138
Phirehose: Connecting to ssl://199.59.148.138, port=443, connectTimeout=5
Phirehose: Connection established to 199.59.148.138
Phirehose: POST /1.1/statuses/filter.json HTTP/1.0
Phirehose: Host: stream.twitter.com:443
Phirehose: Content-type: application/x-www-form-urlencoded
Phirehose: Content-length: 29
Phirehose: Accept: */*
Phirehose: Authorization: OAuth realm="",oauth_consumer_key="***",oauth_nonce="***",oauth_signature_method="***",oauth_timestamp="***",oauth_version="1.0″,oauth_token="***",oauth_signature="***"
Phirehose: User-Agent: Phirehose/0.2.gitmaster +https://github.com/fennb/phireho
se
Phirehose:
Phirehose: delimited=length&track=Justin
Phirehose:
GeneralovaTori: @justinbieber  Justin, you are everything to me! turn on me atte
ntion please!I can not live without you…..
_SwagLikeJBiebs: RT @teamstr0nger_: Justin, si ya tienes grabado el video PORQ
U? NO LO SUBES Y YA?.
SouZicaBieber: – Gente Rapido , olha isso, a primeira foto ou a segunda https://
t.co/6t9eNb6xeS
routemalik69: RT @InBiebersArmy: #imagine you and Justin cuddling together   htt
p://t.co/D0tcCicvIc
(……)
IAmRayitaJB: RT @OLLGconsejos: A Justin le gusta que las chicas respeten su cuer
po, porqu para l las chicas son mucho ms que un fsico. #BieberHechos
klaudyna_bieber: 4. Justin Bieber – Believe #My50FavouriteSongs
JailienysA: RT @jdbdrxws: #MTVSummerClash Justin Bieber
^C
C:\AppServ\www\PhirehoseForStreamAPI\example>c
   我把上面第一個撈到的 PO 文 (User GeneralovaTori用紅色標起來:

GeneralovaTori: @justinbieber  Justin, you are everything to me! turn on me atte
ntion please!I can not live without you…..

   然後上網去查,可以看到這則推文以及他的發文時間卻實就是不久之前
   PS. 因為我抓下來之後過了一陣子才去查這推文的頁面,所以時間有點久,但也不過就剛才而以:



事實上,官網有說一次可以抓很多筆資料,所已在command line 下會一直跑出抓到的資料,可以自己按ctrl+C 中止程式,但是在網頁的時候就會跑很久,按下取消連線沒辦法只顯示已經抓到的資料,而且很容易讓瀏覽器當掉,我就沒有截圖了

*********************************************************************************************************************

*1 網路上有一些解答是用 $sc = new SampleConsumer([username], [password], Phirehose::METHOD_FILTER);,我測試的結果是會有 HTTP 401 的 Unauthorized 結果,我想可能那些都是比較早的問題,也許是在 Version 1 的使用方式

 *2 Phirehose好像主要是針對 Public StreamUser Stream 要另外使用 UserstreamPhirehose,而 Site Stream,這裡暫時不介紹

*3 經過實驗,track 可以使用  +OR+ 來做多關鍵字的查詢

*4 要使用 php 直些執行,需要將 PHP 安裝的資料夾中的 bin 資料夾覺對路徑加入系統環境變數 PATH 中,且可能需要修改php_mbstring.dll的問題

***可能問題***
1.      如果 php sample.php 的錯誤訊息是如下
Phirehose: TCP failure 1 of 20 connecting to stream: Unable to find the socket transport “ssl” – did you forget to enable it when you configured PHP? . Sleeping for 1 seconds.
解決辦法是到 php.ini 中啟用 extension=php_openssl.so (拿掉前方的 “;”)
2.      使用瀏覽器執行,可能會有下列錯誤訊息:
Fatal error: Maximum execution time of 30 seconds exceeded in C:\AppServ\www…\sample.php on line 617
這是因為 php 預設只會執行一支 PHP 程式等帶三十秒,解決辦法可以修改 php.ini 的 max_execution_time=30 為更高的時間,然後重新啟動Apache;也可以在程式中直接使用 ini_set(“max_execution_time”, “xxx”); set_time_limit(xxx) [0為無限]


<!– 對REST API有興趣,可以參考:[PHP] Twitter REST API (Search API為例) 使用 TwitterAPIExchange.php –>