问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

用php怎么写thrift接口

发布网友 发布时间:2022-04-06 00:37

我来回答

2个回答

懂视网 时间:2022-04-06 04:59

php使用thrift做服务端开发

thrift采用接口描述语言定义和创建服务,用二进制格式传输数据,体积更小、效率更高,对于高并发、数据量大和多语言的环境有更好的支持。

Apache Thrift是啥?

Apache Thrift是FaceBook开发的一套可扩展的、跨语言的服务调用框架。简单的说就是先定义一个配置文件,不同的语言可以利用thrift基于这个配置文件生成各自语言的服务端,不管客户端用什么语言,都可以调用,也就是说基于thrift协议用java可以调用php的服务。目前支持C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi等语言之间相互调用。

相对于传统的xml和json等数据传输方式来说,thrift采用接口描述语言定义和创建服务,用二进制格式传输数据,体积更小、效率更高,对于高并发、数据量大和多语言的环境有更好的支持。

thrift安装环境要求

  • g++ 4.2

  • boost 1.53.0

  • lex and yacc(基于flex和bison)

  • 如果没安装lex和yacc的话要先安装,否则会make失败,提示lex和yacc command not found错误(一般的机器貌似都没安,Ubuntu用apt-get install flex bision即可)。

    安装thrift

    下载最新版thrift:

    wget http://www.apache.org/dyn/closer.cgi?path=/thrift/0.9.3/thrift-0.9.3.tar.gz
    tar xvf thrift-0.9.3.tar.gz
    cd thrift-0.9.3

    2.创建configure文件

    // 创建./configure文件
    ./bootstrap.sh
    // 配置并安装
    ./configure
    make
    // 检测是否有问题,如果机子没有安装python和java等可能会报错,不过本文主要讲php,安了php环境就行
    make check
    make install

    编译选项

  • 使用./configure --help可以查看选项

  • 如果想禁用某个语言,可以用./configure --without-java

  • thrift for php安装环境要求

  • php版本>5.0,因为TBinaryProtocol协议用到了pack()和unpack()函数来序列化数据

  • 需要安装APC扩展,因为TSocketPool这个类用到了apc_fetch()和apc_store()函数进行apc缓存操作。

  • php使用thrift的时候,除了要将thrift/lib/php/lib里的基础文件copy到项目目录下,还需要将根据配置文件生成的php文件也copy到packages文件夹下,并引入到项目中,这个后续会详细讲。

    类库说明

    数据传输格式(protocol)

    定义的了传输内容,对Thrift Type的打包解包,包括:

  • TBinaryProtocol,二进制格式,TBinaryProtocolAccelerated则是依赖于thrift_protocol扩展的快速打包解包。

  • TCompactProtocol,压缩格式

  • TJSONProtocol,JSON格式

  • TMultiplexedProtocol,利用前三种数据格式与支持多路复用协议的服务端(同时提供多个服务,TMultiplexedProcessor)交互

  • 数据传输方式(transport)

    定义了如何发送(write)和接收(read)数据,包括:

  • TBufferedTransport,缓存传输,写入数据并不立即开始传输,直到刷新缓存。

  • TSocket,使用socket传输

  • TFramedTransport,采用分块方式进行传输,具体传输实现依赖其他传输方式,比如TSocket

  • TCurlClient,使用curl与服务端交互

  • THttpClient,采用stream方式与HTTP服务端交互

  • TMemoryBuffer,使用内存方式交换数据

  • TPhpStream,使用PHP标准输入输出流进行传输

  • TNullTransport,关闭数据传输

  • TSocketPool在TSocket基础支持多个服务端管理(需要APC支持),自动剔除无效的服务器

  • 开发流程

    1、定义IDL(Interface description language)接口描述文件,后缀.thrift

    IDL规范:http://thrift.apache.org/docs/idl

    thrift types:http://thrift.apache.org/docs/types

    2、服务端代码开发

    3、客户端编写接入代码

    IDL:
    1.tutorial.thrift

    include "shared.thrift"
    namespace php tutorial
    typedef i32 MyInteger
    const i32 INT32CONSTANT = 9853
    const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}
    enum Operation {
     ADD = 1,
     SUBTRACT = 2,
     MULTIPLY = 3,
     DIVIDE = 4
    }
    struct Work {
     1: i32 num1 = 0,
     2: i32 num2,
     3: Operation op,
     4: optional string comment,
    }
    exception InvalidOperation {
     1: i32 whatOp,
     2: string why
    }
    service Calculator extends shared.SharedService {
     void ping(),
     i32 add(1:i32 num1, 2:i32 num2),
     i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),
     oneway void zip()
    }

    2.shared.thrift

    namespace php shared
    struct SharedStruct {
     1: i32 key
     2: string value
    }
    service SharedService {
     SharedStruct getStruct(1: i32 key)
    }

    php服务端

    <?php
    namespace tutorialphp;
    ini_set('display_errors',1);
    error_reporting(E_ALL);
    // 引入类自动加载文件
    require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php';
    // 载入自动加载类
    use ThriftClassLoaderThriftClassLoader;
    // 定义根据.thrift文件生成的php文件
    $GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php';
    // 注册thrift服务
    $loader = new ThriftClassLoader();
    $loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib');
    $loader->registerDefinition('shared', $GEN_DIR);
    $loader->registerDefinition('tutorial', $GEN_DIR);
    $loader->register();
    if (php_sapi_name() == 'cli') {
     ini_set("display_errors", "stderr");
    }
    use ThriftProtocolTBinaryProtocol; // 二进制格式打包解包
    use ThriftTransportTPhpStream; // php流输入输出
    use ThriftTransportTBufferedTransport; // 使用缓存
    // 开始服务端逻辑
    class CalculatorHandler implements 	utorialCalculatorIf {
     protected $log = array();
     public function ping() {
     error_log("ping()");
     }
     // 相加
     public function add($num1, $num2) {
     error_log("add({$num1}, {$num2})");
     return $num1 + $num2;
     }
     // 枚举计算类型
     public function calculate($logid, 	utorialWork $w) {
     error_log("calculate({$logid}, {{$w->op}, {$w->num1}, {$w->num2}})");
     switch ($w->op) {
     case 	utorialOperation::ADD:
     $val = $w->num1 + $w->num2;
     break;
     case 	utorialOperation::SUBTRACT:
     $val = $w->num1 - $w->num2;
     break;
     case 	utorialOperation::MULTIPLY:
     $val = $w->num1 * $w->num2;
     break;
     case 	utorialOperation::DIVIDE:
     if ($w->num2 == 0) {
      $io = new 	utorialInvalidOperation();
      $io->whatOp = $w->op;
      $io->why = "Cannot divide by 0";
      throw $io;
     }
     $val = $w->num1 / $w->num2;
     break;
     default:
     $io = new 	utorialInvalidOperation();
     $io->whatOp = $w->op;
     $io->why = "Invalid Operation";
     throw $io;
     }
     $log = new sharedSharedStruct();
     $log->key = $logid;
     $log->value = (string)$val;
     $this->log[$logid] = $log;
     return $val;
     }
     public function getStruct($key) {
     error_log("getStruct({$key})");
     // This actually doesn't work because the PHP interpreter is
     // restarted for every request.
     //return $this->log[$key];
     return new sharedSharedStruct(array("key" => $key, "value" => "PHP is stateless!"));
     }
     public function zip() {
     error_log("zip()");
     }
    };
    header('Content-Type', 'application/x-thrift');
    if (php_sapi_name() == 'cli') {
     echo "
    ";
    }
    $handler = new CalculatorHandler();
    $processor = new 	utorialCalculatorProcessor($handler);
    // 客户端和服务端在同一个输入输出流上
    //1) cli 方式:php Client.php | php Server.php 
    //2) cgi 方式:利用Apache或nginx监听http请求,调用php-fpm处理,将请求转换为PHP标准输入输出流
    $transport = new TBufferedTransport(new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W));
    $protocol = new TBinaryProtocol($transport, true, true);
    $transport->open();
    $processor->process($protocol, $protocol);
    $transport->close();
    //作为cli方式运行,非阻塞方式监听,基于libevent实现,非官方实现
    //$transportFactory = new TBufferedTransportFactory();
    //$protocolFactory = new TBinaryProtocolFactory(true, true);
    //$transport = new TNonblockingServerSocket('localhost', 9090);
    //$server = new TNonblockingServer($processor, $transport, $transportFactory, $transportFactory, $protocolFactory, $protocolFactory);
    //$server->serve();
    //作为cli方式运行,监听端口,官方实现
    //$transportFactory = new TBufferedTransportFactory();
    //$protocolFactory = new TBinaryProtocolFactory(true, true);
    //$transport = new TServerSocket('localhost', 9090);
    //$server = new TSimpleServer($processor, $transport, $transportFactory, $transportFactory, $protocolFactory, $protocolFactory);
    //$server->serve();

    php客户端

    <?php
    namespace tutorialphp;
    error_reporting(E_ALL);
    require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php';
    use ThriftClassLoaderThriftClassLoader;
    $GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php';
    $loader = new ThriftClassLoader();
    $loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib');
    $loader->registerDefinition('shared', $GEN_DIR);
    $loader->registerDefinition('tutorial', $GEN_DIR);
    $loader->register();
    use ThriftProtocolTBinaryProtocol;
    use ThriftTransportTSocket;
    use ThriftTransportTHttpClient;
    use ThriftTransportTBufferedTransport;
    use ThriftExceptionTException;
    // 以上配置跟服务端类似
    try {
     if (array_search('--http', $argv)) {
     // 使用http方式连接
     $socket = new THttpClient('localhost', 8080, '/php/PhpServer.php');
     } else {
     // 使用socket连接
     $socket = new TSocket('localhost', 9090);
     }
     $transport = new TBufferedTransport($socket, 1024, 1024);
     $protocol = new TBinaryProtocol($transport);
     $client = new 	utorialCalculatorClient($protocol);
     $transport->open();
     $client->ping();
     print "ping()
    ";
     $sum = $client->add(1,1);
     print "1+1=$sum
    ";
     // 调试异常情况
     $work = new 	utorialWork();
     $work->op = 	utorialOperation::DIVIDE;
     $work->num1 = 1;
     $work->num2 = 0;
     try {
     $client->calculate(1, $work);
     print "Whoa! We can divide by zero?
    ";
     } catch (	utorialInvalidOperation $io) {
     print "InvalidOperation: $io->why
    ";
     }
     $work->op = 	utorialOperation::SUBTRACT;
     $work->num1 = 15;
     $work->num2 = 10;
     $diff = $client->calculate(1, $work);
     print "15-10=$diff
    ";
     $log = $client->getStruct(1);
     print "Log: $log->value
    ";
     $transport->close();
    } catch (TException $tx) {
     print 'TException: '.$tx->getMessage()."
    ";
    }

    输出:

    // php client.php --http
    ping()
    1+1=2
    InvalidOperation: Cannot divide by 0
    15-10=5
    Log: PHP is stateless!

    热心网友 时间:2022-04-06 02:07

    <?php
    interface Person {
    function sing();
    function move();
    }

    class Student implements Person {
    function sing() {
    echo "Student sings";
    }

    function move() {
    echo "Student moves";
    }
    }
    ?>
    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    ...时间会发作,很痛的,请问是这样吗?会痛多久? ...已经坏了,如今全身浮肿,尿排不出,医生说就这 我爷爷得了肝癌晚期,腹水,不能手术.听说氩氦超冷刀技术能治.哪里有... 父亲59岁得了肝癌晚期,医生说最多半年时间了,上面还有80多岁的爷爷... 长春跑大连的列车员,怎么区分正式分和临时工呢? 员工刚怀孕就被开除,开除负责人拒不认错,你如何看待该公司的态度?_百 ... 员工在职期间怀孕,老板可以无故迟退吗? 老板开除怀孕女员工违法吗 如何选购蚊帐 什么样的蚊帐最好 在php中thrift怎么用 有使用Thrift开发Service服务的吗,有什么要注意的 php中echo json_encode输出的格式为什么有的带[],有的不带? php使用json_encode把二维数组变为json格式,Javascrpt如何变回数组 php中json_encode转码问题 java对String进行json编码 实现类似与PHP中json_encode 方法的功能 php的json_encode如何让中文不要编码保持原始值? php的json_encode函数如何编码数组中的数组? php 中 json_encode 只保留 value 如何在PHP中解析json php中json_encode参数为true什么意思 如:json_decode($data,true); PHP数组通过json_encode为字符串存入数据库,再从数据库取出来json_decode还是json码 如何在PHP中返回Json数据 PHP json_encode 变量如何转换成数组? php使用json_encode将数据库里的整张表转成json格式的问题 php中json_encode中文不进行unicode编码 如何正确运用PHP json_encode函数进行中文转换? 在PHP使用json_encode 如何设置background大小 body background=定义的背景图片如何居中? thrift java有什么特点 thrift 0.9.1升级单端口多接口服务,那么php怎么实现调用 要测试thrift接口,有没有thrift客户端调用工具 thrift php能在nginx下用吗 如何自己开发一套服务器管理系统 如何用ruby搭建thrift服务 php 操作hbase除了thrift还有别的办法么 php全角转半角。。求助,有两个字居然会神奇的乱码! php全角转换半角问题求助 php 全角转半角 全角输入后的数字如何转成半角的格式 如何将输入的全角数字转换成半角并保存到数据库(pb) 如何把全角的数字变成半角的数字~~急急 如何将文本中的全角字母转换为半角? 如何将文章当中的全角字符转换成半角字符 怎么实现全角字符转换到半角字符 php如何判断是字符串全角还是半角 SQL语言。请教一下,如何将一个库中的所有全角数字转换为半角数字。 请教Laravel eloquent model一对多关联关 laravel 关联模型与联表查询哪种效率高?