>  기사  >  백엔드 개발  >  서버 측 개발을 위해 Thrift를 사용하는 PHP에 관한 것들

서버 측 개발을 위해 Thrift를 사용하는 PHP에 관한 것들

藏色散人
藏色散人앞으로
2020-10-12 14:26:014974검색

php는 서버 측 개발을 위해 thrift를 사용합니다.

thrift는 인터페이스 설명 언어를 사용하여 서비스를 정의하고 생성하며 바이너리 형식을 사용하여 데이터를 전송합니다. 높은 동시성, 대용량 데이터 및 더 효율적입니다. 다국어 환경을 지원합니다.

아파치 Thrift란 무엇인가요?

Apache Thrift는 FaceBook에서 개발한 확장 가능한 언어 간 서비스 호출 프레임워크입니다. 간단히 말하면 구성 파일을 먼저 정의해야 합니다. 클라이언트가 어떤 언어를 사용하든 상관없이 다양한 언어에서 Thrift를 사용하여 자체 언어로 서버를 생성할 수 있습니다. 즉, Thrift 프로토콜을 기반으로 Java는 PHP를 호출할 수 있습니다. 현재 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml, Delphi 및 기타 언어 간 상호 호출을 지원합니다.

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 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. 특정 언어를 비활성화하려면 TBinaryProtocol 프로토콜이 pack() 및 unpack() 함수를 시퀀스로 변환하려면

APC 확장을 설치해야 합니다. 왜냐하면 TSocketPool 클래스는 apc 캐시 작업에 apc_fetch() 및 apc_store() 함수를 사용하기 때문입니다.

php에서 thrift를 사용하는 경우 thrift/lib/php/lib의 기본 파일을 프로젝트 디렉터리에 복사하는 것 외에도 구성 파일에 따라 생성된 php 파일을 packages 폴더에 복사하고 이를 import해야 합니다. 나중에 프로젝트에서 자세히 논의할 것입니다.

클래스 라이브러리 설명
  • 데이터 전송 형식(프로토콜)
  • 은 다음을 포함하여 Thrift 유형의 전송 콘텐츠, 패키징 및 언패킹을 정의합니다.

TBinaryProtocol, 바이너리 형식, TBinaryProtocolAccelerated는 thrift_protocol에 따라 달라집니다. 포장 풀기.

    TCompactProtocol, 압축 형식
  • TJSONProtocol, JSON 형식
  • TMultiplexedProtocol, 처음 세 가지 데이터 형식을 사용하여 다중화 프로토콜을 지원하는 서버와 상호 작용(동시에 여러 서비스 제공, TMultiplexedProcessor)

데이터 전송 방법(전송)

은 다음을 포함하여 데이터 전송(쓰기) 및 수신(읽기) 방법을 정의합니다.

TBufferedTransport, 캐시된 전송, 작성된 데이터는 캐시가 새로 고쳐질 때까지 즉시 전송을 시작하지 않습니다.

  • TSocket, 소켓 전송 사용

  • TFramedTransport, 전송에 블록 모드 사용, 특정 전송 구현은 서버와 상호 작용하기 위해 컬을 사용하는 TSocket

  • TCurlClient와 같은 다른 전송 방법에 따라 다름

  • 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

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

    2.shared.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()
    }

    php server

    namespace php shared
    struct SharedStruct {
      1: i32 key
      2: string value
    }
    service SharedService {
      SharedStruct getStruct(1: i32 key)
    }
  • php client
  • <?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
    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";
    }

위 내용은 서버 측 개발을 위해 Thrift를 사용하는 PHP에 관한 것들의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제