php通过 thrift访问hadoop的hive

作者:工程材料    来源:未知    发布时间:2019-12-18 22:41    浏览量:

4,Using Thrift with Java..在JAVA中使用Thrift,这里需要Java Thrift 库。该java Thrift库的编译非常简单:

1.简单的helloworld程序

这里使用python做服务端,php做客户端,当然也可以使用c++来做服务端。下面开始介绍开发流程。

(1)首先我们在服务器端写个helloworld.thrift文件,如下所示:

service HelloWorld{      string ping(1: string name),      string getpng(),   }

(2)在服务器端编译helloworld.thrift

编译helloworld.thrift文件,会产生服务器端和客户端相应语言的接口源码。
/usr/local/thrift/bin/thrift -r --gen py helloworld.thrift  
/usr/local/thrift/bin/thrift -r --gen php helloworld.thrift  
#会在当前目录下生成 gen-* 目录。
产生的gen-py目录放在服务器上,产生的gen-php目录放在客户端上。
(3)编写服务器端代码

    import sys       sys.path.append('./gen-py')               from helloworld import HelloWorld       from helloworld.ttypes import *               from thrift.transport import TSocket       from thrift.transport import TTransport       from thrift.protocol import TBinaryProtocol       from thrift.server import TServer               class HellowordHandler:           def __init__ (self):               pass                   def ping (self, name):               print name + ' from server.'               return "%s from server." % name           def getpng (self):               f = open("./logo.png", "rb")               c = f.read()               f.close()               return c       handler = HellowordHandler()       processor = HelloWorld.Processor(handler)       transport = TSocket.TServerSocket(9090)       tfactory = TTransport.TBufferedTransportFactory()       pfactory = TBinaryProtocol.TBinaryProtocolFactory()               server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)               # You could do one of these for a multithreaded server       #server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)       #server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)               print 'Starting the server...'       server.serve()       print 'done.'  

(4)编写客户端代码

先将gen-php目录拷贝到客户端上。

<?php   try{       //包含thrift客户端库文件       $GLOBALS['THRIFT_ROOT'] = './php/src';        require_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php';       require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php';       require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php';       require_once $GLOBALS['THRIFT_ROOT'].'/transport/THttpClient.php';       require_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';        error_reporting(E_NONE);        //包含helloworld接口文件     $GEN_DIR = './gen-php';       require_once $GEN_DIR.'/helloworld/HelloWorld.php';        error_reporting(E_ALL);           $socket = new TSocket('*.*.*.*', 9090);       $transport = new TBufferedTransport($socket, 1024, 1024);       $protocol = new TBinaryProtocol($transport);       $client = new HelloWorldClient($protocol);            $transport->open();           $a = $client->ping('xyq ');       echo $a;           $transport->close();           }catch(TException $tx){           print 'TException: '.$tx->getMessage()."/n";       }       ?>

最后给出一篇参考链接:

②安装依赖

二.创建.thrift文件

Thrift编译器安装好之后,需要创建一个thrift文件。该文件为一个接口定义文件,需要定义thrift的类型(types)和服务(services)。该文件中定义的服务(services)是由服务器端实现的,并由客户端进行调用。Thrift编译器的作用是将你写的thrift文件生成为客户端接口源码,该接口源码是由不同的客户端库和你写的服务来生成的。为了通过thrift文件产生不同语言的接口源码,我们需要运行:

thrift --gen <language> <Thrift filename>

①定义好thrift文件--Hello.thrift 并生成相应的java代码

一.服务器端下载安装thrift

在hadoop和hbase都已经安装好的集群上安装thrift。
(1)下载:wget

(2)解压:tar -xzf thrift-0.8.0.tar.gz
(3)编译安装:如果是源码编译的,首先需要执行./bootstrap.sh创建./configure文件;
接下来执行./configure;
再执行make && make install
(4)启动:./bin/hbase-daemon.sh start thrift
Thrift默认监听的端口是9090。
参考链接:

 

三.thrift文件描述

支持的变量类型

类型           描述     bool            #true, false     byte            #8位的有符号整数     i16             #16位的有符号整数     i32             #32位的有符号整数     i64             #64位的有符号整数     double          #64位的浮点数     string          #UTF-8编码的字符串     binary          #字符数组     struct          #结构体     list<type>        #有序的元素列表,类似于STL的vector     set<type>     #无序的不重复元素集,类似于STL的set     map<type1,type2>  #key-value型的映射,类似于STL的map     exception       #是一个继承于本地语言的exception基类     service         #服务包含多个函数接口(纯虚函数)
public class Hello {

  public interface Iface {

    public String helloString(String para) throws org.apache.thrift.TException;

    public int helloInt(int para) throws org.apache.thrift.TException;

  }

  public interface AsyncIface {

    public void helloString(String para, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

五.thrift类说明

TSocket:采用TCP socket进行数据传输;
Transport类(传输层):
负责数据传输,介绍几个常用类:
TBufferedTransport:对某个Transport对象操作的数据进行buffer,即从buffer中读取数据进行传输,或者将数据直接写入buffer;
TFramedTransport:同TBufferdTransport类型,也会对数据进行buffer,同时它支持定长数据发送和接受;
TFileTransport:文件(日志)传输类,允许client将文件传给server,语序server将受到的数据写到文件中;

Protocol类(协议):
负责数据编码,主要有以下几个常用类:
TBinaryProtocol:二进制编码;
TJSONProtocol:JSON编码。

版权声明:本文为博主原创文章,未经博主允许不得转载。


4,至于整个传输过程则被Thrift封装起来了--protocol 定义数据传输格式,transport 定义数据传输方式。

Thrift的官方网址:

TTransport transport = new TSocket("localhost",7911);//建立连接
            transport.open();
            TProtocol protocol = new TBinaryProtocol(transport);
            Hello.Client client = new Hello.Client(protocol);//生成客户端实例对象
            client.helloString("Hello World");//调用定义好的服务
            client.helloInt(88);//调用定义好的服务

Thrift的诞生是为了解决不同语言之间的访问的问题,可以支持多种程序语言,如c++、php、java、python等。Thrift是由facebook开发的轻量级跨语言的服务框架,现在已经移交到Apache基金会下。和它类似的有google出的protocol buffer和ice。Thrift的一大优势是支持的语言很丰富,它使用自己的IDL语言来服务接口和数据交换的格式。

奇怪的是这里报了个错误:

3.实战经历

(1).thrift接口文件

文件名为hive.thrift,如下所示:

namespace java com.gj.data.hive.thrift  /**  * 向HADOOP提交HIVE任务类。典型的用法是提交任务,轮询任务是否完成,取得任务的结果URI,读取结果文件。  *这里展示的是客户端为java语言时的用法。  *           long taskId = client.submitTask("abc@gj.com", "web", "select * from table1 where dt = '2013-04-10' limit 10;");  *           if (taskId <=0) {  *               System.out.println("error submit");  *               return;  *           }               //轮询任务是否完成  *           int count = 50;  *           while(count >= 0) {  *               try {  *                   Thread.sleep(30 * 1000);  *               } catch (InterruptedException ex) {}  *               if (client.isTaskFinished(taskId)) {  *                   System.out.println(client.getResultURI(taskId));  *                   break;  *               }   *               count --;  *          }  */  service Hive {      /** 提交任务      * user - 用户名,工作邮箱,如abc@xxx.com      * env - 提交的环境。目前支持两个环境: mobile - 移动端, web - 主站。      * sql - 提交的sql语句。      * 返回值:成功提交返回大于0的任务id值,此id用于后续查询。失败返回0或-1.      */     i64 submitTask(1:string user, 2:string env, 3:string sql);          /** 查看任务是否完成      *  taskId - 任务号      * 返回值:完成返回true,未完成返回false      */     bool isTaskFinished(1:i64 taskId);          /** 取得任务结果的URI,可以用此URI获得结果数据      *  taskId - 任务号      * 返回值:任务有结果,返回URI,否则返回空字符串      */         string getResultURI(1:i64 taskId);          /** 取得用户的所有任务列表      *  user - 用户名,完整的ganji邮箱      * 返回值:任务号列表,如果没有任务,返回空      */     list<i64> getTasksByUserName(1:string user); }

(2).生成php与hbase的接口文件(服务器端实现)

/usr/local/thrift/bin/thrift --gen php hive.thrift
然后会在gen-php目录下生成了Hive.php和Hive_types.php文件。
然后把Hive.php和Hive_types.php文件拷贝到:客户端php开发的目录下。

(3).配置php客户端

php作为客户端使用thrift时,需要进行如下配置。

(a)准备thrift php客户端基础类

这些基础类可以从thrift的源码包中找到。在thriftsrc/lib/php/src下,一班有如下目录和文件:ext/,protocol/,transport/目录,和thrift.php、autoload.php文件。我们把这些目录和文件拷贝到客户端的/server/www/thrift_part/thrift-0.5.0/目录下。

(b)配置php的thrift扩展,使其支持thrift

如果php想要使用thrift,还需要安装php的thrift扩展。
如下所示:
首先下载相应的php的thrift扩展,进行解压;
进入源码下的ext/thrift_protocol;
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config --enable-thrift_protocol
make
make install
然后把生成的thrift_protocol.so文件配置到php.ini并重启apache服务。

(4).php客户端的实现

文件名为:updateHiveData.php

<?php     $GLOBALS['THRIFT_ROOT'] = '/server/www/third_part/thrift-0.5.0';          require_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php';     require_once $GLOBALS['THRIFT_ROOT'].'/packages/scribe/scribe.php';     require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php';     require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php';     require_once $GLOBALS['THRIFT_ROOT'].'/transport/THttpClient.php';     require_once $GLOBALS['THRIFT_ROOT'].'/transport/TFramedTransport.php';     require_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';      //生成的文件     require_once dirname(__FILE__) . '/Hive.php';     //require_once dirname(__FILE__) .'/hive_types.php';          ERROR_REPORTING(E_ALL);     INI_SET('DISPLAY_ERRORS','ON');         $socket = new TSocket('hive.corp.gj.com',13080);     $socket->setDebug(TRUE);           // 设置接收超时(毫秒)     $socket->setSendTimeout(10000);     $socket->setRecvTimeout(10000);          //$transport = new TBufferedTransport($socket, 1024, 1024);     $transport = new TFramedTransport($socket);     $protocol = new TBinaryProtocol($transport);     $client = new HiveClient($protocol);          try{         $transport->open();     }catch(TException $tx){         echo $tx->getMessage();     }           //获取各个类目某一天的 PV UV     $taskId = $client->submitTask('xxx@xxx.com','web',"select regexp_extract(gjch, '^/([^/]+)', 1), count(*), count(distinct uuid) from table1 where dt = '2013-04-22' and gjch regexp '[^@]*/detail' GROUP BY regexp_extract(gjch, '^/([^/]+)', 1);");          if($taskId <= 0){  echo 'error submit';         exit;     }     echo $taskId . "n";         $count = 50;     while($count > 0){         try{             //sleep以秒为单位,这里3分钟轮询一次             sleep(3*60);         }catch(TException $tx){}    if($client->isTaskFinished($taskId)){             //echo $client->getResultURI($taskId);             $url = $client->getResultURI($taskId);             //echo $url;          $handle = fopen($url,"rb");             $content = stream_get_contents($handle);             echo $content;             fclose($handle);              break;         }         $count--;     }        $transport->close(); ?>

由于服务器端不是本人负责,所以当时只根据thrift定义文件,实现了php客户端。运行结果如下:

图片 1

其中这里url是$client->getResultURI取得的结果,网页内容是这个uri对应的内容。

参考:

本文讲解php通过sql查询hadoop中的数据。主要使用的技术是:php通过thrift向hive提交sql查询,hive将sql查询转换成hadoop任务,等到hadoop执行完毕后,返回一个结果uri,然后我们只需要读取这个uri中的内容。

service Hello{
    string helloString(1:string para)
    i32 helloInt(1:i32 para)
}

2.thrift官网上给出的例子

Apache thrift能够让你在一个简单的.thrift文件中,定义数据类型和服务接口。将该.thrift文件作为输入文件,通过编译器编译产生服务端和客户端源码,从而构建了RPC客户端和服务器端之间的跨语言编程。
下面直接给出关键代码。

(1)thrift定义文件

/*定义的接口数据类型*/ struct UserProfile {         1: i32 uid,         2: string name,         3: string blurb } /*定义的接口函数*/ service UserStorage {         void store(1: UserProfile user),         UserProfile retrieve(1: i32 uid) }

(2)客户端python实现

  # Make an object   up = UserProfile(uid=1,       name="Test User",       blurb="Thrift is great")     # Talk to a server via TCP sockets, using a binary protocol   transport = TSocket.TSocket("localhost", 9090)   transport.open()   protocol = TBinaryProtocol.TBinaryProtocol(transport)    # Use the service we already defined   service = UserStorage.Client(protocol)   service.store(up)    # Retrieve something as well   up2 = service.retrieve(2)

(3)服务器端c++实现

class UserStorageHandler : virtual public UserStorageIf {    public:     UserStorageHandler() {       // Your initialization goes here     }      void store(const UserProfile& user) {       // Your implementation goes here       printf("storen");     }      void retrieve(UserProfile& _return, const int32_t uid) {       // Your implementation goes here       printf("retrieven");     }   };    int main(int argc, char **argv) {     int port = 9090;     shared_ptr<UserStorageHandler> handler(new UserStorageHandler());     shared_ptr<TProcessor> processor(new UserStorageProcessor(handler));     shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));     shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());     shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());     TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);     server.serve(); }

②编写HelloServiceImpl接口实现thrift文件中定义的服务

四.从服务端到客户端如何开发

./configure && make && make install

Hive是可以使用类似sql的语言访问HBase。而HBase是一个开源的nosql产品,它实现了google bigtable论文的一个开源产品,和hadoop、hdfs一起,可以用来存储和处理海量column family数据。

3,在/usr/lcoal/thrift-0.9.2/运行如下命令:

生成的java部分代码如下:

TServerSocket serverTransport = new TServerSocket(7911);//设置服务器端口
            Factory proFactory = new TBinaryProtocol.Factory();//设置协议工厂
            TProcessor processor = new Hello.Processor<Hello.Iface>(new HelloServiceImpl());//关联处理器与Hello.thrift文件中定义的服务的实现
            TServer.Args tArgs = new TServer.Args(serverTransport);
            tArgs.processor(processor);
            tArgs.protocolFactory(proFactory);

            TServer server = new TSimpleServer(tArgs);
            System.out.println("Start server on port 7911");
            server.serve();

在/usr/lcoal/thrift-0.9.2/lib/java/ 下运行 ant 即可,生成了一个libthrift-0.9.2.jar文件,就可以把该jar包导入到java工程中作为Thrift for java的依赖包了。

①下载安装包并解压,假设解压到/usr/lcoal/thrift-0.9.2/

sudo apt-get install libboost-dev libboost-test-dev libboost-program-options-dev libboost-system-dev libboost-filesystem-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev

 ⑤总结:

 

1,环境:Ubuntu12.04   thrift-0.9.2。安装:

import org.apache.thrift.TException;

public class HelloServiceImpl implements Hello.Iface{
    public String helloString(String para) throws TException {
        return para;
    }
    public int helloInt(int para) throws TException {
        try{
            Thread.sleep(2000);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        return para;
    }
}

参考:

补充一下:在由Thrift IDL语言定义好**.thrift 文件,运行 thrift --gen java **.thrift 就可以生成相应的JAVA文件。把该JAVA文件导入到JAVA工程中,还需要slf4j-api-1.5.8.jar 、slf4j-log4j12-1.5.8.jar 、log4j-1.2.14.jar

③编写服务器端程序,部分代码如下:

thrift-t_gv_generator.o: file not recognized: File truncated
collect2: ld returned 1 exit status
make[3]: *** [thrift] 错误 1
make[3]:正在离开目录 `/usr/local/thrift-0.9.2/compiler/cpp'

5,Thrift for java 之 eclipse编程实例

参考:

④编写客户端程序

1,使用IDL语言写好接口定义thrift文件,该文件指明了服务器端提供的各种服务。2,通过thrift --gen java/c++/py/... <thrift file> 生成相应语言的代码。

3,用户实现具体的服务--服务器端程序、客户端程序。。。客户端调用服务,服务器端提供服务。

找到出错的文件,发现它的大小为0,然后直接把它移除,再重新运行第 3 步中的命令。安装成功。

前言:由于最近在看storm Topology提交过程的源代码,写好的topology jar文件是通过Thrift RPC的形式提交给nimbus的。故了解下Thrift的基本原理。

thrift文件如下:

上一篇:时光掩伤城

相关新闻推荐

友情链接: 网站地图
Copyright © 2015-2019 http://www.kai-wang.com. AG亚游国际有限公司 版权所有