让我说我定义了以下Thrift服务
service FileResource {
binary get_file(1:string file_name)
}
以下是生成的实现,我无法理解
public ByteBuffer recv_get_file() throws org.apache.thrift.TException
{
org.apache.thrift.protocol.TMessage msg = iprot_.readMessageBegin();
if (msg.type == org.apache.thrift.protocol.TMessageType.EXCEPTION) {
org.apache.thrift.TApplicationException x = org.apache.thrift.TApplicationException.read(iprot_);
iprot_.readMessageEnd();
throw x;
}
if (msg.seqid != seqid_) {
throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.BAD_SEQUENCE_ID, "get_file failed: out of sequence response");
}
get_file_result result = new get_file_result();
result.read(iprot_);
iprot_.readMessageEnd();
if (result.isSetSuccess()) {
return result.success;
}
throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "get_file failed: unknown result");
}
如何使用字符串
result.read(iprot_);
? 是同步还是异步?它如何适用于大数据(几兆字节以上)? 我需要阅读那些数据? 不幸的是,我不习惯使用java.nio和ByteBuffer。任何示例或指南都会很好。
答案 0 :(得分:3)
我认为你误解了Apache Thrift的用途。如果这很复杂,Java NIO会更容易......
它如何适用于大数据(几兆字节以上)?
Thrift应该为您传输这些数据。性能如何?这在很大程度上取决于您的硬件和网络质量。 Thrift has a pretty good performance
我需要阅读这些数据吗?
在Java Thrift客户端中,您可以执行
TTransport transport;
transport = new TSocket("yourServerHostNameOrIPAddress", serverPort);
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
ChunkFileResourceThrift.Client client = new ChunkFileResourceThrift.Client(protocol);
ByteBuffer buffer = client.get_file(yourFileName);
// Do whatever you want with the byte buffer
transport.close();
是同步还是异步?
如果您在 .thrift 文件中将其定义为oneway
,则它是异步的,否则它是同步的。因此,在您的情况下,它是同步的。
必须实现网络低级细节完全胜过使用Thrift的目的。精确使用节俭,你可以忘记这些细节。
答案 1 :(得分:-4)
最后,我成功地将文件从服务器传输到客户端。我扩展了Thrift自动生成的客户端和处理器类。它让我可以访问TProtocol对象。这又允许发送/接收任意数据流 我相信我的解决方案非常粗糙。如果有人指出我如何按照Thrift架构实现它会很好。通过实现自定义Thrift协议可以更好地完成吗?
客户端:
package alehro.droid;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TProtocol;
import alehro.log.Logger;
import alehro.tcp.ChunkFileResourceThrift;
import alehro.tcp.ServerSideError;
class ThriftClientExt extends ChunkFileResourceThrift.Client {
public ThriftClientExt(TProtocol prot) {
super(prot);
}
public void recv_get_file_ext(String get_file_out_path) throws TException,
IOException, ServerSideError {
FileOutputStream fos = new FileOutputStream(get_file_out_path);
FileChannel channel = fos.getChannel();
int size = 0;
// -1 - end of file, -2 exception.
while ((size = iprot_.readI32()) > 0) {
Logger.me.v("receiving buffer size=" + size);
ByteBuffer out = iprot_.readBinary();
// out.flip();
channel.write(out);
}
if (size == -2) {
String msg = iprot_.readString();
Logger.me.e("Server error: " + msg);
// TODO: report error to user
}
channel.close();
recv_get_file();
}
}
服务器:
package alehro.tcp;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TProtocol;
import alehro.log.Logger;
import alehro.tcp.ChunkFileResourceThrift.Iface;
import alehro.tcp.ChunkFileResourceThrift.get_file_args;
import alehro.tcp.ChunkFileResourceThrift.get_file_result;
public class ChunkedFileResourceProcessor extends
ChunkFileResourceThrift.Processor {
public interface IfaceExt extends Iface {
void get_file_raw(String key, String file_name, TProtocol out)
throws TException, ServerSideError;
}
final private IfaceExt iface_1;
public ChunkedFileResourceProcessor(IfaceExt iface) {
super(iface);
iface_1 = iface;
// replace generated implementation by my custom one.
processMap_.put("get_file", new get_file_raw());
}
private class get_file_raw implements ProcessFunction {
@Override
public void process(int seqid, TProtocol iprot, TProtocol oprot)
throws TException {
get_file_args args = new get_file_args();
try {
args.read(iprot);
} catch (org.apache.thrift.protocol.TProtocolException e) {
iprot.readMessageEnd();
org.apache.thrift.TApplicationException x = new org.apache.thrift.TApplicationException(
org.apache.thrift.TApplicationException.PROTOCOL_ERROR,
e.getMessage());
oprot.writeMessageBegin(new org.apache.thrift.protocol.TMessage(
"get_file",
org.apache.thrift.protocol.TMessageType.EXCEPTION,
seqid));
x.write(oprot);
oprot.writeMessageEnd();
oprot.getTransport().flush();
return;
}
iprot.readMessageEnd();
get_file_result result = new get_file_result();
try {
iface_1.get_file_raw(args.key, args.file_name, oprot);
} catch (ServerSideError ouch) {
result.ouch = ouch;
} catch (Throwable th) {
Logger.me.e("Internal error processing get_file_raw");
Logger.me.e(th.getMessage());
Logger.me.e(th);
org.apache.thrift.TApplicationException x = new org.apache.thrift.TApplicationException(
org.apache.thrift.TApplicationException.INTERNAL_ERROR,
"Internal error processing get_file");
oprot.writeMessageBegin(new org.apache.thrift.protocol.TMessage(
"get_file",
org.apache.thrift.protocol.TMessageType.EXCEPTION,
seqid));
x.write(oprot);
oprot.writeMessageEnd();
oprot.getTransport().flush();
return;
}
oprot.writeMessageBegin(new org.apache.thrift.protocol.TMessage(
"get_file", org.apache.thrift.protocol.TMessageType.REPLY,
seqid));
result.write(oprot);
oprot.writeMessageEnd();
oprot.getTransport().flush();
}
}
}
服务器处理程序:
public class ChunkedFileResourceHandler implements
ChunkedFileResourceProcessor.IfaceExt {
....
@Override
public void get_file(String key, String file_name) throws TException {
// stub
throw new TException("Wrong call. Use get_file_raw instead.");
}
@Override
public void get_file_raw(String key, String file_name, final TProtocol out)
throws ServerSideError, TException {
// catch all here. mimic original get_file throw politics.
try {
Logger.me.v("Begin get_file_raw");
UserSession se = accessUserSession(key, "get", 0, 0);
vali(se != null);
synchronized (se) {
String fullPath = "";
Logger.me.i("get file start: " + file_name);
String userDir = AppConfig.getUserDir(se.info.email);
fullPath = userDir + file_name;
final FileInputStream inputFile;
ByteBuffer buffer = null;
int bytesRead = -1;
FileChannel fileChannel = null;
inputFile = new FileInputStream(fullPath);
fileChannel = inputFile.getChannel();
buffer = ByteBuffer.allocate(2048);
bytesRead = fileChannel.read(buffer);
// Logger.me.v("start sending file");
while (bytesRead != -1) {
buffer.flip();
int length = buffer.limit() - buffer.position()
- buffer.arrayOffset();
Logger.me.v("sending buffer length=" + length);
out.writeI32(length); // read it in client
out.writeBinary(buffer); // read it in client
buffer.clear();
bytesRead = fileChannel.read(buffer);
}
out.writeI32(-1); // read it in client
Logger.me.i("get file end.");
}
} catch (TException e) {
throw e;
} catch (Throwable e) {
write_get_file_exception(file_name, e, out);
return;
}
}
void write_get_file_exception(String file, Throwable e, final TProtocol out)
throws TException {
out.writeI32(-2);
out.writeString("Exception in get_file_raw: file=" + file
+ "description=" + e.getMessage());
Logger.me.e(e);
Logger.me.i("get file ended wtih errors: " + e.getMessage());
}
}