今天同事试验oneway的时候,发现client发送的消息数目和server接收的不一致。自己也做了下试验。发现也是不一致。
数据结构定义如下:book.thrift
namespace cpp codelab
struct Book {
1: i32 book_id
2: string name
}
server 端 hello.thrift 定义如下:
include "book.thrift"
namespace cpp codelab_proto
service HelloBook {
oneway void ping(1: book.Book book)
}
server代码大致如下
class HelloBookHandler : virtual public HelloBookIf {
public:
HelloBookHandler() {
// Your initialization goes here
}
void ping(const codelab::Book& book) {
// Your implementation goes here
++count;
printf("book name: %s,%d\n", book.name.c_str(), count);
}
private:
static volatile int count;
};
volatile int HelloBookHandler::count = 0;
int main(int argc, char **argv) {
// create the server in a new thread
ThriftNonBlockingServerThread<HelloBookHandler, HelloBookProcessor>
thread(false, 9090, NULL);
thread.Start();
bool flag = true;
// wait forever or do anything you need to do
while (true) {
sleep(1);
if (flag) {
LOG(INFO) << "server port:" << thread.ServerPort();
flag = false;
}
}
return 0;
}
client代码大致如下:
int main(int argc, char **argv) {
base::ParseCommandLineFlags(&argc, &argv, true);
boost::shared_ptr<TSocket> socket(new TSocket("localhost", 9090));
boost::shared_ptr<TTransport> transport(new TFramedTransport(socket));
boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
HelloBookClient client(protocol);
transport->open();
Book book;
book.name = "This is a hello thrift test";
for(size_t i = 0; i < 10000; ++i) {
try{
client.ping(book);
sleep(0); // 这里是第一处A
}catch(TException& tx) {
LOG(ERROR) << "exception:" << tx.what();
transport->open();
}
}
sleep(60);//这里是第二处B
transport->close();
return 0;
}
注: 由于个人代码编译环境问题,上面的代码仅供了解逻辑,可能无法直接使用。
实现现象如下:
当thrift接口定义非oneway时,服务端收到的消息个数和客户端是一致的。
但是当定义为oneway时,有如下几种情况
注意上面有两处A和B 当A设置为大于0时, 没有B处的代码时,服务端接收到的消息个数和客户端是一致的。
当A设置为0时,而没有B处的代码时。服务端接收到的消息个数就不一致了。收到消息个数跟消息大小有关系。
当A设置为0时,同时设置B出的代码做一定的sleep。服务端接收到的消息的个数和客户端就一致了。
个人分析:
oneway的方式是客户端将消息写入本地的网络缓冲区就直接返回。是否成功发送到服务端是由网络保证的。而如果发送的速度慢。客户端直接退出了。后面的消息就会丢失。
而非oneway的方式是将消息发送给对方。服务端收到消息后,会给client端发送响应。这样就是同步的停等发送方式。
所以oneway应该使用在可靠性要求不高,同时对发送的速度有了解。可以保证失败的几率很低时。