Apache Thrift journey on .NET

I needed fast protocol for cross-process communication. There are many options, and Apache Thrift one of them. So I decided to give it a try. This is quote from project site:

The Apache Thrift software framework, for scalable cross-language services development, 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, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages.

How to start

First thing to know is that Thrift has simple DSL to define contracts and called the Thrift interface description language (IDL). DSL is quite powerful and self explanatory. Most easy way to get familiar with syntax is to read tutorial.thift. Another place to learn it IDL page. For playing purposes you may end with something like this (default file extension is .thrift):

namespace csharp PlayWithThrift.Contracts

struct Work {
  1: i32 num1 = 0
  2: i32 num2
  3: optional string comment
}

service Calculator {   
   i32 add(1:Work work)   
}

Save this to something like test.thrift. IDL file can also have service(RPC) definitions, enums, namespaces and constants. You can use inheritance and include other thrift files.

Second is how to turn IDL file to something that can work. Thrift uses code generation to produce DTOs, serializers for them, client and server classes. To generate code Apache Thrift compiler is necessary. You can download one from downloads page. Or if you have Chocolatey installed, just use:

cinst thrift

This will add thrift to your PATH, so you can just use thrift executable form anywhere. So to compile our test.thrift execute:

thrift --gen csharp test.thrift

Result will be in gen_csharp folder. I should say result is ugly, but a bit later on this.

Now, third. Now when we have code in place, lets make it dance.  First of all you need implementation of the server side. It uses ugly named interfaces, but let us pretend that all is good. We have only one method defined and so has implementation:

public class CalculatorHandler : Calculator.Iface
{
    public int add(Work work)
    {
        Console.WriteLine("add({0},{1}) // {2}", 
            work.Num1, work.Num2, work.Comment);
        return work.Num1 + work.Num2;
    }
}

Now it is time to start serving stuff to the wire!

try
{
    var handler = new CalculatorHandler();
    var processor = new Calculator.Processor(handler);
    var serverTransport = new TServerSocket(9090);
    var server = new TSimpleServer(processor, serverTransport);

    // Use this for a multithreaded server
    // server = new TThreadPoolServer(processor, serverTransport);

    server.Serve();
}
catch (Exception ex)
{
    Console.WriteLine(ex);
}

And finally client part:

using (var transport = new TSocket("localhost", 9090))
{
    var protocol = new TBinaryProtocol(transport);
    var client = new Calculator.Client(protocol);

    transport.Open();

    var sum = client.add(new Work
    {
        Num1 = 12,
        Num2 = 13
    });
    Console.WriteLine("12+13={0}", sum);    
}

 

Troubleshooting

When run compiler, you might get error:

[ERROR:C:/Users/Mike/Projects/PlayWithThrift/PlayWithThrift/ContractMsg.thrift:1] (last token was ‘∩’)

Unexpected token in input: "∩"

It looks like this means that you have unsupported encoding for thrift file. Change it to something without signature fixes the problem.

Main problems

  1. Generated code is awful, strange naming conventions, strange base classes. Lack of correct capitalization. And T prefix – it probably means Thrift, but for me it reminds Delphi. Async code is generated only under SILVERLIGT symbol.
  2. Lack of UTF-8 support for .thrift files
  3. Looks like implementation is blocking

Conclusion

There is no love at first sight. Usability is quite good, but implementation kills the whole idea. I will try to find better implementations for my needs. Next is probably protobuf.

Please note, Apache Thrift project permanently moves all things around. So many links to tutorials, readmes repositories may not be available at the time of reading. Ping me with any problem, I will update post.

Advertisements
Tagged

4 thoughts on “Apache Thrift journey on .NET

  1. Bruno Juchli says:

    Thanks.
    What did you end up using for RPC?

    • Mike Chaliy says:

      We postponed protocol migration that time, so project I was prototyping Thift for, is still HTTP based.

      • lsem says:

        Worth to try gRPC as Thrift replacement due to the fact it uses http2 for transport purposes. The latter has such an essential feature for asynchronous RPC via HTTP as channel multiplexing.

  2. lsem says:

    Recently released gRPC looks very promising due to Http2 which has very essential features for RPC over hypertext transport.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s