サーバーサイド開発に thrift を使用する php について

藏色散人
リリース: 2023-04-09 15:52:02
転載
5003 人が閲覧しました

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、Delphi およびその他の言語間の相互呼び出しをサポートしています。

Thrift は、xml や json などの従来のデータ送信方法と比較して、インターフェイス記述言語を使用してサービスを定義および作成し、バイナリ形式でデータを送信します。より小さく、より効率的です。高い同時実行性とデータ量を実現するため、大規模な多言語環境では、サポートが強化されます。

#thrift インストール環境要件

  • g 4.2

  • boost 1.53.0

  • lex と yacc (flex と bison に基づく)

lex と yacc がインストールされていない場合は、最初にインストールする必要があります。そうしないと、make が失敗してプロンプトが表示されます。 lex および yacc コマンドが見つからないエラー (一般的なマシンはインストールされていないようです。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文件
./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() 関数がデータのシリアル化に使用されます

  • TSocketPool クラスが apc_fetch() と apc_store を使用するため、APC 拡張機能をインストールする必要があります() APC キャッシュ操作用の関数。

php が thrift を使用する場合、thrift/lib/php/lib 内の基本ファイルをプロジェクト ディレクトリにコピーすることに加えて、設定に基づいて生成された php ファイルもコピーする必要がありますファイルをパッケージ フォルダーに移動し、プロジェクトに導入します。これについては後で詳しく説明します。

クラスライブラリの説明

データ送信フォーマット(プロトコル)

Thrift Type Unpackingの送信内容とパッケージ化を定義します。

  • TBinaryProtocol、バイナリ形式、TBinaryProtocolAccelerated は、thrift_protocol 拡張機能に依存する高速パッケージ化およびアンパックです。

  • TCompactProtocol、圧縮形式

  • TJSONProtocol、JSON 形式

  • TMultiplexedProtocol、最初の 3 つを使用データ形式は、多重化プロトコル (複数のサービスを同時に提供する TMultiplexedProcessor) をサポートするサーバーと通信します。

#データ送信方法 (トランスポート)

# 以下を含むデータの送信 (書き込み) および受信 (読み取り) 方法を定義します。

TBufferedTransport、キャッシュされた送信。書き込まれたデータは、キャッシュが更新されるまですぐには送信を開始しません。
  • TSocket、ソケット送信を使用します。
  • TFrameTransport、送信にブロック モードを使用します。特定の送信実装は、TSocket などの他の送信方法に依存します。
  • TCurlClient、curl を使用してサーバーと対話します
  • THttpClient、ストリーム モードを使用して HTTP サーバーと対話します
  • TMemoryBuffer、データ交換にメモリを使用します
  • TPhpStream、送信に PHP 標準入出力ストリームを使用します
  • TNullTransport、データ送信を閉じる
  • TSocketPool は TSocket に基づく複数のサーバー管理をサポートし (APC サポートが必要)、無効なサーバーを自動的に排除します
  • 開発プロセス

1. IDL (インターフェース記述言語) インターフェース記述ファイル、サフィックス .thrift

IDL 仕様を定義します: http://thrift.apache.org/docs/idl

thrift タイプ: 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 = {&#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サーバー

<?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クライアント

<?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";
}
ログイン後にコピー

出力:

// php client.php --http
ping()
1+1=2
InvalidOperation: Cannot divide by 0
15-10=5
Log: PHP is stateless!
ログイン後にコピー

以上がサーバーサイド開発に thrift を使用する php についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:csdn.net
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!