PHP使用thrift做服務端開發

2021-03-02 php中文網最新課程

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安裝環境要求

如果沒安裝lex和yacc的話要先安裝,否則會make失敗,提示lex和yacc command not found錯誤(一般的機器貌似都沒安,Ubuntu用apt-get install flex bision即可)。

安裝thrift

1.下載最新版thrift:

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

2.創建configure文件

./bootstrap.sh./configuremakemake checkmake install

編譯選項

thrift for php安裝環境要求

php使用thrift的時候,除了要將thrift/lib/php/lib裡的基礎文件copy到項目目錄下,還需要將根據配置文件生成的php文件也copy到packages文件夾下,並引入到項目中,這個後續會詳細講。

類庫說明

數據傳輸格式(protocol)

定義的了傳輸內容,對Thrift Type的打包解包,包括:

數據傳輸方式(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 tutorialtypedef i32 MyIntegerconst i32 INT32CONSTANT = 9853const 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 sharedstruct SharedStruct {  1: i32 key  2: string value}service SharedService {  SharedStruct getStruct(1: i32 key)}

php服務端

<?phpnamespace 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;$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();if (php_sapi_name() == 'cli') {  ini_set("display_errors", "stderr");}use Thrift\Protocol\TBinaryProtocol; use Thrift\Transport\TPhpStream; 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})");                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);$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();

php客戶端

<?phpnamespace 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)) {      $socket = new THttpClient('localhost', 8080, '/php/PhpServer.php');  } else {        $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";}

輸出:

ping()1+1=2InvalidOperation: Cannot divide by 015-10=5Log: PHP is stateless!


相關焦點

  • Thrift-簡單使用
    Apache Thrift是一個軟體框架,用來進行可擴展跨語言的服務開發,結合了軟體堆棧和代碼生成引擎,用來構建C++,Java,Python...等語言,使之它們之間無縫結合、高效服務。安裝brew install thrift作用跨語言調用,打破不同語言之間的隔閡。跨項目調用,微服務的麼麼噠。
  • 記一次內存溢出的分析經歷,thrift帶給我的痛
    背景:有一個項目做一個系統,分客戶端和服務端,客戶端用c++寫的,用來收集信息然後傳給服務端(客戶端的數量還是比較多的,正常的有幾千個),服務端用Java寫的(帶管理頁面),屬於RPC模式,中間的通信框架使用的是thrift。
  • 從Thrift到I/O多路復用
    Thrift是一個輕量級、跨語言的遠程服務調用框架,支持C++、Java、Python、PHP、Ruby等。通過代碼生成引擎自動生成RPC接口Thrift IDL文件對應的各種主流語言的RPC服務端/客戶端模板代碼,省去自定義和維護接口編解碼、消息傳輸、伺服器多線程模型等基礎工作,服務端只需要編寫接口實現類,客戶端根據服務對象調用遠端服務。
  • grpc的Go服務端和PHP客戶端實現
    grpc四種服務類型:1、簡單方式:這就是一般的rpc調用,一個請求對象對應一個返回對象2、服務端流式(Sever-side streaming )3、客戶端流式(Client-side streaming RPC)4、雙向流式(Bidirectional streaming
  • 開發直播App從服務端到客戶端的應用
    直播的技術層:直播變得越來越流行,很多的直播平臺也應運而生,直播是一個很有技術的項目,從服務端到客戶端到web等等。介紹包括服務端技術和客戶端技術。包括最簡單的服務端環境部署、客戶端編譯、採集、推流、拉流、美化特效、水印、延時優化、音視頻同步、p2p等等。還有就是一些信號處理的知識,比如濾波,傅立葉變換(FFT)。
  • PHP開發環境搭建工具有哪些?
    對於php開發小白來說搭建一個php運行環境就是一道坎!因為要做php開發,搭建一個能夠運行php網站的伺服器環境是第一步,傳統的php環境軟體非常複雜,好在很多公司開發了一鍵搭建php安裝環境,一鍵進行php環境配置,大大節省了搭建php mysql環境的時間!對老手來說安裝配置php環境也不再是一件煩瑣的事。
  • php極速後臺開發框架,快速開發後臺管理系統,提升開發效率
    今天給大家分享一個php後臺開發框架,使用這個框架可以快速提升後臺開發效率,小編我也是在使用的哦,特別適合接外包項目使用!這個框架就是——fastadmin,官網地址:https://www.fastadmin.net/。
  • 基於Netty的高性能RPC框架Nifty 服務端啟動全解析
    這款框架很輕量,即不提供服務治理的功能。如果公司規模不大急需做功能,暫時沒精力去做服務治理的話可能還是會選擇dubbo等帶服務治理功能的rpc框架。但是恰恰是thrift不提供服務治理,這樣公司可以自己去定義服務治理的功能。
  • 做彩票系統源碼開發用php和java兩個語言間的區別
    彩票行業進入我國已經幾十年了,隨著時間的沉澱,也是發展起來了,也有投資者看中了彩票行業的前景想要做彩票系統源碼開發,而像是php與java是目前非常主流的兩個語言,對於系統開發也是需要做選擇的,且也是經常會在開發web應用時發生分歧,開發前很多外包團隊肯定會問你,是用java開發還是
  • 交友直播APP源碼開發中,服務端與客戶端的環境搭建
    服務端與客戶端的區別是什麼?簡單地說:一般客戶端負責和用戶的交互,也就是屏幕顯示(UI/UE),服務端負責數據存儲,也就是你的用戶數據,而計算能力,客戶端和服務端一般各負責一部分。1、服務端在部署服務端環境其實包含很多東西的,最常用的web服務nginx,資料庫Mysql、Nosql,api開發最多的三種選擇:java環境,需要jdk,tomcat/jbossphp環境,需要安裝php,odplua環境,需要安裝lua、luajit考慮使用緩存技術,則主要包含redis和memcached。
  • php直播源碼開發優勢以及提高系統承載量和伺服器選擇詳解
    節省開發成本php是開源腳本語言,免費是它的優勢,搭配同樣開源免費的Linux系統和Redis、Mysql,能夠為開發者節省不少的開發成本。2. 具有可移植性能php直播源碼移植性強,可以支持很多的作業系統和資料庫系統,選擇性也是比較大的,只不過採用php語言開發直播系統Web端時,Mysql是常用資料庫。3.
  • 俯瞰 Java 服務端開發
    ,無數的服務基於其開發,它整合了服務端開發所需的絕大多數組件,Spring Boot 在其基礎上又做了一層輕封裝並簡化了依賴管理,使得它用起來更加的便捷。在服務端開發方面,MySQL 的市場佔用率是最高的,但也推薦學習一下 PostgreSQL 和所謂的「企業級資料庫」,畢竟 MySQL 在這些資料庫面前有時確實顯得功能簡單、實用性不足。在真實的工作中,資料庫的設計是一個非常需要平衡取捨的過程,有時為了優化查詢性能不得不做一些數據冗餘,而在數據量極大的情況下,又必須謹慎選擇每一列的存儲類型、避免冗餘。
  • polarphp 0.0.1 alpha 發布:全新 PHP 運行時環境
    簡單來說polarphp之於PHP語言的關係跟NodeJS之於Javascript語言一樣,NodeJS在v8引擎基礎之上進行打造,為Javascript提供了一個在服務端運行的環境。同樣polarphp也在zend engine的基礎上進行打造,實現了一個除Web開發之外的一個全新的運行環境。
  • php工作原理是什麼?php常用功能有哪些?
    Php是超文本預處理器(Hypertext Preprocessor)英文全稱首字母的縮寫,php從1995年發展到現在現在已經成為流行開發動態網站的程序開源伺服器端語言。它融合了c、java、perl語言一些好的特點成為網站開發最佳的工具。
  • php開發擴展的三種方式
    作為世界上最好的語言,php有著非常靈活的語法,它的靈活甚至有時候讓你摸不到頭腦,函數的命名不規範遭到了很多人的批評,然而這些並不能阻止它的發展。沒有一種語言從設計之初就可以做所有事情,因此我們需要不斷去發展它,擴展它,而php的擴展就是它這些年不斷前行的動力,yar,swoole的出現,讓php又煥發出青春活力。
  • Mac上通過docker配置PHP開發環境
    安裝docker關於MAC上安裝docker網上有很多文章介紹,這裡我就不在做描述了,順便提一句,建議使用阿里雲或Daocloud提供的加速器。使用docker-compose配置開發環境一般一個基本的PHP開發環境包括PHP、PHP-FPM、WEB伺服器、MySQL資料庫,另外還會有Redis或memcache等相關NoSQL服務。我主要是通過docker-compose來配置服務。
  • C、C++、Java、PHP、Python分別用來開發什麼?
    目前而言,C語言主要用來開發底層模塊(比如驅動,解碼器,算法實現),服務應用(比如web伺服器)和嵌入式應用(比如微波爐裡的程序)。C++也可以做這些,不過由於C++的複雜性和標準問題,人們還是更願意使用C來做。C++更適合比較複雜但又特別需要高效率的設施,比如大型遊戲,一些基礎庫,大型桌面應用。
  • 2020年學PHP開發在淄博還有用嗎
    實際上,PHP 仍然在被大範圍的使用,尤其是 Web 後端領域,PHP 的地位依然沒有下滑,不減反增。儘管現在有最新的替代技術,但它並沒有太大受壓縮。 它驅動全球超過2億多個網站,有全球超過81.7%的公共網站在伺服器端採用php。不僅如此,據統計,有78.1%從事php的人認為php最容易學習和上手。這是因為php常用的數據結構都內置了,使用起來方便簡單,也一點都不複雜,表達能力相當靈活。 其次,他還有一個優點就是:開發職位很多。
  • java和php在web開發方面對比分析
    使用javabean可以方便的實現java代碼和html的分離,能夠增強系統的功能和軟體的復用性。java的web開發屬於sun公司定義的j2ee其中的規範。而且在j2ee中包括了java的web開發的所有方面,如:jsp、servlet、jdbc、jndi、javabean、ejb等等。j2ee就特別適合於做大型的企業級的應用。
  • PHP 微服務集群搭建
    ——維基百科實現了 RPC 協議的框架,可以讓服務方和調用方屏蔽各種底層細節,讓調用方像調用本地函數一樣調用遠端的函數(服務)。RPC 框架一般為服務端和客戶端提供了序列化、反序列化、連接池管理、負載均衡、故障轉移、隊列管理、超時管理、異步管理等職能。