站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        關(guān)于php使用thrift做服務(wù)端開發(fā)的那些事

        php使用thrift做服務(wù)端開發(fā)

        thrift采用接口描述語言定義和創(chuàng)建服務(wù),用二進(jìn)制格式傳輸數(shù)據(jù),體積更小、效率更高,對于高并發(fā)、數(shù)據(jù)量大和多語言的環(huán)境有更好的支持。

        Apache Thrift是啥?

        Apache Thrift是FaceBook開發(fā)的一套可擴(kuò)展的、跨語言的服務(wù)調(diào)用框架。簡單的說就是先定義一個(gè)配置文件,不同的語言可以利用thrift基于這個(gè)配置文件生成各自語言的服務(wù)端,不管客戶端用什么語言,都可以調(diào)用,也就是說基于thrift協(xié)議用java可以調(diào)用php的服務(wù)。目前支持C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi等語言之間相互調(diào)用。

        相對于傳統(tǒng)的xml和json等數(shù)據(jù)傳輸方式來說,thrift采用接口描述語言定義和創(chuàng)建服務(wù),用二進(jìn)制格式傳輸數(shù)據(jù),體積更小、效率更高,對于高并發(fā)、數(shù)據(jù)量大和多語言的環(huán)境有更好的支持。

        thrift安裝環(huán)境要求

        • g++ 4.2

        • boost 1.53.0

        • lex and yacc(基于flex和bison)

        如果沒安裝lex和yacc的話要先安裝,否則會(huì)make失敗,提示lex和yacc command not found錯(cuò)誤(一般的機(jī)器貌似都沒安,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.創(chuàng)建configure文件

        // 創(chuàng)建./configure文件 ./bootstrap.sh // 配置并安裝 ./configure make // 檢測是否有問題,如果機(jī)子沒有安裝python和java等可能會(huì)報(bào)錯(cuò),不過本文主要講php,安了php環(huán)境就行 make check make install

        編譯選項(xiàng)

        • 使用./configure –help可以查看選項(xiàng)

        • 如果想禁用某個(gè)語言,可以用./configure –without-java

        thrift for php安裝環(huán)境要求

        • php版本>5.0,因?yàn)門BinaryProtocol協(xié)議用到了pack()和unpack()函數(shù)來序列化數(shù)據(jù)

        • 需要安裝APC擴(kuò)展,因?yàn)門SocketPool這個(gè)類用到了apc_fetch()和apc_store()函數(shù)進(jìn)行apc緩存操作。

        php使用thrift的時(shí)候,除了要將thrift/lib/php/lib里的基礎(chǔ)文件copy到項(xiàng)目目錄下,還需要將根據(jù)配置文件生成的php文件也copy到packages文件夾下,并引入到項(xiàng)目中,這個(gè)后續(xù)會(huì)詳細(xì)講。

        類庫說明

        數(shù)據(jù)傳輸格式(protocol)

        定義的了傳輸內(nèi)容,對Thrift Type的打包解包,包括:

        • TBinaryProtocol,二進(jìn)制格式,TBinaryProtocolAccelerated則是依賴于thrift_protocol擴(kuò)展的快速打包解包。

        • TCompactProtocol,壓縮格式

        • TJSONProtocol,JSON格式

        • TMultiplexedProtocol,利用前三種數(shù)據(jù)格式與支持多路復(fù)用協(xié)議的服務(wù)端(同時(shí)提供多個(gè)服務(wù),TMultiplexedProcessor)交互

        數(shù)據(jù)傳輸方式(transport)

        定義了如何發(fā)送(write)和接收(read)數(shù)據(jù),包括:

        • TBufferedTransport,緩存?zhèn)鬏敚瑢懭霐?shù)據(jù)并不立即開始傳輸,直到刷新緩存。

        • TSocket,使用socket傳輸

        • TFramedTransport,采用分塊方式進(jìn)行傳輸,具體傳輸實(shí)現(xiàn)依賴其他傳輸方式,比如TSocket

        • TCurlClient,使用curl與服務(wù)端交互

        • THttpClient,采用stream方式與HTTP服務(wù)端交互

        • TMemoryBuffer,使用內(nèi)存方式交換數(shù)據(jù)

        • TPhpStream,使用PHP標(biāo)準(zhǔn)輸入輸出流進(jìn)行傳輸

        • TNullTransport,關(guān)閉數(shù)據(jù)傳輸

        • TSocketPool在TSocket基礎(chǔ)支持多個(gè)服務(wù)端管理(需要APC支持),自動(dòng)剔除無效的服務(wù)器

        開發(fā)流程

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

        IDL規(guī)范:http://thrift.apache.org/docs/idl

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

        2、服務(wù)端代碼開發(fā)

        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服務(wù)端

        <?php namespace tutorialphp; ini_set('display_errors',1); error_reporting(E_ALL); // 引入類自動(dòng)加載文件 require_once __DIR__.'/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php'; // 載入自動(dòng)加載類 use ThriftClassLoaderThriftClassLoader; // 定義根據(jù).thrift文件生成的php文件 $GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php'; // 注冊thrift服務(wù) $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; // 二進(jìn)制格式打包解包 use ThriftTransportTPhpStream; // php流輸入輸出 use ThriftTransportTBufferedTransport; // 使用緩存 // 開始服務(wù)端邏輯 class CalculatorHandler implements tutorialCalculatorIf {   protected $log = array();   public function ping() {     error_log("ping()");   }   // 相加   public function add($num1, $num2) {     error_log("add({$num1}, {$num2})");     return $num1 + $num2;   }   // 枚舉計(jì)算類型   public function calculate($logid, tutorialWork $w) {     error_log("calculate({$logid}, {{$w->op}, {$w->num1}, {$w->num2}})");     switch ($w->op) {       case tutorialOperation::ADD:         $val = $w->num1 + $w->num2;         break;       case tutorialOperation::SUBTRACT:         $val = $w->num1 - $w->num2;         break;       case tutorialOperation::MULTIPLY:         $val = $w->num1 * $w->num2;         break;       case tutorialOperation::DIVIDE:         if ($w->num2 == 0) {           $io = new tutorialInvalidOperation();           $io->whatOp = $w->op;           $io->why = "Cannot divide by 0";           throw $io;         }         $val = $w->num1 / $w->num2;         break;       default:         $io = new tutorialInvalidOperation();         $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 "rn"; } $handler = new CalculatorHandler(); $processor = new tutorialCalculatorProcessor($handler); // 客戶端和服務(wù)端在同一個(gè)輸入輸出流上 //1) cli 方式:php Client.php | php Server.php  //2) cgi 方式:利用Apache或nginx監(jiān)聽http請求,調(diào)用php-fpm處理,將請求轉(zhuǎn)換為PHP標(biāo)準(zhǔn)輸入輸出流 $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方式運(yùn)行,非阻塞方式監(jiān)聽,基于libevent實(shí)現(xiàn),非官方實(shí)現(xiàn) //$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方式運(yùn)行,監(jiān)聽端口,官方實(shí)現(xiàn) //$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; // 以上配置跟服務(wù)端類似 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 tutorialCalculatorClient($protocol);   $transport->open();   $client->ping();   print "ping()n";   $sum = $client->add(1,1);   print "1+1=$sumn";   // 調(diào)試異常情況   $work = new tutorialWork();   $work->op = tutorialOperation::DIVIDE;   $work->num1 = 1;   $work->num2 = 0;   try {     $client->calculate(1, $work);     print "Whoa! We can divide by zero?n";   } catch (tutorialInvalidOperation $io) {     print "InvalidOperation: $io->whyn";   }   $work->op = tutorialOperation::SUBTRACT;   $work->num1 = 15;   $work->num2 = 10;   $diff = $client->calculate(1, $work);   print "15-10=$diffn";   $log = $client->getStruct(1);   print "Log: $log->valuen";   $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!

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
        主站蜘蛛池模板: 免费欧美精品a在线| 久久国产热这里只有精品| 久久99热这里只有精品国产| 2018国产精华国产精品| 亚洲国产精品不卡毛片a在线| 亚洲国产精品自在线一区二区| 精品无码一区二区三区爱欲| 亚州日韩精品专区久久久| 成人精品一区二区久久久| 国产精品福利一区二区| 欧美成人精品高清在线观看| 日韩精品成人a在线观看| 国产精品亚洲综合一区| 无码精品一区二区三区免费视频 | 久久精品人人做人人爽电影| 人妻熟妇乱又伦精品视频| 一区二区日韩国产精品| 久久久久国产精品麻豆AR影院 | freesexvideos精品老师毛多| 亚洲精品国产高清嫩草影院| 久久e热在这里只有国产中文精品99 | 99re这里只有精品热久久| 国产欧美亚洲精品A| 久久66热人妻偷产精品9| 精品无人码麻豆乱码1区2区| 国自产偷精品不卡在线| 国产精品亚洲片在线观看不卡| 久久香蕉国产线看观看精品yw| 无码人妻精品一区二区三区在线 | 久久精品国产91久久麻豆自制| 国产精品99久久久久久人| 国产成人精品无码片区在线观看 | 国产精品一级毛片无码视频| 隔壁老王国产在线精品| 国产一级精品高清一级毛片| 精品露脸国产偷人在视频| 精品久久久久久国产牛牛app| 美女岳肉太深了使劲国产精品亚洲专一区二区三区 | 无码人妻精品中文字幕| 无码人妻精品一区二区三区在线| 亚洲精品国产av成拍色拍|