如何指定非默认的 Thrift 协议和传输

How to specify non-default Thrift Protocols and Transports

我已阅读official Apache Thrift docs. I have read the excellent Thrift By Example Docs. I have even read the even more excellent Thrift: The Missing Guide

无处 我能弄清楚如何指定,比方说,TCompactProtocol 超过默认值 (TBinaryProtocol)。或者说,TFramedSocket 超过默认值 (TSocket)。

有人可以在这里详细说明吗?

Thrift 中的协议描述了如何从底层存储介质写入实际数据位的格式to/read。通常只需要一个这样的东西,不需要堆叠它们,因为您只需要一个物理布局来序列化数据。

相比之下,设计成堆叠的就是所谓的"layered transports"。传输在较低的抽象级别上运行。非常典型的例子是TFramedTransportTBufferedTransport。分层传输向字节流添加功能,例如添加帧大小、缓冲数据或提供多路复用功能。从技术上讲,它们位于协议和底层 "endpoint transports" 之间,后者实际上 write/read 字节 to/from 存储介质(例如套接字)。

因此,如果您需要更改从字节到字节的转换,则需要编写另一个协议。每当需要额外的存储介质时,编写端点传输。如果字节只应在 serialization/deserialization 过程之间进行操作,假设您想添加新的压缩算法 "Schrippe" 让 Brotli and Zopfli 看起来像旧面包(双关语非常有意),写分层传输。

在 Thrift 测试套件的依赖于语言的实现中可以找到一个如何将所有东西堆叠在一起的好例子(/test/yourlanguage 下有一些例外)。测试套件旨在测试各种组合。如果您完成了本教程,我建议您查看该代码,因为它解释了 client end and the server end.

的许多高级功能。

举个例子,这是设置所有选定组件的相关部分from the C++ Test Client

  boost::shared_ptr<TTransport> transport;
  boost::shared_ptr<TProtocol> protocol;

  boost::shared_ptr<TSocket> socket;
  boost::shared_ptr<TSSLSocketFactory> factory;

  if (ssl) {
    factory = boost::shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory());
    factory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
    factory->loadTrustedCertificates((dir_path + "../keys/CA.pem").c_str());
    factory->authenticate(true);
    socket = factory->createSocket(host, port);
  } else {
    if (domain_socket != "") {
      if (abstract_namespace) {
        std::string abstract_socket("[=10=]", 1);
        abstract_socket += domain_socket;
        socket = boost::shared_ptr<TSocket>(new TSocket(abstract_socket));
      } else {
        socket = boost::shared_ptr<TSocket>(new TSocket(domain_socket));
      }
      port = 0;
    } else {
      socket = boost::shared_ptr<TSocket>(new TSocket(host, port));
    }
  }

  if (transport_type.compare("http") == 0) {
    boost::shared_ptr<TTransport> httpSocket(new THttpClient(socket, host, "/service"));
    transport = httpSocket;
  } else if (transport_type.compare("framed") == 0) {
    boost::shared_ptr<TFramedTransport> framedSocket(new TFramedTransport(socket));
    transport = framedSocket;
  } else {
    boost::shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket));
    transport = bufferedSocket;
  }

  if (protocol_type.compare("json") == 0) {
    boost::shared_ptr<TProtocol> jsonProtocol(new TJSONProtocol(transport));
    protocol = jsonProtocol;
  } else if (protocol_type.compare("compact") == 0) {
    boost::shared_ptr<TProtocol> compactProtocol(new TCompactProtocol(transport));
    protocol = compactProtocol;
  } else if (protocol_type == "header") {
    boost::shared_ptr<TProtocol> headerProtocol(new THeaderProtocol(transport));
    protocol = headerProtocol;
  } else {
    boost::shared_ptr<TBinaryProtocol> binaryProtocol(new TBinaryProtocol(transport));
    protocol = binaryProtocol;
  }

  // Connection info
  cout << "Connecting (" << transport_type << "/" << protocol_type << ") to: ";
  if (abstract_namespace) {
    cout << '@';
  }
  cout << domain_socket;
  if (port != 0) {
    cout << host << ":" << port;
  }
  cout << endl;