How to create an Apache Thrift Service – Tutorial

Overview

Say you come up with a wonderful idea such as a really great phone service. You would want this phone service to be available to the APIs in various languages. Whether people are using Python, C++, Java or any other programming language, the users should be able to use your service. Also, you would want the users to be able to access globally. In such scenarios, you should create the Thrift Service. Thrift lets you create a generic interface which can be implemented on the server. The clients of this generic interface can be automatically generated in all kinds of languages.

Let us get started! Here we are going to create a very simple service that just prints the server time.

Step 0: Install Thrift

This step is not required if you are using CloudxLab. You can just log in to the web console. In case you want to set up Apache Thrift on your own machine please follow these instructions: https://thrift.apache.org/docs/install/

Step 1: Create the interface definition

Let us create a file with name Example.thrift with the following code in it:

namespace php Example
service Example{
    // return current time stamp
    string showCurrentTimestamp()
     
    // wait for 10 seconds, but work asynchronously
    oneway void asynchronousJob()
}

Step 2: Generate the server and client side code in python

thrift --gen py Example.thrift

At this point, you will observe a folder with the name “gen-py” created in your current directory. Inside gen-py, you would notice that a folder with name “Example” has been created with all sorts of code.

Step3: Create Server

First, create a directory with the name “server” and go into that directory:

mkdir server

cd server

Inside this folder create a file with the name PythonServer.py and the following contents:

#!/usr/bin/env python

# This server demonstrates Thrift's connection and "oneway" asynchronous jobs
# showCurrentTimestamp : which returns current time stamp from server
# asynchronousJob() : prints something, waits 10 secs and print another string
#

port = 9090

import sys
# your gen-py dir
sys.path.append('../gen-py')

import time

# Example files
from Example import *
from Example.ttypes import *

# Thrift files
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

# Server implementation
class ExampleHandler:
    # return current time stamp
    def showCurrentTimestamp(self):
        timeStamp = time.time()
        return str(timeStamp)

    # print something to string, wait 10 secs, than print something again
    def asynchronousJob(self):
        print 'Assume that this work takes 10 seconds'
        time.sleep(10)
        print 'Job finished, but client didn\'t wait for 10 seconds'


# set handler to our implementation
handler = ExampleHandler()

processor = Example.Processor(handler)
transport = TSocket.TServerSocket("0.0.0.0", port)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()

# set server
server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)

print 'Starting server'
server.serve()

Notice that we are implementing service by the way of the class ExampleHandler.

Step 4: Now start the server:

python PythonServer.py

Step 5: Create a client

Let the server run and open a new terminal. In the new terminal follow the instructions from here onwards. Create a folder with the name “client”. Inside that folder create a file with name PythonClient.py and the following code:

#!/usr/bin/env python

# This client demonstrates Thrift's connection and "oneway" asynchronous jobs
# Client connects to server host:port and calls 2 methods
# showCurrentTimestamp : which returns current time stamp from server
# asynchronousJob() : which calls a "oneway" method
#

host = "localhost"
port = 9090

import sys

# your gen-py dir
sys.path.append('../gen-py')

# Example files
from Example import *
from Example.ttypes import *

# Thrift files
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

try:

    # Init thrift connection and protocol handlers
    transport = TSocket.TSocket( host , port)
    transport = TTransport.TBufferedTransport(transport)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)

    # Set client to our Example
    client = Example.Client(protocol)

    # Connect to server
    transport.open()

    # Run showCurrentTimestamp() method on server
    currentTime = client.showCurrentTimestamp()
    print currentTime

    # Assume that you have a job which takes some time
    # but client sholdn't have to wait for job to finish
    # ie. Creating 10 thumbnails and putting these files to sepeate folders
    client.asynchronousJob()


    # Close connection
    transport.close()

except Thrift.TException, tx:
    print 'Something went wrong : %s' % (tx.message)

Step 6: Run the client

python PythonClient.py

It should print the current time such as:

1549721664.93

It is an extremely simple example. You can extend it to add more functions and objects.

The code for the whole project is available here: https://github.com/cloudxlab/thrift-examples