PostsAboutGames

Apache Thrift - not a replacement for Protobuf *yet*

April 23, 2019 - Søren Alsbjerg Hørup

I frequently need to share typed structures between applications, such as between an ASP.NET C# Backend and an Typescript React single page application.

For this, I have used Google’s protobuf, a binary serialization library.

In protobuf, one defines the intended information in .proto files and uses a Protobuf compiler to auto generate language specific source files.

syntax = “proto3”; message Position { float x = 1; float y = 2; }

Here I define a message called Position, containing two simples float values: x and y. 1 and 2 denotes the order of which the fields appear during the serialization process - for backward compatibility reasons changing the name is allowed but changing the numbers are not since this will change the order on the wire!

Using a Protobuf compiler, such as protoc, language specific versions of the messages can be generated to fit the required language. For C#, the message above results in a class called Position with public Properties called X and Y, including several serialization methods and Properties such as WriteTo, MergeFrom and Parser.

For the web, protobufjs exists, which is a protobuf compiler implemented in JavaScript. This compiler can generate JavaScript and TypeScript source files to be consumed both in node.js and in the browser. I typically generate files for node.js and use a bundler such as parcel-bundler or webpack to bundle for the browser.

This provides binary transport of my messages from backend to frontend, with type security - very nice indeed.

Lately, I have looked into Apache Thrift, which is very similar to Protobuf but with support for many more programming languages out of the box, and with the added bonus of also supporting Remote Procedure Calls (RPC) . (although RPC can be achieved in Protobuf using gRPC)

The syntax of Thrift messages are very similar to Protobuf, the same message above would be written as:

struct Position { 1: double x, 2: double y }

Note: floats are not supported by Thrift, only doubles.

Looking at the supported languages, it seems to dwarf that of protoc (the default compiler of Protobuf) - with support for nearly 30 languages of the the box. Very nice indeed.

C# and TypeScript is also supported, making the Thrift a prime candidate for my typical needs. However, diving a bit deeper into what support means, it quickly shows that not all languages are equally supported, this includes TypeScript.

Generating browser compatible TypeScript that supports binary serialization is not supported. Node.js compatible TypeScript can be generated that supports binary serialization, but this generated code cannot be consumed by bundlers such as WebPack or Parcel Bundler. RPC is also not supported in the browser, although not required for the project in which I decided to test out Thrift.

Looking through NPM, I found “browser-thrift” - a patched version of node thrift that can be consumed by bundlers, only requiring that require(‘thrift’) is replaced with require(‘browser-thrift’) in generated thrift code.

After a few tries, I never got this approach to work and reverted back to using Protobuf.

Summary: Binary serialization is not natively supported by Thrift in the browser - making Protobuf the obvious choice until this is implemented in Thrift.