使用Finagle直接ByteBuffers in Thrift

时间:2014-08-01 18:41:32

标签: thrift finagle twitter-finagle

我们目前使用thrift服务器为我们的RPC。我们希望支持的其中一个调用想要将读取文件的结果返回到直接的ByteBuffer。 THRIFT-883表示不支持(因为不支持ByteBuffer.array()),所以如果我们切换到finagle,我们是否想支持直接的ByteBuffers?

finagle是否克服了这个限制,还是面临这个限制?

示例代码:

节俭

struct BlockRequest {
  1: i64 blockId,
  2: i64 offset,
  3: i64 len
}

struct BlockResponse {
  1: i64 blockId
  2: i64 offset
  3: i64 len
  4: binary data
}

service DataService {
  BlockResponse requestBlock(1: BlockRequest request)
    throws (1: BlockInfoException bie, 2: FileDoesNotExistException fdne)
}

爪哇

  @Override
  public BlockResponse requestBlock(BlockRequest request) throws BlockInfoException,
      FileDoesNotExistException, TException {

    final long blockId = request.blockId;
    final long offset = request.offset;
    final long len = request.len;
...

    final RandomAccessFile file = new RandomAccessFile(filePath, "r");
    long fileLength = file.length();
    final long readLen;
    if (len == -1) {
      readLen = fileLength - offset;
    } else {
      readLen = len;
    }

    FileChannel channel = file.getChannel();
    final MappedByteBuffer data = channel.map(FileChannel.MapMode.READ_ONLY, offset, readLen);

    final BlockResponse response = new BlockResponse();
    response.setBlockId(blockId);
    response.setOffset(offset);
    response.setLen(readLen);
    response.setData(data);

    return response
...

1 个答案:

答案 0 :(得分:0)

  

无法使用thrift,因为文件可能很大。

真正的问题是:将一个可能很大的文件完全放在线上的一个块中是一个好主意吗?您的服务已经定义了以块的形式提供文件的能力,而这正是我的提议。当然,您必须在某些时候将文件复制到内存中,但即使您只使用原始套接字也是如此:在某些时候,数据需要在内存中。

要防止大块,请限制允许的最大长度。无论是为超大请求抛出异常还是仅以某种方式指示BlockResponse中的服务器端限制(以允许客户端清楚地区分EOF和限制)都是品味问题。我可能会使用后一种方法来防止不必要的额外往返。