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 )
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();
}
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)
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)
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 ) );
}
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を抽出して実行し続ける.