LinuxC/C++编程基础(31) 使用thrift/rpc开发简单实例(续3)

来源:互联网 发布:上海网络布线点位价格 编辑:程序博客网 时间:2024/05/08 22:56

写在前面:本篇文字在前面几篇的基础上,做了很大部分深入的改动,但thrift/rpc的通信原理是一样的

thrift-client的实现:

一.thrift_pool类:
1.TTransport类的创建,如下:
shared_ptr<TTransport> ThriftPool::CreateConnection(const string ip, int port)
{
     /*采用TCP Socket进行数据传输*/
     shared_ptr<TSocket> socket(new TSocket(ip, port));
     /*设置超时*/ 
     socket->setConnTimeout(THRIFT_TIME_OUT);
     socket->setSendTimeout(THRIFT_TIME_OUT);
     socket->setRecvTimeout(THRIFT_TIME_OUT);
     /*对Transport的数据进行buffer*/
     shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket));
     shared_ptr<TTransport> transport = bufferedSocket;
     transport->open();
     return transport;
}
2.TTransport类的关闭,如下:
void ThriftPool::TerminateConnection(shared_ptr<TTransport> transport)
{
    /*NULL_PTR即为静态的空智能指针*/
    if(transport != NULL_PTR)
    {
          transport->close();
    }
}
3.获取连接的TTransport,如下:
shared_ptr<TTransport> ThriftPool::GetConnection(const string ip, int port)
{
    shared_ptr<TTransport> conn;
    scoped_lock lock(m_mutex);

    if(conns.size() > 0)
 /*调用CreateConnection获取TTransport类的实例,这里略去*/
 /*conns的定义为queue< shared_ptr<TTransport> > conns;*/
        return conn;
    }
    else{
 /*调用CreateConnection获取TTransport类的实例,这里略去*/
 /*与上述的不同之处在与是否判断conn是否打开*/
    }
}

转载请注明出处:山水间博客,http://blog.csdn.net/linyanwen99/article/details/8510479
二.QueueWithPool类
1.消息队列的定义及读写,如下:
queue< string > msgQueue;
void QueueWithPool::pushMsg(string msg)
{
     boost::recursive_mutex::scoped_lock lock(m_queue_mutex);
     msgQueue.push(msg);
}

string QueueWithPool::popMsg()
{
      boost::recursive_mutex::scoped_lock lock(m_queue_mutex);
      string tmp_msg = msgQueue.front();//返回第一个元素
      msgQueue.pop();
      return tmp_msg;
}
2.queueMsgProcessor的实现,如下:
void QueueWithPool::queueMsgProcessor(vector<std::string> &sp_salmon_servers)
{
 bool isFirstConn = true;
 string pre_server_addr = "";
 unsigned int pre_server_count = -1;
 int pre_idx = -1;

 while (true)
 {
  /*读取消息队列中的消息并返回,实现简单,这里略去*/
  boost::xtime nowTime;
  boost::xtime_get(&nowTime, boost::TIME_UTC_);
  if (nowTime.sec - lastLogTime.sec > 10)
  {
   printf("[QueueWithPool::queueMsgProcessor] Thrift message queue[%d] left size: %u\n", id, msgQueue.size());
   lastLogTime = nowTime; // lastLogTime is the member variable
  }

  vector<std::string> ptr_salmon_servers = sp_salmon_servers;//服务器地址vector
  if (ptr_salmon_servers.size() > 0)
  {
   /* salmon_servers is an argument.  */
   int retrycount = 0;
   while (retrycount < 3)
   {
    /*根据具体策略选择服务器地址,实现简单,这里略去*/
    string server_addr = ptr_salmon_servers[idx];
    string::size_type pos = server_addr.find(':');
    if (pos != string::npos)
    {
     ip = server_addr.substr(0, pos);//解析ip地址和端口
     port = atoi(server_addr.substr(pos+1).c_str());
    }
    
    shared_ptr<TTransport> transport = thriftPool.NULL_PTR;
    try
    {
     transport = thriftPool.GetConnection(ip, port);
     if(transport == thriftPool.NULL_PTR || transport == 0x0)
     {
      printf("[QueueWithPool::queueMsgProcessor] Transport is invalid when sending thrift message\n");
      retrycount++;
      continue;
     }
     /*设置二进制的传输格式*/     
     shared_ptr<TBinaryProtocol> protocol(new TBinaryProtocol(transport));
     LinyanwenServletClient client(protocol);
     /*发送消息*/
     client.sendMessage(msg);
     printf("[QueueWithPool::queueMsgProcessor] Received msg and send to server: %s\n", msg.c_str());
     break;
    }
    catch(apache::thrift::TException e)
    {
     thriftPool.TerminateConnection(transport);
     printf("[QueueWithPool::queueMsgProcessor] Send thrift message error\n");
    }
    retrycount ++;
   }
  }
  else
  {
   printf("[QueueWithPool::queueMsgProcessor]No salmon server found!!!\n");
  }
 }
}
3.queueMsgProcessor的启动,如下:
void QueueWithPool::initialize(int qpid, vector<std::string> sp_salmon_servers, int arg_queueNum)
{
      printf("[QueueWithPool::initialize] id=%d.\n",qpid);
      id = qpid;
      queueNum = arg_queueNum;
      /*创建新线程启动*/
      boost::thread thrd(boost::bind(&QueueWithPool::queueMsgProcessor, this, sp_salmon_servers));
}

转载请注明出处:山水间博客,http://blog.csdn.net/linyanwen99/article/details/8510479
三.ServiceContainer类
1.类的定义,如下:
#ifndef _SERVICE_CONTAINER_H_
#define _SERVICE_CONTAINER_H_

#include "queue_with_pool.h"
#define QUEUE_NUM 3
class ServiceContainer{
public:
      ServiceContainer(){}
     ~ServiceContainer(){}
     void pushMsg(std::string& message);
public:
     static const int queueNum = QUEUE_NUM;
     QueueWithPool queue_pool[queueNum];
};

#endif
2.pushMsg方法的实现,如下:
void ServiceContainer::pushMsg(std::string& message){
      printf("[ServiceContainer::pushMsg]\n");
      int queue_no = 1;
      queue_pool[queue_no].pushMsg(message);
}
四.main.cpp的实现,如下:
#include <vector>
#include <string>
using boost::shared_ptr;
int main(int argc,char** argv){
      std::vector<std::string> servers;
      servers.push_back("localhost:5555");
      servers.push_back("localhost:9999");
      servers.push_back("localhost:3333");
      ServiceContainer container;
      for(int i=0;i<container.queueNum;++i){
           printf("[main] Initialize queue_pool[%d].\n",i);
           container.queue_pool[i].initialize(i,servers,container.queueNum);
      }
      while(true){
          std::string msg = "linyanwen";
          container.pushMsg(msg);
          sleep(1);
      }
      return 0;
}

 

参考文字:柳大,http://my.csdn.net/Poechant

转载请注明出处:山水间博客,http://blog.csdn.net/linyanwen99/article/details/8510479

  

原创粉丝点击