ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Thrift 알아보기
    BigData 2023. 11. 4. 16:58
    728x90
    반응형

     

    - 목차

     

    함께 보면 좋은 글

    https://westlife0615.tistory.com/361

     

    RPC (Remote Procedure Call) 알아보기

    - 목차 소개. RPC 는 Remote Procedure Call 의 약자입니다. 의미는 "원격 서버에 있는 함수를 사용한다" 라는 뜻인데요. 프로그래밍에서 함수를 뜻하는 여러 표현들이 있습니다. Function, Procedure, Method 등

    westlife0615.tistory.com

     

    소개.

    Thrift 는 분산환경 시스템에서 많은 역할을 수행하는 도구입니다.

    많은 역할을 수행하다보니 "Thrift 는 바로 이것이다 !" 라고 쉽게 정의를 내리기보단 주요한 역할들을 알아보려고 합니다.

     

    먼저, ThriftRPC 프레임워크로써 동작합니다.

    RPC 는 Remote Procedure Call 의 약자인데요.

    Remote Procedure Call 은 물리적으로 떨어진 두 서버가 통신하는 행위와 방식을 의미합니다.

    HTTP 통신으로 요청을 주고받아도 RPC 이고,

    gRPC 와 같은 RPC 의 구현 프로토콜도 존재합니다.

    그리고 TCP 소켓을 연결하여 클라이언트와 서버가 데이터를 주고 받아도 이 또한 RPC 라고 부를 수 있습니다.

    Thrift 는 분산환경에서 분산 서버들끼리 효율적으로 데이터를 교환하기 위한 방식을 제공합니다.

    RPC 로써의 Thrift 는 이어지는 내용에서 알아보도록 하겠습니다.

     

    두번째로 Thrift 는 Serialization/Deserialization 기능을 수행합니다.

    Avro, Parquet 등과 같이 Thrift 또한 Serialiation, Deserialization 기능을 가집니다.

    ThriftRPC 를 위한 수단이기 때문에 Thrift 는 네트워크 통신에서 사용됩니다.

    그리고 네트워크 통신은 Serialization/Deserialization 가 필수입니다.

    비트 단위로 데이터가 전달되어야하기 때문이죠.

    이 과정에서 효율적으로 직렬화하는 것이 중요한데, Thrift 는 자체적인 Serialization 체계를 가집니다.

    그래서 Thrift 를 RPC 의 용도가 아닌 Serialization/Deserialization 의 용도로 사용할 수도 있습니다.

    이 또한 이어지는 내용에서 알아보도록 하겠습니다.

     

    Thrift IDL.

    ThriftIDLInterface Definition Language 의 약자입니다.

    Thrift IDL 은 하나의 파일이며, 파일의 내용으로 Thrift 의 구성요소들이 작성됩니다.

    구성요소를 아래와 같습니다.

     

    1. Serialization/Deserialization 할 데이터의 모양

    2. RPC 로써 동작한 기능들

     

    Java 로 치면 Class 의 Field 와 Method 들을 정의하는 것과 유사합니다.

    Thrift 에서 어떤 데이터 ( Field )를 사용할 것이며, 어떤 기능 ( Method ) 들을 제공해야하는지 정의합니다.

     

    예를 들어보겠습니다.

    아래 예시는 Person.thrift 파일이며, 텍스트 기반의 파일입니다.

    해당 파일은 Thrift 에서 사용할 데이터와 기능을 정의하는 명세입니다.

    Person 이라는 struct 은 Serialization/Deserialization 을 수행하는 데이터 형식입니다.

    PersonService 라는 service 는 RPC Function 들이죠.

     

    < IDL 예시  Person.thrift >

    namespace java com.example.thrift
    
    typedef i32 int
    
    struct Person {
      1: required string name,
      2: optional int age,
      3: list<string> email
    }
    
    service PersonService {
      void create(1: Person person),
      Person get(1: string name),
      list<Person> getAll()
    }

     

     

    이러한 방식으로 IDL 이 구성되면, 이는 thrift 바이너리 실행 파일에 의해서 활용됩니다.

    Mac 에선 아래와 같이 brew 로 설치가 가능합니다.

    brew install thrift

     

    그리고 아래와 같은 명령어로 관련된 결과물을 얻을 수 있습니다.

    thrift -gen java Person.thrift

     

     

    결과물은 아래와 같이 Person.java, PersonService.java 파일이 생성됩니다.

    ls -al
    total 224
    drwxr-xr-x  4 XXXXXXXX    128 11  4 15:48 .
    drwxr-xr-x  3 XXXXXXXX     96 11  4 15:48 ..
    -rw-r--r--  1 XXXXXXXX  20443 11  4 15:48 Person.java
    -rw-r--r--  1 XXXXXXXX  93188 11  4 15:48 PersonService.java

     

     

    Thrift Compiler.

     

    Thrift Compiler 는 Thrift IDL 파일을 기반으로 소스코드를 생성하는 Thrift 구성요소입니다.

    이름그대로 IDL 파일을 컴파일하여 실질적인 소스코드를 생성합니다.

     

    아래 예시처럼

    struct 디렉티브로 설정된 Person 이라는 구조는 커스텀 데이터 타입 ( class, struct ) 으로 변형됩니다.

    java 의 경우라면 Person Class, Golang 이나 C 같은 경우에는 struct 등이 생성되죠.

     

    service 디렉티브로 설정된 PersonService 또한 소스코드로 변형되는데요.

    RPC 통신을 위한 실질적인 기능을 수행할 수 있도록 변형됩니다.

    이는 네트워크 스택 위에서 동작하므로 내부적으로 네트워크 통신을 위한 로직들 또한 추상화됩니다.

     

    < IDL 예시 >

    struct Person {
      1: required string name,
      2: optional int age,
      3: list<string> email
    }
    
    service PersonService {
      void create(1: Person person),
      Person get(1: string name),
      list<Person> getAll()
    }

     

    output file 의 언어와 버전은 어떻게 설정하는가?

    Thrift Compiler 는 IDL 파일을 기반으로 실제 소스코드를 생성합니다.

    생성된 소스코드는 지정된 프로그래밍 언어로 작성됩니다.

    아래와 같은 형식으로 프로그래밍 언어와 언어의 버전을 설정할 수 있습니다.

     

    # Generate Java code with Java version 11
    thrift -gen java -version 11 Person.thrift
    
    # Generate C++ code with C++ version 17
    thrift -gen c++ -version 17 Person.thrift
    
    # Generate Python code with Python version 3.8
    thrift -gen python -version 3.8 Person.thrift
    
    # Generate PHP code with PHP version 8.1
    thrift -gen php -version 8.1 Person.thrift
    
    # Generate Ruby code with Ruby version 3.1
    thrift -gen ruby -version 3.1 Person.thrift
    
    # Generate Erlang code with Erlang version 25
    thrift -gen erlang -version 25 Person.thrift
    
    # Generate Perl code with Perl version 5.30
    thrift -gen perl -version 5.30 Person.thrift
    
    # Generate Haskell code with Haskell version 9.4
    thrift -gen haskell -version 9.4 Person.thrift
    
    # Generate C# code with C# version 11
    thrift -gen csharp -version 11 Person.thrift
    
    # Generate Cocoa code with Cocoa version 13.4
    thrift -gen cocoa -version 13.4 Person.thrift
    
    # Generate JavaScript code with JavaScript version ES2023
    thrift -gen js -version ES2023 Person.thrift
    
    # Generate Node.js code with Node.js version 18
    thrift -gen nodejs -version 18 Person.thrift

     

     

     

    examples for javascript version.

    아래는 javascript 로 작성된 output 소스코드를 위한 예시입니다.

    class 가 없는 javascript 같은 경우에는 output 소스코드가 어떻게 생겼을지 궁금해서 시도해보았습니다.

     

    < IDL & Compile >

    cat <<EOF > /tmp/Person.thrift
    typedef i32 int
    
    struct Person {
      1: required string name,
      2: optional int age,
      3: list<string> email
    }
    
    service PersonService {
      void create(1: Person person),
      Person get(1: string name),
      list<Person> getAll()
    }
    EOF
    
    thrift -gen js -version es6 /tmp/Person.thrift

     

     

    < JS Thrift 결과물 >

     

    javascript 는 Class 가 없으므로 Person_types.js 라는 파일이 생성되며,

    ls -al
    total 32
    drwxr-xr-x  4 ihyeong-ug  wheel    128 11  4 16:41 .
    drwxr-xr-x  5 ihyeong-ug  wheel    160 11  4 16:41 ..
    -rw-r--r--  1 ihyeong-ug  wheel  11309 11  4 16:41 PersonService.js
    -rw-r--r--  1 ihyeong-ug  wheel   2805 11  4 16:41 Person_types.js

     

    < Person_types.js >

    대략 아래와 같은 형식으로 파일이 생성됩니다.

    Person = function(args) {
      this.name = null;
      this.age = null;
      this.email = null;
      if (args) {
        if (args.name !== undefined && args.name !== null) {
          this.name = args.name;
        } else {
          throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.UNKNOWN, 'Required field name is unset!');
        }
        if (args.age !== undefined && args.age !== null) {
          this.age = args.age;
        }
        if (args.email !== undefined && args.email !== null) {
          this.email = Thrift.copyList(args.email, [null]);
        }
      }
    };
    Person.prototype = {};
    Person.prototype.read = function(input) {
        // 생략
    };
    
    Person.prototype.write = function(output) {
          // 생략
    };

     

     

     

    a Example for Python.

    아래는 python 로 작성된 output 소스코드를 위한 예시입니다.

     

    cat <<EOF > /tmp/Person.thrift
    
    struct Person {
      1: required string name,
      2: optional i32 age,
      3: list<string> email
    }
    
    service PersonService {
      void create(1: Person person),
      Person get(1: string name),
      list<Person> getAll()
    }
    EOF
    
    thrift -gen py /tmp/Person.thrift

     

     

    < 결과물 구조 >

    /gen-py
      /__init__.py
      /Person
        /PersonService-remote
        /PersonService.py
        /__init__.py
        /constants.py
        /ttypes.py

     

     

    반응형

    'BigData' 카테고리의 다른 글

    ASCII 코드 알아보기  (2) 2023.12.22
    Trino 도커로 따라하기  (0) 2023.12.03
    Avro Serialization 알아보기.  (0) 2023.10.05
    Avro File 알아보기  (0) 2023.10.04
    RabbitMQ 에 대해서  (0) 2023.04.09
Designed by Tistory.