今天同事試驗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應該使用在可靠性要求不高,同時對發送的速度有了解。可以保證失敗的幾率很低時。
摘自 @且聽風吟@