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 co妹妹and 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支持),主动剔除了有效的效劳器
开发流程
一、界说IDL(Interface description language)接口形容文件,后缀.thrift
IDL标准:http://thrift.apache.org/docs/idl
thrift types:http://thrift.apache.org/docs/types
二、效劳端代码开发
三、客户端编写接入代码
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 co妹妹ent, } 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 tutorial\php; ini_set('display_errors',1); error_reporting(E_ALL); // 引入类主动加载文件 require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php'; // 载入主动加载类 use Thrift\ClassLoader\ThriftClassLoader; // 界说依据.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 Thrift\Protocol\TBinaryProtocol; // 二进制格局打包解包 use Thrift\Transport\TPhpStream; // php流输出输入 use Thrift\Transport\TBufferedTransport; // 应用缓存 // 开端效劳端逻辑 class CalculatorHandler implements \tutorial\CalculatorIf { 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, \tutorial\Work $w) { error_log("calculate({$logid}, {{$w->op}, {$w->num1}, {$w->num2}})"); switch ($w->op) { case \tutorial\Operation::ADD: $val = $w->num1 + $w->num2; break; case \tutorial\Operation::SUBTRACT: $val = $w->num1 - $w->num2; break; case \tutorial\Operation::MULTIPLY: $val = $w->num1 * $w->num2; break; case \tutorial\Operation::DIVIDE: if ($w->num2 == 0) { $io = new \tutorial\InvalidOperation(); $io->whatOp = $w->op; $io->why = "Cannot divide by 0"; throw $io; } $val = $w->num1 / $w->num2; break; default: $io = new \tutorial\InvalidOperation(); $io->whatOp = $w->op; $io->why = "Invalid Operation"; throw $io; } $log = new \shared\SharedStruct(); $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 \shared\SharedStruct(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 "\r\n"; } $handler = new CalculatorHandler(); $processor = new \tutorial\CalculatorProcessor($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 tutorial\php; error_reporting(E_ALL); require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php'; use Thrift\ClassLoader\ThriftClassLoader; $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 Thrift\Protocol\TBinaryProtocol; use Thrift\Transport\TSocket; use Thrift\Transport\THttpClient; use Thrift\Transport\TBufferedTransport; use Thrift\Exception\TException; // 以上设置装备摆设跟效劳端相似 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 \tutorial\CalculatorClient($protocol); $transport->open(); $client->ping(); print "ping()\n"; $sum = $client->add(1,1); print "1+1=$sum\n"; // 调试异样状况 $work = new \tutorial\Work(); $work->op = \tutorial\Operation::DIVIDE; $work->num1 = 1; $work->num2 = 0; try { $client->calculate(1, $work); print "Whoa! We can divide by zero?\n"; } catch (\tutorial\InvalidOperation $io) { print "InvalidOperation: $io->why\n"; } $work->op = \tutorial\Operation::SUBTRACT; $work->num1 = 15; $work->num2 = 10; $diff = $client->calculate(1, $work); print "15-10=$diff\n"; $log = $client->getStruct(1); print "Log: $log->value\n"; $transport->close(); } catch (TException $tx) { print 'TException: '.$tx->getMessage()."\n"; }
输入:
// php client.php --http ping() 1+1=2 InvalidOperation: Cannot divide by 0 15-10=5 Log: PHP is stateless!
以上就是对于php应用thrift做效劳端开发的那些事的具体内容,更多请存眷资源魔其它相干文章!
标签: php php开发教程 php开发资料 php开发自学 thrift
抱歉,评论功能暂时关闭!