Thrift有IPC传输实现吗?或者低延迟的SOA解决方案

8

我想将SOA引入一个低延迟系统,但不想有TCP通信的开销(即使在同一台机器上)。由于我同时拥有Java和php进程,Thrift似乎是一个很好的选择。请问是否有适用于Thrift的IPC传输实现,或者在这种情况下是否有其他好的想法?

2个回答

5

您可以使用Thrift对对象进行序列化,然后使用IPC方法(如命名管道、消息队列等)。

下面是使用管道的简单示例:

  1. 我们有一个类型为Message的对象,其中包含一些信息
  2. Php进程是消息的生产者
  3. Java进程是消费者

Thrift模型

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

生成Thrift源代码
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"

请问您能否澄清一下您的评论中所提到的“服务器方法路由”是什么意思? - gt5050
1
Thrift 提供的不仅仅是序列化,生成的代码还允许您进行客户端调用,从而在服务器上调用远程过程。我更愿意避免自己进行路由,即确定应该调用哪个方法。 - Assaf Karmon
1
Unix管道是1:1连接(每个“服务器”只有一个客户端)。域套接字更像Windows命名管道,因为它们可以支持多个连接(客户端)。虽然上面的解决方案很巧妙,但它没有利用Thrift及其分层架构的强大功能。 - pmont
你的代码似乎假定你会在消息边界上从管道中获取数据(我怀疑在实践中是否会发生这种情况)。那只是为了简单起见吗? - jtahlborn

2

关于 Thrift C++ 库的跨平台管道传输,请参见此处。这应该很容易移植到其他语言。如果你只需要支持 *NIX,可以使用域套接字(domain sockets),TSocket 已经支持。只需将 (host, port) 替换为 (name) 传递给它的构造函数即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接