EOS區塊鏈究竟有幾個線程

一 nodeos工作線程

nodeso節點的工作線程包括:一個主線程,一個信號處理線程和兩個線程池。

  1. 主線程:main函數啓動線程,該線程執行完程序初始化工作後,會調用app().io_service.run(), 啓動boost::asio::io_service的異步io服務,通過異步io方式完成節點塊生產,交易處理等主要業務工作。

  2. 信號處理線程:子線程,通過異步io服務,接收系統信號並處理。
  3. 線程池,線程池啓動的工作線程數可通過啓動參數配置。

    • controller線程池: 異步執行塊block_state創建,塊中交易驗證時的交易解簽名計算。
    • 生產者插件線程池:負責異步執行交易解簽名計算。

​ 採用默認配置(每個線程池2個工作線程),nodeos節點總線程數是6個,通過pstree命令可查看:
EOS區塊鏈究竟有幾個線程

​ nodeos有一個主線程pid=32385,該主線程有5個子線程,32386~32390。

二 主線程

​ main函數執行線程:main函數最後調用app().exec(),啓動io_service服務。
EOS區塊鏈究竟有幾個線程

app()是application實例,application中定義了io_service對象io_serv:

class application
{...
   std::shared_ptr<boost::asio::io_service>  io_serv;
}
application::application():my(new application_impl()){
   io_serv = std::make_shared<boost::asio::io_service>();
}

boost::asio::io_service& get_io_service() { return *io_serv; }
//啓動io服務
void application::exec() {
   io_serv->run();
   shutdown(); 
}

void application::quit() {
   my->_is_quiting = true;
   io_serv->stop();
}
  • 其它插件通過get_io_service()函數,獲取io_serv,進行異步io投遞。
  • 程序退出時,會調用quit()函數,結束io服務。

​ nodeos節點交易處理,出塊,塊驗證等主要業務操作都是在該線程執行的,因爲eos中交易不支持並行處理,所以application中的io_serv是不允許在除主線程之外的其它線程中重複執行io_serv.run()操作的。

​ 看到application::exec()中的代碼,有些人可能會有疑問:asio::io_service監聽的io端口都完成(沒有待監聽的io端口)時,io_serv->run()就會退出。這裏io_serv->run()只調用了一次,沒有循環調用,不會退出麼?

​ nodeos投遞到application::io_serv的io處理handle函數,會重複投遞該io端口。所以在handle處理函數完成時,io_serv中總會有待完成io存在,io_serv->run()就不會退出,下面以producer_plugin中的_timer爲例,看一下這個投遞過程:

producer_plugin::producer_plugin()
   : my(new producer_plugin_impl(app().get_io_service())){
      my->_self = this;
};

class producer_plugin_impl {
  producer_plugin_impl(boost::asio::io_service& io):_timer(io),
  _transaction_ack_channel(app().get_channel<compat::channels::transaction_ack>()){} 
    boost::asio::deadline_timer   _timer;
};

​ producer_plugin()在構造時傳入app().get_io_service()構造了producer_plugin_impl:: _timer; 在節點的生產循環函數中可以看到, _timer的handle函數中會調用schedule_production_loop()函數,而在該函數中,又會調用 _timer.asyncwait()重複投遞 _timer到ioservice中:
EOS區塊鏈究竟有幾個線程

三 信號處理線程

EOS區塊鏈究竟有幾個線程

  1. 創建io_service對象sig_io_serv;
  2. 將SIGINT信號投遞到io_service對象,並綁定信號處理函數,當系統發送SIGINT信號時,會觸發該處理函數。
  3. 創建sig_thread信號處理線程,在該線程中調用sig_io_serv->run(),等待信號觸發,調用相應處理函數。
  4. 信號處理線程只處理SIGINT,SIGTERM,SIGPIPE這三個系統信號,一旦收到信號,會調用退出操作,使nodeos退出。

四 controller線程池

4.1 定義及創建

struct controller_impl {
  ...
  boost::asio::thread_pool       thread_pool;
}

controller_impl( const controller::config& cfg, controller& s  ):self(s),
    chain_id( cfg.genesis.compute_chain_id() ),
    read_mode( cfg.read_mode ),
    ...
    thread_pool( cfg.thread_pool_size )
    {...}
  • controller線程池定義在controller_impl中;
  • 根據配置參數中設定的thread_pool_size創建相應數量的工作線程。

4.2 異步任務

​ 執行塊相關操作時,較耗時且與排序無關的動作都會投遞到controller線程池執行。eos目前投遞到該線程池執行的操作有兩個:

​ 1 塊交易驗證時的解簽名操作;

​ 2 塊狀態block_state數據創建操作(兩輪共識計算都在這裏完成)。

4.2.1 解簽名操作

​ 節點收到塊,會調用apply_block()函數執行塊中交易,進行塊驗證。期間會投遞交易解簽名計算到controller線程池:
EOS區塊鏈究竟有幾個線程

​ 解簽名投遞函數create_signing_keys_futrue():
EOS區塊鏈究竟有幾個線程

  • 在線程池thread_pool中異步執行解簽名函數,異步解簽名的執行結果,會放入交易的signing_keys_future中。
  • 真正解簽名算法是trn.get_signature_keys(),解出的公鑰放到recovered_pub_keys中。
4.2.2 block_state創建

EOS區塊鏈究竟有幾個線程

五 生產者線程池

5.1 定義及創建

​ 生產者線程池定義在producer_plugin_impl中,執行插件初始化函數plugin_initialize()時會根據配置參數創建工作線程。

class producer_plugin_impl : public std::enable_shared_from_this<producer_plugin_impl> {
   public:
      void schedule_production_loop();//生產處理循環
     //線程池定義
     fc::optional<boost::asio::thread_pool>   _thread_pool;//異步線程池
    ...
}

void producer_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ 
  auto thread_pool_size = options.at( "producer-threads" ).as<uint16_t>();
  //線程池創建 
  my->_thread_pool.emplace( thread_pool_size );
}

5.2 異步任務

​ 生產者線程池負責的工作任務有兩個:

 1. 爲接收到的投遞交易進行異步解簽名計算;
 2. 等待解簽名計算完成,將交易投遞到主線程的異步io服務中處理。

​ 這兩個工作任務都在同一個函數中投遞執行:
EOS區塊鏈究竟有幾個線程

該函數在節點收到其它節點/客戶端投遞的交易時被調用:

  1. 投遞異步解簽名計算任務到 _threadpool線程池( 生產者線程池),計算結果放到

    trx->signing_keys_future中。

  2. 投遞異步任務到 _thread_pool線程池,該任務等待將異步解簽名計算結束的交易投遞到主線程的io_service中執行。

5.3 線程池關閉

​ 當調用插件shutdown函數時,會執行線程池關閉動作,前程池中的工作線程退出。
EOS區塊鏈究竟有幾個線程

六 鏈接

星河公鏈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章