稍微进阶点的搞实验中的杂谈(一)—— 主要关于boost asio例程2,多个io_service的server,例程3,多个线程一个io_service

在看第二个例程,额,第一个例程也花得够多时间的,不过我觉得还是值得,毕竟把基本的框架都搭建了起来,就差个多线程了,还自己写了很多补充的方法,定义了我要用到的请问的报文格式,嗯嗯,今天杭州天气不错的。

 

这个server2的例程的话,其实改动不大,它的标题是one io_service per cpu,其实大部分的源文件还是跟server1的一样的,主要就是用一个叫 io_service_pool的类代替了原本的connection_manager,这个类就是用来管理一堆Io_service的,主要核心的变量我暂时一眼看出应该就是这三个吧:

private:
  typedef boost::shared_ptr<boost::asio::io_service> io_service_ptr;
  typedef boost::shared_ptr<boost::asio::io_service::work> work_ptr;

  /// The pool of io_services.
  std::vector<io_service_ptr> io_services_;

  /// The work that keeps the io_services running.
  std::vector<work_ptr> work_;

  /// The next io_service to use for a connection.
  std::size_t next_io_service_;

然后相应地,server类也要做一点点改动,总之就是,外部负责与客户端打交道的逻辑稍微改变下,因为要处理多个io_service也就是要多个Connection,但是内部处理request啊怎样handle read和wirte的,还是没变的

 

然后这个work的作用我特意查了下,这个朋友说得简单明了的,大概理解了:http://www.cnblogs.com/hurricane2011/articles/2384437.html

让io保持繁忙,呵呵,不让退出,除非io.stop()执行。

然后server端其实就是每次接到i请求的话,就会一个线程来应答这个请求,而这个线程其实是事先生成好的,每个线程负责在跑着一个ioservice:

void io_service_pool::run()
{
  // Create a pool of threads to run all of the io_services.
  std::vector<boost::shared_ptr<boost::thread> > threads;
  for (std::size_t i = 0; i < io_services_.size(); ++i)
  {
    boost::shared_ptr<boost::thread> thread(new boost::thread(
          boost::bind(&boost::asio::io_service::run, io_services_[i])));
    threads.push_back(thread);
  }

  // Wait for all threads in the pool to exit.
  for (std::size_t i = 0; i < threads.size(); ++i)
    threads[i]->join();
}

而在io_service_pool对象构造函数执行的时候,已经有了一堆的io_service(用智能指针去指向它),每个指针都被work来搞得在忙了:

io_service_pool::io_service_pool(std::size_t pool_size)
  : next_io_service_(0)
{
  if (pool_size == 0)
    throw std::runtime_error("io_service_pool size is 0");

  // Give all the io_services work to do so that their run() functions will not
  // exit until they are explicitly stopped.
  for (std::size_t i = 0; i < pool_size; ++i)
  {
    io_service_ptr io_service(new boost::asio::io_service);
    work_ptr work(new boost::asio::io_service::work(*io_service));
    io_services_.push_back(io_service);
    work_.push_back(work);
  }
}

那个next_io_service就是一个普通的int用来实现最简单的round robin,每次就加+1,用来指派下一个线程,从get_io_service方法中搞的。

 

ok了,其他没什么特别的,总的来说再啰嗦一次,就是有一个类维护了一个vector的ioservice和实现了一个计数器,用来每次取出不同的ioservice来应答server端发过来的请求,不过貌似挺占内存的…不知道呢,进入到真正多现场的server3例程吧!

 

然后看了下例程三,貌似也什么太多新意的地方…只是这次它是在server类里面,维护了一个vector<boost::shared_ptr<boost::thread>> threads,然后对比起,例程2的server::run,例程2直接调用了io_service_pool的run,启动多个线程然后每个线程分别运营着一个io_service,而例程三就直接是这样:

void server::run()
{
  // Create a pool of threads to run all of the io_services.
  std::vector<boost::shared_ptr<boost::thread> > threads;
  for (std::size_t i = 0; i < thread_pool_size_; ++i)
  {
    boost::shared_ptr<boost::thread> thread(new boost::thread(
          boost::bind(&boost::asio::io_service::run, &io_service_)));
    threads.push_back(thread);
  }

  // Wait for all threads in the pool to exit.
  for (std::size_t i = 0; i < threads.size(); ++i)
    threads[i]->join();
}

这个io_service依然是server类制剂的私有变量,然后值得一提的是在connnection类里面,多了这个:

 /// Strand to ensure the connection's handlers are not called concurrently.
  boost::asio::io_service::strand strand_;

这个如果没记错的话就是boost里面用来保证线程之间的安全的,反正在connection的方法里面,凡是有asyncread或者write的话,都要用strand把bind方法来wrap一下,就比如这样:

if (result)
    {
      request_handler_.handle_request(request_, reply_);
      boost::asio::async_write(socket_, reply_.to_buffers(),
          strand_.wrap(
            boost::bind(&connection::handle_write, shared_from_this(),
              boost::asio::placeholders::error)));
    }

 

然后看了其他的类,都没什么变化了,唯一区别就在这里了,看来这篇可以这么完结了,接下来好好想想怎样想想写好服务端的多线程框架然后测试下吧,两台机子这样。

 

posted @ 2013-11-28 11:06  Allen_Tung  阅读(1218)  评论(0编辑  收藏  举报