8

I want to introduce SOA to a low latency system without the overhead of TCP communication(even on the same machine). Thirft seems like a great fit as I have both Java and php processes. Is there an IPC transport implementation for thrift, or any other good idea that could help in this scenario?

rid
  • 61,078
  • 31
  • 152
  • 193
Assaf Karmon
  • 915
  • 1
  • 10
  • 23

2 Answers2

5

You could use Thrift to serialize your objects and then use IPC method of your liking(named pipe,message queues etc). The following is a simple example using pipes

  1. We have a an object of type Message which contains some information
  2. Php process is the producer of the message
  3. Java process is the consumer

Thrift model

struct Message {
  1: i32 uid,
  2: string information,
}

generate thrift sources

thrift --gen java message.thrift
thrift --gen php message.thrift

PHP producer

<?php
$GLOBALS['THRIFT_ROOT'] = 'src';
require_once $GLOBALS['THRIFT_ROOT'].'/Thrift.php';
require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinarySerializer.php'; // this generates serialized string from our obect
require_once $GLOBALS['THRIFT_ROOT'].'/packages/message/message_types.php'; //from generated thrift sources
//create new message
$message = new Message();
$message->uid = '1';
$message->information = 'Some info';
var_dump($message);

//serialize
$serializer = new TBinarySerializer(); 
$serialized_message = $serializer->serialize($message);
var_dump($serialized_message);

//write to a pipe
if (pcntl_fork() == 0) {
$namedPipe = '/tmp/pipe';
if (! file_exists($namedPipe)) {
   posix_mkfifo($namedPipe, 0600);
}

$fifo = fopen($namedPipe, 'w');

fwrite($fifo, $serialized_message);
exit(0);
}
?>

Java Consumer

        //read from pipe
    FileInputStream fileInputStream = new FileInputStream(new File("/tmp/pipe"));
    int availableBytes = fileInputStream.available();

    byte[] b = new byte[availableBytes]; 
        fileInputStream.read(b , 0, availableBytes);
        //deserialize
    TDeserializer tDeserializer = new TDeserializer();
    Message deserMessage = new Message();
    tDeserializer.deserialize(deserMessage, b);
    System.out.println(deserMessage.getInformation());
    //prints "Some info"
Greg Kopff
  • 15,945
  • 12
  • 55
  • 78
gt5050
  • 561
  • 6
  • 12
  • Could you please clarify your comment "server method routing" . – gt5050 May 21 '12 at 15:19
  • 1
    Thrift offers more than just serialization, the generated code allows you to make a client call that will invoke a remote procedure on the server. I rather avoid doing the routing, i.e which method should be invoked, myself. – Assaf Karmon May 21 '12 at 16:23
  • 1
    Unix pipes are 1:1 connections (only one client per 'server'). Domain sockets are more like Windows Named Pipes in that they can support multiple connections (clients). While the solution above is ingenious, it doesn't leverage the power of Thrift and its layered architecture. – pmont Jun 09 '12 at 18:54
  • your code seems to assume that you will get data from the pipe on message boundaries (which i doubt would happen in practice). was that just for simplicity of example? – jtahlborn Jun 11 '12 at 18:59
2

See here regarding a cross-platform pipe transport for the Thrift C++ library. This should be straight-forward to port to the other languages. If you only need to support *NIX, you could use domain sockets which is already supported by TSocket. Simply pass in (name) instead of (host, port) to its constructor.

Community
  • 1
  • 1
pmont
  • 2,083
  • 22
  • 43