天天看點

php使用thrift操作hdfs

假定主機上已經安裝了LAMP環境

1. 安裝所需的依賴包

  也可以參考thift官網來安裝 http://thrift.apache.org/docs/install/centos

  #yum install automake libtool flex bison pkgconfig gcc-c++ boost-devel libevent-devel zlib-devel python-devel ruby-devel php php-devel

2. 從http://thrift.apache.org/download/下載下傳thrift源碼包

3. 安裝thrift

    ./configure --with-lua=no –prefix=/usr/local/thrift

(可能出現的錯誤  bison版本不夠,更新bison2.5.*)

    make && make install

4. 安裝php擴充

    cd /path/to/thrift-0.8.0/lib/php/src/ext/thrift_protocol

    phpize

    ./configure -enable-thrift_protocol -with-php-config=/usr/bin/php

    make

    make install

    修改php.ini,添加extension=thrift_protocol.so

5. 從http://hadoop.apache.org/releases.html#Download下載下傳hadoop源碼包

6. 解壓并編譯hadoop(注意必須先安裝好java編譯器,ant編譯環境,以及libtool, autoconf等工具)

    tar zxvf hadoop-1.0.4.tar.gz

    cd hadoop-1.0.4

    ant compile

7. 啟動hdfs以及thrift代理(hdfs叢集配置請參考官方文檔,不再累述)

    cd /path/to/hadoop-1.0.4

    bin/start-dfs.sh

     cd /path/to/hadoop-1.0.4/src/contrib/thriftfs/scripts/

     ./start_thrift_server.sh [port] (如果port為空,則随機一個port)

8. 準備php依賴庫

    cp -r /path/to/thrift-0.8.0/lib/php  /usr/local/thrift/lib

    mkdir -p /usr/local/thrift/lib/php/src/packages

    cp -r /path/to/hadoop-1.0.4/src/contrib/thriftfs/gen-php/ /usr/local/thrift/lib/php/src/packages/hadoopfs/

9. php測試代碼

<?php

error_reporting(E_ALL);
ini_set('display_errors', 'on');

$GLOBALS['THRIFT_ROOT'] = '/usr/local/thrift/lib/php/src';
define('THRIFT_ROOT', $GLOBALS['THRIFT_ROOT']);

/**
 * Init Autloader
*/
require_once THRIFT_ROOT . '/Thrift.php';
require_once THRIFT_ROOT . '/transport/TSocket.php';
require_once THRIFT_ROOT . '/transport/TBufferedTransport.php';
require_once THRIFT_ROOT . '/protocol/TBinaryProtocol.php';

$socket = new TSocket('192.168.1.12', 11511);
$socket->setSendTimeout(10000);
$socket->setRecvTimeout(20000);
$transport = new TBufferedTransport($socket);
$protocol = new TBinaryProtocol($transport);

require_once $THRIFT_ROOT . '/packages/hadoopfs/ThriftHadoopFileSystem.php';
$client = new ThriftHadoopFileSystemClient($protocol);

$transport->open();
try{

#$pathname = new Pathname(array('pathname' => '/user/hadoop/dir4test'));

#$fp = $client->open($pathname);

#var_dump($client->stat($pathname));

#var_dump($client->read($fp, 0, 1024));



$pathname = new Pathname(array('pathname' => '/user/hadoop/thrift'));

if(!$client->exists($pathname)){


$client->mkdirs($pathname);


print("Created dir". $pathname->pathname);


var_dump($client->stat($pathname));

}
}
catch(Exception $ex){

print_r($ex);
}
$transport->close();
?> 
           

thrift接口檔案位于/src/contrib/thriftfs/if/hadoopfs.thrift,啟動thrift服務的腳本位于/usr/local/hadoop/src/contrib/thriftfs/scripts/start_thrift_server.sh,PHP語言檔案位于/usr/local/hadoop/src/contrib/thriftfs/gen-php,包括hadoopfs_types.php  ThriftHadoopFileSystem.php兩個檔案。

hadoopfs.thrift,包括4個結構,2個異常,19個service函數。以下将分别介紹結構和函數。

開啟thrift sever的腳本如下(當然,首先應啟動hadoop):

啟動start_thrift_server.sh時可以指定啟動端口 eg:sh start_thrift_server.sh 48566  不指定則随機配置設定

啟動start_thrift_server.sh時報錯為hadoop環境配置錯誤

Exception in thread “main” java.lang.NoClassDefFoundError: org/apache/ hadoop/conf/Configuration

解決方法,将Hadoop的classpath加到環境變量中,如:

export CLASSPATH=$HADOOP_HOME"hadoop-core-1.0.4.jar"

或者直接在/etc/profile裡面加上變量的路徑  然後執行source /etc/profile讓其修改生效

如果不寫端口,則偵聽端口是随機的,無論哪種情況,注意一下啟動的輸出,其中有端口号。

補充:

單機狀态測試時 本機必須同時安裝hadoop環境和thrift

聯機狀态使用時 server機安裝hadoop環境和thrift  php項目所在的客戶機也要安裝thrift

server機啟動thrift服務 (sh start_thrift_server.sh 48566)

用戶端機器連結時  socket(ip=server機ip,port=48566,……)

聯機操作時自己遇見的問題,測試機執行時一切正常,但是聯機時卻老是報錯

exception 'TTransportException' with message 'TSocket read 0 bytes' in /root/thrift/lib/php/src/transport/TSocket.php:263

問題:最後發現是因為用戶端機器是32位系統,檔案句柄id較長,32位機器溢出,緻使write時找不到正确的檔案句柄

解決:遷移64位機器後一切正常

接口結構,如下:

  • ThriftHandle:這個東西相當于檔案句柄
  • Pathname:檔案路徑
  • FileStatus :實際上是檔案的各種屬性,包括名稱、長度、檔案/目錄、塊複制數、塊大小,權限屬性等。
  • BlockLocation :檔案塊的屬性,包括位置屬性,該塊在檔案中的偏移量,大小等。

接口service函數如下(本文thrift采用的是0.8.0):

  • setInactivityTimeoutPeriod:設定逾時時間(s),如果超過此時間,伺服器斷開。
  • shutdown:斷開與伺服器的連接配接
  • create、createFile:這兩個是建立檔案,并輸出檔案句柄供寫入,後一個函數提供了更多的檔案屬性參數來控制檔案的建立。
  • open:以讀寫方式打開一個已存在的檔案,輸出檔案句柄供操作。
  • append:以添加方式打開一個已存在的檔案,輸出為檔案句柄。
  • write:向已打開的檔案寫入資料,傳回是否成功。
  • read:向已打開的檔案讀取資料,與通常檔案讀取一樣,需指定讀取位置和讀取大小。
  • close:關閉檔案
  • rm:删除檔案或目錄,可以指定是否遞歸删除目錄
  • rename:重新命名檔案或目錄
  • mkdirs:建立目錄
  • exists:檢查檔案或目錄是否存在
  • stat:擷取檔案或目錄的屬性,輸出的是FileStatus結構。
  • listStatus:如果輸入是一個目錄,則輸出是目錄下所有檔案的FileStatus結構(數組)
  • chmod:設定檔案/目錄的權限
  • chown:設定檔案/目錄的組和所有者
  • setReplication:設定檔案的複制因子(多少份)
  • getFileBlockLocations:得到檔案的塊的資訊,輸出是BlockLocation數組。

以上這些接口除了具有複制因子、塊等資訊外,與通常的檔案操作沒有什麼差別,是以對它們進行再次封裝似乎沒有必要,除非有特殊的要求。

php操作hdfs自己用的另外一種解決方案:

在項目所在機器裝hadoop的client,并且安裝jdk,把hadoop需要的jar包放到此機器上,php直接exec去調用java,通過java指令去執行jar包,jar包内部執行hdfs操作

參考文章:

http://blog.csdn.net/guxch/article/details/12163519

http://blog.csdn.net/jiangheng0535/article/details/12089023

http://dongxicheng.org/search-engine/scribe-installation/

http://www.thinksaas.cn/group/topic/234079/

http://www.docin.com/p-473359851.html

http://blog.csdn.net/gs_zhaoyang/article/details/13503527