Top Rated
Categories
- Git (2)
- Programming (7)
- Rails (8)
- ROR (7)
- Ruby (7)
- Thrift (1)
- Uncategorized (3)
Search with in my blog
Join 9 other subscribers
Technical Articles for RoR Developers
Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml.
Originally developed at Facebook, Thrift was open sourced in April 2007 and entered the Apache Incubator in May, 2008.
Thrift is arguably one of the best lightweight systems for cross-language programming using code-generation, RPC, and object serialization. Designed from the ground up by the Facebook development team it enables seamless integration of the most commonly used languages (Ruby, Perl, C/C++, Haskell, Python, Java, and more) via a set of common RPC libraries and interfaces.
In this post I’ll outline how to setup and connect a thrift client in ruby
To install thrift
gem install thrift
Steps:
Defining a service in Thrift
The core goal of Thrift is to enable efficient and reliable communications across multiple languages. All datatypes and services are defined in a single language-neutral file and the necessary code is auto-generated for the developer by the thrift compiler.
One of the great things about thrift is that it simplifies the communication between a client and server to a simple .thrift file. This file describes the data structures, and functions available to your remote service. In this tutorial, we use a simple calculator mechanism.
Define a struct and a service
enum BinaryOperation { ADDITION = 1, SUBTRACTION = 2, MULTIPLICATION = 3, DIVISION = 4, MODULUS = 5 } /** Structs are the basic complex data structures. They are comprised of fields * which each have an integer identifier, a type, a symbolic name, and an * optional default value. */ struct ArithmeticOperation { 1:BinaryOperation op, 2:double lh_term, 3:double rh_term, } /* Structs can also be exceptions, if they are nasty. */ exception ArithmeticException { 1:string msg, 2:optional double x, } service Calculator { /** * A method definition looks like C code. It has a return type, arguments, * and optionally a list of exceptions that it may throw. Note that argument * lists and exception lists are specified using the exact same syntax as * field lists in struct or exception definitions. */ double calc(1:ArithmeticOperation op) throws (1:ArithmeticException ae), /** * This method has an oneway modifier. That means the client only makes * a request and does not listen for any response at all. Oneway methods * must be void. * * The server may execute async invocations of the same client in parallel/ * out of order. */ oneway void run_task() }
Open a empty file and create service(copy the above code) and save it with .thrift extension(eg:calc.thrift)
We’ve defined two different functions: remote calculationand an asynchronous method call. To generate the required code, we simply call the thrift generator:
# Generate C++, Ruby, and Python implementations
# generated code will be in ‘gen-cpp’, ‘gen-rb’, ‘gen-py’ folder
thrift --gen rb calc.thrift
The beauty of this approach is, of course, the ability to mix and match implementations of services: server may be written in C++, but we can access it seamlessly via a Python, Java, or a Ruby client. Thrift will take care of the communications links, object serialization, and socket management!
Implementing a Thrift powered server in Ruby
A very simple example of interaction with a calculator server application whose actions are facilitated by thrift. Both the client and server negotiate on the common interface defined by calc.thrift.
# include thrift-generated code $:.push('../gen-rb') require 'thrift' require 'calculator' # provide an implementation of Calculator class CalculatorHandler def initialize() #nothing goes here end def calc(val) lh_term = val.lh_term rh_term = val.rh_term case val.op when 1 #Addition lh_term+rh_term when 2 #subraction lh_term-rh_term when 3 #multiplication lh_term*rh_term when 4 #division lh_term/rh_term when 5 #modulas lh_term%rh_term end end def run_task() puts "Kicking off the task" end end # Thrift provides mutiple communication endpoints # - Here we will expose our service via a TCP socket # - Web-service will run as a single thread, on port 9090 handler = CalculatorHandler.new() processor = Calculator::Processor.new(handler) transport = Thrift::ServerSocket.new(9090) transportFactory = Thrift::BufferedTransportFactory.new() server = Thrift::SimpleServer.new(processor, transport, transportFactory) puts "Starting the Calculator server..." server.serve() puts "done."
To expose our thrift service, we wrap it into a TCP socket listening on port 9090. From this point on, Thrift takes over all communications, serialization and handling of the incoming requests. Because the protocol is identical in every language, the client may be written in any language of choice.
Building the Ruby Client
You may have the client program in any language which supports Thrift.
In similar fashion, we can build a Ruby client for any Thrift service with just a few lines of code. To interface with our server implementation above, refer the following code:
# include thrift-generated code $:.push('../gen-rb') require 'thrift' require 'calculator' begin port = ARGV[0] || 9090 transport = Thrift::BufferedTransport.new(Thrift::Socket.new('localhost', 9090)) protocol = Thrift::BinaryProtocol.new(transport) client = Calculator::Client.new(protocol) transport.open() ar = ArithmeticOperation.new() ar.op = BinaryOperation::ADDITION ar.lh_term = 99 ar.rh_term = 3 # Run a remote calculation result = client.calc(ar) #it accessing the ruby server program method calc via thrift service puts result.inspect #Run a Async call client.run_task() transport.close() rescue puts $! end
And there you have it, a simple thrift client. I hope you think about thrift next time you need to interface between 2 applications, or require some kind of client->server model for your system. Thrift makes it very fast and convenient to share data across different programming languages and makes it easy/flexible to develop to a shared interface contract. Cheers!
Download Files
calc.thrift
ruby_server
ruby_client
Summary:
References: