我们目前使用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
...
答案 0 :(得分:0)
无法使用thrift,因为文件可能很大。
真正的问题是:将一个可能很大的文件完全放在线上的一个块中是一个好主意吗?您的服务已经定义了以块的形式提供文件的能力,而这正是我的提议。当然,您必须在某些时候将文件复制到内存中,但即使您只使用原始套接字也是如此:在某些时候,数据需要在内存中。
要防止大块,请限制允许的最大长度。无论是为超大请求抛出异常还是仅以某种方式指示BlockResponse
中的服务器端限制(以允许客户端清楚地区分EOF和限制)都是品味问题。我可能会使用后一种方法来防止不必要的额外往返。