hadoop 0.21.0 ant build thrift php

名詞解釋
hadoop : 分散式檔案系統與 MapReduce 運算軟體框架
HDFS : 分散式檔案系統
ant : Java 自動編譯工具
thrift : 跨語言 API 介面,由 Facebook 開發用來銜接各語言 api 。

編譯 hadoop 建立 thrift server 

$ install ant
$ cd ./hdfs ;
$ ant compile

if error

[ivy:resolve] module not found: org.apache.hadoop#hadoop-common;0.21.0

原先的 repo snapshot 檔名都換過了,將 build.xml 內 repo 網址改成

https://repository.apache.org/content/repositories/snapshots/ => https://repository.apache.org/service/local/repositories/orgapachehadoop-042/content/

從 https://repository.apache.org/index.html 找到的

編譯 again

warning ‘includeantruntime’ was not set

錯誤 依照錯誤行數 在 javac 加上 includeantruntime=”false” 屬性就略過了 (http://www.coderanch.com/t/503097/tools/warning-includeantruntime-was-not-set)

接著會有 lib not fount 的錯誤

搬移 $hadoop/lib to hdfs/lib 應該是因為 抓的是 release 不是 dev 的版本 目錄位置有些差異,

然後發現缺了 conf ,所以對著 $hadoop/common 造著編譯一次,

然後混和兩個資料夾,我是建了一個 $hadoop/build

然後 cp $hadoop/common $hadoop/build -r ; cp $hadoop/hdfs $hadoop/build -ru

hdfs thrift server 環境就差不多了,thrift 負責建立一個 socket ,然後用各種語言透過 socket 連接 API 。

為什麼要自己編譯 hadoop 呢?我也不知道…感覺可以把編譯好的 hadoop-thrift.jar 拿來用,但是沒有地方有教…

只好照著有人有教的方式做,就編譯吧,順便瞭解一下原始碼路徑,大略看一下程式邏輯,並且之後還能做修改。

編譯 thrift-php ext

接著要建立 php 連接 thrift 的環境,可以先裝 thrift (http://thrift.apache.org/) 只是用不到= =,

thrift 應該是用來把寫好的 *.thrift(抽象API描述) 編譯成各種語言適用的API,只是 hadoop 已經都編譯好了,在 gen-php 裡面,

thrift 下載好以後,裡面有附 php-ext module 的程式,就一樣phpize;./configure;make ;make install;

他好像會在 /usr/lib/php/ 下面複製好對應的程式,./protocol/ , ./transport/ , ./Thrift.php …應該是吧 如果沒有就自己從 Thrift 原始碼裡面 co 出來吧,

然後建立一個 /usr/lib/php/packages/ 然後把 gen-php 丟進去 改名字叫…XD…原始碼裡面有寫…自己看…

example

進資料夾跑 build/src/contrib/thriftfs/scripts/start_thrift_serve.sh $port & 吧 ,可以指定 port,他會連結哪台伺服器一樣在 conf/core-site.xml 裡面設定,

然後在跑 client demo ..應該還ok,只是不知道 thrift_protocol 有作用嗎…

<?php
//include thrift路徑
$GLOBALS['THRIFT_ROOT'] = '/usr/lib/php';
require_once( $GLOBALS['THRIFT_ROOT'].'/Thrift.php' );
require_once( $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php' );
require_once( $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php' );
require_once( $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php' );
require_once( $GLOBALS['THRIFT_ROOT'].'/packages/hadoopfs/ThriftHadoopFileSystem.php' );
//建立連線
$socket = new TSocket( 'localhost', 50000 );
$socket->setSendTimeout( 10000 ); // Ten seconds
$socket->setRecvTimeout( 20000 ); // Twenty seconds
$transport = new TBufferedTransport( $socket );
$protocol = new TBinaryProtocol( $transport );
$client = new ThriftHadoopFileSystemClient( $protocol );
//啟動
$transport->open();
/*程式碼寫在這*/
try {
$pathname = new Pathname(array("pathname" => "/mlwmlw/"));
print_r($client->mkdirs($pathname));
<div>$pathname = new Pathname(array("pathname" => "/"));
<div>//列表
print_r($client->listStatus($pathname));
//用帳號名稱相同就能跨伺服器存取資料 權限很弱喔?!
} catch(Exception $e) {
print_r($e);
}
$transport->close();
?>

接著測 create and write 的部份就出錯了,錯誤訊息有兩種,第一次都是
TException: TSocket: Could not write 4 bytes
接著都是 TScoket timeout,在某篇資源裡面有提到他猜測是 php 處理 64bit 的整數時造成的錯誤,
因為 Thrift 有定義 64bit 整數的型態,然後API裡面有一個 readI64 的函式,好像是在合成兩個 32bit 的整數,
我自己試著去把 create 產生的 fileid 印出來,跟 HadoopThriftServer 進行比對,
發現總是對不起來,因為 create 產生的是 getRandom().nextLong() 好像都是滿滿 64bit 的長整數,
將他替換成 nextInt() 重新編譯就沒有問題了。

#org/apache/hadoop/thriftfs/HadoopThriftServer.java 50行
-- private long nextId = new Random().nextLong();
++ private long nextId = new Random().nextInt();

[參考資源]