Thrift

Содержание
Введение
Установка
Пример
Похожие статьи

Введение

Thrift (с англ. — «бережливость», произносится как [θrift]) — язык описания интерфейсов , который используется для определения и создания служб под разные языки программирования.

Является фреймворком к удалённому вызову процедур (RPC). Используется компанией Facebook в качестве масштабируемого кросс-языкового сервиса по разработке.

Сочетает в себе программный конвейер с движком генерации кода для разработки служб, в той или иной степени эффективно и легко работающих между такими языками как C# , C++ , Cappuccino, Cocoa, Delphi, Erlang, Go , Haskell, Java , OCaml, Perl, PHP , Python , Ruby , Rust, Smalltalk и JavaScript .

Проще говоря, Thrift является двоичным протоколом связи. С апреля 2007 разрабатывается как open source проект некоммерческой организации Apache Software Foundation.

Изображение баннера

Установка

Про установку в Windows читайте здесь

PowerShell скрипт для скачивания thrift.exe

$THRIFT_URL = "https://dlcdn.apache.org/thrift/0.19.0/thrift-0.19.0.exe" $FilePath = ".\thrift.exe" If (Test-Path -path $FilePath -PathType Leaf) { Write-Host "thrift.exe file exists" -f Green } Else { Write-Host "thrift.exe file does not exist - starting download" -f Yellow Invoke-WebRequest $THRIFT_URL -OutFile thrift.exe }

Пример

Предположим, что под Windows с официального сайта скачан и помещён в

C:\DEV\Thrift

.exe файл, например thrift-0.19.0.exe

Также заранее установлен Python , например, по этой инструкции.

Из документации к Thrift берем пример multiplication.thrift убрав для простоты часть про Java

namespace py tutorial /* C like comments are supported */ // This is also a valid comment typedef i32 int // We can use typedef to get pretty names for the types we are using service MultiplicationService { int multiply(1:int n1, 2:int n2), }

Открываем консоль в директории с multiplication.thrift и выполняем

C:\DEV\Thrift\thrift-0.19.0.exe --gen py .\multiplication.thrift

Сгенерируется директория gen-py со следующим содержимым

gen-py/ |-- __init__.py `-- tutorial |-- MultiplicationService-remote |-- MultiplicationService.py |-- __init__.py |-- constants.py `-- ttypes.py

Файл __init__.py в корне пустой

внутри tutorial

__all__ = ['ttypes', 'constants', 'MultiplicationService']

constants.py

# # Autogenerated by Thrift Compiler (0.19.0) # # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING # # options string: py # from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException from thrift.protocol.TProtocol import TProtocolException from thrift.TRecursive import fix_spec import sys from .ttypes import *

MultiplicationService.py

# # Autogenerated by Thrift Compiler (0.19.0) # # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING # # options string: py # from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException from thrift.protocol.TProtocol import TProtocolException from thrift.TRecursive import fix_spec import sys import logging from .ttypes import * from thrift.Thrift import TProcessor from thrift.transport import TTransport all_structs = [] class Iface(object): def multiply(self, n1, n2): """ Parameters: - n1 - n2 """ pass class Client(Iface): def __init__(self, iprot, oprot=None): self._iprot = self._oprot = iprot if oprot is not None: self._oprot = oprot self._seqid = 0 def multiply(self, n1, n2): """ Parameters: - n1 - n2 """ self.send_multiply(n1, n2) return self.recv_multiply() def send_multiply(self, n1, n2): self._oprot.writeMessageBegin('multiply', TMessageType.CALL, self._seqid) args = multiply_args() args.n1 = n1 args.n2 = n2 args.write(self._oprot) self._oprot.writeMessageEnd() self._oprot.trans.flush() def recv_multiply(self): iprot = self._iprot (fname, mtype, rseqid) = iprot.readMessageBegin() if mtype == TMessageType.EXCEPTION: x = TApplicationException() x.read(iprot) iprot.readMessageEnd() raise x result = multiply_result() result.read(iprot) iprot.readMessageEnd() if result.success is not None: return result.success raise TApplicationException(TApplicationException.MISSING_RESULT, "multiply failed: unknown result") class Processor(Iface, TProcessor): def __init__(self, handler): self._handler = handler self._processMap = {} self._processMap["multiply"] = Processor.process_multiply self._on_message_begin = None def on_message_begin(self, func): self._on_message_begin = func def process(self, iprot, oprot): (name, type, seqid) = iprot.readMessageBegin() if self._on_message_begin: self._on_message_begin(name, type, seqid) if name not in self._processMap: iprot.skip(TType.STRUCT) iprot.readMessageEnd() x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name)) oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid) x.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() return else: self._processMap[name](self, seqid, iprot, oprot) return True def process_multiply(self, seqid, iprot, oprot): args = multiply_args() args.read(iprot) iprot.readMessageEnd() result = multiply_result() try: result.success = self._handler.multiply(args.n1, args.n2) msg_type = TMessageType.REPLY except TTransport.TTransportException: raise except TApplicationException as ex: logging.exception('TApplication exception in handler') msg_type = TMessageType.EXCEPTION result = ex except Exception: logging.exception('Unexpected exception in handler') msg_type = TMessageType.EXCEPTION result = TApplicationException(TApplicationException.INTERNAL_ERROR, 'Internal error') oprot.writeMessageBegin("multiply", msg_type, seqid) result.write(oprot) oprot.writeMessageEnd() oprot.trans.flush() # HELPER FUNCTIONS AND STRUCTURES class multiply_args(object): """ Attributes: - n1 - n2 """ def __init__(self, n1=None, n2=None,): self.n1 = n1 self.n2 = n2 def read(self, iprot): if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) return iprot.readStructBegin() while True: (fname, ftype, fid) = iprot.readFieldBegin() if ftype == TType.STOP: break if fid == 1: if ftype == TType.I32: self.n1 = iprot.readI32() else: iprot.skip(ftype) elif fid == 2: if ftype == TType.I32: self.n2 = iprot.readI32() else: iprot.skip(ftype) else: iprot.skip(ftype) iprot.readFieldEnd() iprot.readStructEnd() def write(self, oprot): if oprot._fast_encode is not None and self.thrift_spec is not None: oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) return oprot.writeStructBegin('multiply_args') if self.n1 is not None: oprot.writeFieldBegin('n1', TType.I32, 1) oprot.writeI32(self.n1) oprot.writeFieldEnd() if self.n2 is not None: oprot.writeFieldBegin('n2', TType.I32, 2) oprot.writeI32(self.n2) oprot.writeFieldEnd() oprot.writeFieldStop() oprot.writeStructEnd() def validate(self): return def __repr__(self): L = ['%s=%r' % (key, value) for key, value in self.__dict__.items()] return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) def __eq__(self, other): return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ def __ne__(self, other): return not (self == other) all_structs.append(multiply_args) multiply_args.thrift_spec = ( None, # 0 (1, TType.I32, 'n1', None, None, ), # 1 (2, TType.I32, 'n2', None, None, ), # 2 ) class multiply_result(object): """ Attributes: - success """ def __init__(self, success=None,): self.success = success def read(self, iprot): if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None: iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec]) return iprot.readStructBegin() while True: (fname, ftype, fid) = iprot.readFieldBegin() if ftype == TType.STOP: break if fid == 0: if ftype == TType.I32: self.success = iprot.readI32() else: iprot.skip(ftype) else: iprot.skip(ftype) iprot.readFieldEnd() iprot.readStructEnd() def write(self, oprot): if oprot._fast_encode is not None and self.thrift_spec is not None: oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec])) return oprot.writeStructBegin('multiply_result') if self.success is not None: oprot.writeFieldBegin('success', TType.I32, 0) oprot.writeI32(self.success) oprot.writeFieldEnd() oprot.writeFieldStop() oprot.writeStructEnd() def validate(self): return def __repr__(self): L = ['%s=%r' % (key, value) for key, value in self.__dict__.items()] return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) def __eq__(self, other): return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ def __ne__(self, other): return not (self == other) all_structs.append(multiply_result) multiply_result.thrift_spec = ( (0, TType.I32, 'success', None, None, ), # 0 ) fix_spec(all_structs) del all_structs

MultiplicationService-remote.py

#!/usr/bin/env python # # Autogenerated by Thrift Compiler (0.19.0) # # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING # # options string: py # import sys import pprint if sys.version_info[0] > 2: from urllib.parse import urlparse else: from urlparse import urlparse from thrift.transport import TTransport, TSocket, TSSLSocket, THttpClient from thrift.protocol.TBinaryProtocol import TBinaryProtocol from tutorial import MultiplicationService from tutorial.ttypes import * if len(sys.argv) <= 1 or sys.argv[1] == '--help': print('') print('Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] [-s[sl]] [-novalidate] [-ca_certs certs] [-keyfile keyfile] [-certfile certfile] function [arg1 [arg2...]]') print('') print('Functions:') print(' int multiply(int n1, int n2)') print('') sys.exit(0) pp = pprint.PrettyPrinter(indent=2) host = 'localhost' port = 9090 uri = '' framed = False ssl = False validate = True ca_certs = None keyfile = None certfile = None http = False argi = 1 if sys.argv[argi] == '-h': parts = sys.argv[argi + 1].split(':') host = parts[0] if len(parts) > 1: port = int(parts[1]) argi += 2 if sys.argv[argi] == '-u': url = urlparse(sys.argv[argi + 1]) parts = url[1].split(':') host = parts[0] if len(parts) > 1: port = int(parts[1]) else: port = 80 uri = url[2] if url[4]: uri += '?%s' % url[4] http = True argi += 2 if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': framed = True argi += 1 if sys.argv[argi] == '-s' or sys.argv[argi] == '-ssl': ssl = True argi += 1 if sys.argv[argi] == '-novalidate': validate = False argi += 1 if sys.argv[argi] == '-ca_certs': ca_certs = sys.argv[argi+1] argi += 2 if sys.argv[argi] == '-keyfile': keyfile = sys.argv[argi+1] argi += 2 if sys.argv[argi] == '-certfile': certfile = sys.argv[argi+1] argi += 2 cmd = sys.argv[argi] args = sys.argv[argi + 1:] if http: transport = THttpClient.THttpClient(host, port, uri) else: if ssl: socket = TSSLSocket.TSSLSocket(host, port, validate=validate, ca_certs=ca_certs, keyfile=keyfile, certfile=certfile) else: socket = TSocket.TSocket(host, port) if framed: transport = TTransport.TFramedTransport(socket) else: transport = TTransport.TBufferedTransport(socket) protocol = TBinaryProtocol(transport) client = MultiplicationService.Client(protocol) transport.open() if cmd == 'multiply': if len(args) != 2: print('multiply requires 2 args') sys.exit(1) pp.pprint(client.multiply(eval(args[0]), eval(args[1]),)) else: print('Unrecognized method %s' % cmd) sys.exit(1) transport.close()

ttypes.py

# # Autogenerated by Thrift Compiler (0.19.0) # # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING # # options string: py # from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException from thrift.protocol.TProtocol import TProtocolException from thrift.TRecursive import fix_spec import sys from thrift.transport import TTransport all_structs = [] fix_spec(all_structs) del all_structs

Демо

hello.thrift

service HelloSvc { string hello_func() }

thrift --gen py hello.thrift

Проект будет иметь следующую структуру

thrift_hello/ |-- gen-py | |-- __init__.py | `-- hello | |-- HelloSvc-remote | |-- HelloSvc.py | |-- __init__.py | |-- constants.py | `-- ttypes.py |-- hello.thrift |-- hello_client.py |-- hello_server.py |-- requirements.txt `-- venv

hello_server.py

import sys sys.path.append("gen-py") from hello import HelloSvc from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from thrift.server import TServer class HelloHandler: def hello_func(self): print("(Server) Handling client request") return "Hello from the python server" handler = HelloHandler() proc = HelloSvc.Processor(handler) trans_svr = TSocket.TServerSocket(port=9090) trans_fac = TTransport.TBufferedTransportFactory() proto_fac = TBinaryProtocol.TBinaryProtocolFactory() server = TServer.TSimpleServer(proc, trans_svr, trans_fac, proto_fac) server.serve()

python hello_server.py

hello_client.py

import sys sys.path.append("gen-py") from hello import HelloSvc from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol trans = TSocket.TSocket("localhost", 9090) trans = TTransport.TBufferedTransport(trans) proto = TBinaryProtocol.TBinaryProtocol(trans) client = HelloSvc.Client(proto) trans.open() msg = client.hello_func() print(f"(Client) received: {msg}") trans.close()

В другом терминале

python hello_client.py

(Client) received: Hello from the python server

В терминале сервера появится лог

(Server) Handling client request

Обмен сообщениями с Thrift сервреом Wireshark www.devhops.ru
Отравка одного сообщения
WireShark
Похожие статьи
Ошибки Thrift
Make
Изображение баннера

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: