EOSシリーズ-ソース分析-EOSスレッドメカニズム


EOSにはいくつかのスレッドがあります


Nodesoノードの動作スレッドには、1つのプライマリスレッド、1つの信号処理スレッド、および4つのスレッドプールが含まれる。

nodeos(10265  & ) :  io  `epoll_wait` |  
	─┬─{nodeos}(10311 controller _1:  block_state , )
      ├─{nodeos}(10312 controller _2)
      ├─{nodeos}(10314 producer_plugin _1:  )
      ├─{nodeos}(10315 producer_plugin _2)
      ├─{nodeos}(10317 http_plugin _1: http )
      ├─{nodeos}(10318 http_plugin _2)
      └─{nodeos}(10319 net_plugin _1: p2p )
  • メインスレッド:main関数起動スレッド、このスレッドはプログラム初期化作業を実行した後、app().io_service.run()を呼び出し、boost::asio::io_serviceの非同期ioサービスを起動し、非同期io方式でノードブロック生産、取引処理などの主要業務を完成する.
    void application::exec() {
           
    boost::asio::io_service::work work(*io_serv);
    (void)work;
    bool more = true;
    while( more || io_serv->run_one() ) {
           
      	while( io_serv->poll_one() ) {
           }
      	// execute the highest priority item
      	more = pri_queue.execute_highest();
    }
    
    shutdown(); /// perform synchronous shutdown
    io_serv.reset();
    }
    
  • eosでのトランザクションはパラレル処理をサポートせず、プライマリ・スレッド以外のスレッドでio_を繰り返し実行することは許可されません.serv.run()動作
    boost::asio::io_service& get_io_service() {
              return *io_serv; }
    
    producer_plugin::producer_plugin()
    : my(new producer_plugin_impl(app().get_io_service())){
              //   app().get_io_service()
    	my->_self = this;
    }
    
    producer_plugin_impl(boost::asio::io_service& io)
    	:_timer(io)
    
  • 信号処理スレッド:サブスレッド、非同期ioサービスにより、システム信号を受信し、処理する.
     boost::asio::io_service startup_thread_ios;     // 
    setup_signal_handling_on_ios(startup_thread_ios);
    std::thread startup_thread([&startup_thread_ios]() {
           
      	startup_thread_ios.run();
    });
    
    void application::setup_signal_handling_on_ios(boost::asio::io_service& ios, bool startup) 
    
  • スレッドプール、スレッドプールで起動された作業スレッド数は、起動パラメータによって構成できます.(デフォルトプール内の2つのワークスレッド)
    struct controller_impl {
           
    ...
    boost::asio::thread_pool       thread_pool; // 
    }
    
    controller_impl( const controller::config& cfg, controller& s  ){
           
    ...
    thread_pool( cfg.thread_pool_size )
    }
    
  • controllerスレッドプール:非同期実行ブロックblock_state作成、ブロック内の取引検証時の取引解署名計算.ブロック関連操作を実行すると、時間がかかり、ソートに関係のない動作がcontrollerスレッドプールに送信されます.
  • ブロック取引検証時の署名解除操作(ノード受信ブロック)
    //  , apply_block()  , 
    void apply_block( const block_state_ptr& bsp, controller::block_status s ) {
               
    ...
    transaction_metadata::start_recover_keys( mtrx, thread_pool, chain_id, microseconds::maximum() ); 
    }
    
    // `thread_pool` , ,  `signing_keys_future`  
    //  trn.get_signature_keys(), recovered_pub_keys 。
    signing_keys_future_type transaction_metadata::start_recover_keys( const transaction_metadata_ptr& mtrx,
                                                           boost::asio::thread_pool& thread_pool,
                                                           const chain_id_type& chain_id,
                                                           fc::microseconds time_limit )
    
  • ブロック状態block_stateデータ作成操作(2回の共通認識計算はすべてここで完了)
  • producer_pluginスレッドプール:非同期で取引解署名計算を実行します.
    void producer_plugin::plugin_initialize(const boost::program_options::variables_map& options){
             
    ...
    my->_thread_pool.emplace( thread_pool_size );
    }
    
  • 受信送信取引の非同期解署名計算(ノードが他のノード/クライアントブロードキャストの取引を受信したときに呼び出される)
    void on_incoming_transaction_async(const transaction_metadata_ptr& trx, bool persist_until_expired, next_function<transaction_trace_ptr> next) {
               
    	signing_keys_future_type future = transaction_metadata::start_recover_keys( trx, _thread_pool->get_executor(),
       chain.get_chain_id(), fc::microseconds( cfg.max_transaction_cpu_usage ) );
    }
    
  • .
  • は、解署名計算が完了するのを待って、トランザクションをプライマリスレッドの非同期ioサービスに送信して処理する.
    boost::asio::post( *_thread_pool, [self = this, future, trx, persist_until_expired, next]() {
               
    			if( future.valid() )
       				future.wait();
    				app().post(priority::low, [self, trx, persist_until_expired, next]() {
               
       				self->process_incoming_transaction_async( trx, persist_until_expired, next );
    			});
    	});
    

  • http_pluginスレッドプール:httpのresponseをマルチスレッドoptional<:asio::thread_pool> thread_pool
  • に変更
  • net_pluginスレッドプールoptional<:asio::thread_pool> thread_pool

  • EOS非同期フレームワークboost::asio


    EOS非同期フレームワークは、タスクキューを実装し、キューにpostタスクを実行することによって実現され、消費者はtaskを抽出して実行し続ける.

    boost::asio

  • オペレーティングシステムに基づいて提供される非同期メカニズム(下層にselect/epoll/kqueue/overlappedがカプセル化され、様々なオペレーティングシステムに適用される)であり、フロントカメラ設計モードを用いて移植可能な非同期動作を実現する.
  • postによってタスクを追加し、runはタスクを実行する.