Heim  >  Artikel  >  Backend-Entwicklung  >  Dinge über die Verwendung von Thrift in PHP für die serverseitige Entwicklung

Dinge über die Verwendung von Thrift in PHP für die serverseitige Entwicklung

藏色散人
藏色散人nach vorne
2020-10-12 14:26:015042Durchsuche

PHP verwendet Thrift für die serverseitige Entwicklung.

Thrift verwendet die Schnittstellenbeschreibungssprache zum Definieren und Erstellen von Diensten und verwendet das Binärformat zum Übertragen von Daten. Es ist besser für hohe Parallelität und große Datenmengen Mehrsprachige Umgebung.

Was ist Apache Thrift?

Apache Thrift ist ein erweiterbares, sprachübergreifendes Service-Calling-Framework, das von FaceBook entwickelt wurde. Um es einfach auszudrücken: Sie müssen zunächst eine Konfigurationsdatei definieren, um Server in ihren jeweiligen Sprachen basierend auf dieser Konfigurationsdatei zu generieren Mit anderen Worten: Basierend auf dem Thrift-Protokoll kann Java zum Aufrufen von PHP verwendet werden. Unterstützt derzeit den gegenseitigen Aufruf zwischen C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml und Delphi und anderen Sprachen.

Im Vergleich zu herkömmlichen Datenübertragungsmethoden wie XML und JSON verwendet Thrift die Schnittstellenbeschreibungssprache zum Definieren und Erstellen von Diensten und überträgt Daten im Binärformat. Es ist für hohe Parallelität und große Datenmengen geeignet Mehrsprachige Anwendungen werden besser unterstützt. Anforderungen an die Thrift-Installationsumgebung sind nicht installiert. Zuerst installieren, Andernfalls schlägt „make“ fehl und es kommt zu der Fehlermeldung „Lex- und Yacc-Befehl nicht gefunden“ (allgemeine Maschinen scheinen deinstalliert zu sein, verwenden Sie einfach „apt-get install flex bision“ für Ubuntu).

Thrift installieren

    Laden Sie die neueste Version von Thrift herunter:
  • 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. Erstellen Sie die Konfigurationsdatei

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

  • Verwenden Sie ./configure --help, um die Optionen anzuzeigen

Wenn Sie eine Sprache deaktivieren möchten, können Sie ./configure --without-java verwenden unpack()-Funktionen zum Sequenzieren Um Daten zu konvertieren

müssen Sie die APC-Erweiterung installieren, da die TSocketPool-Klasse die Funktionen apc_fetch() und apc_store() für APC-Cache-Vorgänge verwendet.

Wenn Sie Thrift mit PHP verwenden, müssen Sie zusätzlich zum Kopieren der Basisdateien in Thrift/lib/php/lib in das Projektverzeichnis auch die gemäß der Konfigurationsdatei generierten PHP-Dateien in den Paketordner kopieren und importieren Dies wird später im Projekt ausführlich besprochen.

klassebibliothek Beschreibung

    Data Transmissionsformat (Protokoll)
  • Definiert den Übertragungsinhalt, die Verpackung und das Auspacken des Sparsamkeitstyp Auspacken.
  • TCompactProtocol, Komprimierungsformat

TJSONProtocol, JSON-Format

  • TMultiplexedProtocol, Verwendung der ersten drei Datenformate zur Interaktion mit Servern, die Multiplexprotokolle unterstützen (Bereitstellung mehrerer Dienste gleichzeitig, TMultiplexedProcessor)

  • Datenübertragungsmethode (Transport)

definiert, wie Daten gesendet (geschrieben) und empfangen (gelesen) werden, einschließlich:

TBufferedTransport, zwischengespeicherte Übertragung, geschriebene Daten beginnen nicht sofort mit der Übertragung, bis der Cache aktualisiert wird.

TSocket verwendet Socket-Übertragung

TFramedTransport verwendet den Blockmodus für die Übertragung. Die spezifische Übertragungsimplementierung hängt von anderen Übertragungsmethoden ab, z. B. TSocket
  • TCurlClient verwendet Curl zur Interaktion mit dem Server
  • THttpClient, verwenden Sie den Stream-Modus, um mit dem HTTP-Server zu interagieren.
  • TMemoryBuffer, verwenden Sie den Speichermodus, um Daten auszutauschen
  • TSocketPool basiert auf TSocket. Unterstützt die Verwaltung mehrerer Server (APC-Unterstützung erforderlich) und eliminiert automatisch ungültige Server Spezifikation: http://thrift.apache.org/docs/idl

    Thrift-Typen: http://thrift.apache.org/docs/types
2. Clientseitiges Schreiben Zugangscode

IDL: 1.tutorial.thrift

include "shared.thrift"
namespace php tutorial
typedef i32 MyInteger
const i32 INT32CONSTANT = 9853
const map<string,string> MAPCONSTANT = {&#39;hello&#39;:&#39;world&#39;, &#39;goodnight&#39;:&#39;moon&#39;}
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-Server

    <?php
    namespace tutorial\php;
    ini_set(&#39;display_errors&#39;,1);
    error_reporting(E_ALL);
    // 引入类自动加载文件
    require_once __DIR__.&#39;/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php&#39;;
    // 载入自动加载类
    use Thrift\ClassLoader\ThriftClassLoader;
    // 定义根据.thrift文件生成的php文件
    $GEN_DIR = realpath(dirname(__FILE__).&#39;/..&#39;).&#39;/gen-php&#39;;
    // 注册thrift服务
    $loader = new ThriftClassLoader();
    $loader->registerNamespace(&#39;Thrift&#39;, __DIR__ . &#39;/../../lib/php/lib&#39;);
    $loader->registerDefinition(&#39;shared&#39;, $GEN_DIR);
    $loader->registerDefinition(&#39;tutorial&#39;, $GEN_DIR);
    $loader->register();
    if (php_sapi_name() == &#39;cli&#39;) {
      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&#39;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(&#39;Content-Type&#39;, &#39;application/x-thrift&#39;);
    if (php_sapi_name() == &#39;cli&#39;) {
      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(&#39;localhost&#39;, 9090);
    //$server = new TNonblockingServer($processor, $transport, $transportFactory, $transportFactory, $protocolFactory, $protocolFactory);
    //$server->serve();
    //作为cli方式运行,监听端口,官方实现
    //$transportFactory = new TBufferedTransportFactory();
    //$protocolFactory = new TBinaryProtocolFactory(true, true);
    //$transport = new TServerSocket(&#39;localhost&#39;, 9090);
    //$server = new TSimpleServer($processor, $transport, $transportFactory, $transportFactory, $protocolFactory, $protocolFactory);
    //$server->serve();

    php-Client
  • <?php
    namespace tutorial\php;
    error_reporting(E_ALL);
    require_once __DIR__.&#39;/../../lib/php/lib/Thrift/ClassLoader/ThriftClassLoader.php&#39;;
    use Thrift\ClassLoader\ThriftClassLoader;
    $GEN_DIR = realpath(dirname(__FILE__).&#39;/..&#39;).&#39;/gen-php&#39;;
    $loader = new ThriftClassLoader();
    $loader->registerNamespace(&#39;Thrift&#39;, __DIR__ . &#39;/../../lib/php/lib&#39;);
    $loader->registerDefinition(&#39;shared&#39;, $GEN_DIR);
    $loader->registerDefinition(&#39;tutorial&#39;, $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(&#39;--http&#39;, $argv)) {
      // 使用http方式连接
        $socket = new THttpClient(&#39;localhost&#39;, 8080, &#39;/php/PhpServer.php&#39;);
      } else {
        // 使用socket连接
        $socket = new TSocket(&#39;localhost&#39;, 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 &#39;TException: &#39;.$tx->getMessage()."\n";
    }
  • Ausgabe:

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

Das obige ist der detaillierte Inhalt vonDinge über die Verwendung von Thrift in PHP für die serverseitige Entwicklung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen