EOSIO源码分析 - Nodeos服务节点程序框架

Nodeos程序简介

Nodeos是eosio公链中最重要,最核心的程序,可以说搞定了nodeos,基本上就可以说掌握了eosio整个设计精髓。
除了nodeos程序,其他的模块都是工具或者支撑程序。
Nodeos程序可以说几乎完成了eosio公链所有的功能,核心功能总结如下:

  • 最基本的合约运行(集成Wasm虚拟机,系统合约本地运行)
  • 本地内存数据库(保存状态数据,链数据,配置数据等)
  • 账户及权限系统(内置主合约实现,权限系统)
  • 块打包与生产过程(块共识,块同步,DPOS算法等)
  • 链RestApi封装(链访问API,合约状态访问API)
  • 快照系统,实现节点快速保存,快速启动

Nodeos框架

Nodeos采用静态插件式的开发框架,核心代码结构请参考 EOSIO简介
在eosio中,所有的插件代码是通过appbase模块来组织管理与启动的,所有的插件都继承模版类plugin

template<typename Impl>
class plugin : public abstract_plugin {
   public:
      virtual void initialize(const variables_map& options) override {
        //调用插件的plugin_initialize方法完成初始化
      	static_cast<Impl*>(this)->plugin_initialize(options);
      } 
      virtual void startup() override { 
        //调用插件的plugin_startup方法启动插件
        static_cast<Impl*>(this)->plugin_startup();
      }
      virtual void shutdown() override {
        //调用插件的shutdown方法卸载插件
        static_cast<Impl*>(this)->plugin_shutdown();
      }
   protected:
      plugin(const string& name) : _name(name){}
   private:
      state _state = abstract_plugin::registered;
      std::string _name;
};
class abstract_plugin {
  public:
  	 ...
  	 // 插件参数注册函数
     virtual void set_program_options( options_description& cli, options_description& cfg ) = 0;
     // 插件初始化函数
     virtual void initialize(const variables_map& options) = 0;
     // 插件启动函数
     virtual void startup() = 0;
     // 插件退出函数
     virtual void shutdown() = 0;
};

接下来,继续看application类的实现

class application {
private:
	map<string, std::unique_ptr<abstract_plugin>> plugins; ///< all registered plugins
    vector<abstract_plugin*>                  initialized_plugins; ///< stored in the order they were started running
    vector<abstract_plugin*>                  running_plugins; ///< stored in the order they were started running
    std::function<void()>                     sighup_callback;
    map<std::type_index, erased_method_ptr>   methods;
    map<std::type_index, erased_channel_ptr>  channels;
    std::shared_ptr<boost::asio::io_service>  io_serv;
    execution_priority_queue                  pri_queue;
}

从上面的application的代码中,得到两个最重要的信息

  • application全局管理了所有的注册的插件
  • application提供了插件之间通信机制

Nodeos启动过程

所有C++程序的启动都是从main函数开始的,所以Nodeos也不例外,其启动过程依次如下

int main(int argc, char** argv) {
	//调用app.initialize函数直接默认初始化链,网络,生产插件
	if(!app().initialize<chain_plugin, net_plugin, producer_plugin>(argc, argv)) {
        const auto& opts = app().get_options();
        if( opts.count("help") || opts.count("version") || opts.count("full-version") || opts.count("print-default-config") ) {
           return SUCCESS;
        }
        return INITIALIZE_FAIL;
     }
    //启动已经注册的插件
	app().startup();
	//程序开始运行
    app().exec();
}

接下来依次展开app的initialize,startup函数如下

// 利用变参函数,动态初始化需要的插件
template<typename... Plugin>
bool                 initialize(int argc, char** argv) {
   return initialize_impl(argc, argv, {find_plugin<Plugin>()...});
}

// 具体初始化在函数initialize_impl中完成
bool application::initialize_impl(int argc, char** argv, vector<abstract_plugin*> autostart_plugins) {
   // 注册插件的启动参数
   set_program_options();
   // 初始化基本参数
   ...
   // 调用initialize函数,逐个初始化每个插件
   try {
      for (auto plugin : autostart_plugins)
         if (plugin != nullptr && plugin->get_state() == abstract_plugin::registered)
            plugin->initialize(options);

      bpo::notify(options);
   } catch (...) {
      std::cerr << "Failed to initialize\n";
      return false;
   }
}
void application::startup() {
   // 按顺序逐个启动每个插件
   try {
      for( auto plugin : initialized_plugins ) {
         if( is_quiting() ) break;
         plugin->startup();
      }
   } catch( ... ) {
      clean_up_signal_thread();
      shutdown();
      throw;
   }
}

接下来逐个分析每个插件的plugin_initialize,plugin_startup方法就可以了解在程序启动时,都具体做了哪些事情

总结

  • nodeos中chain,net,producer插件是默认启动的,其他的插件需要配置才能启动
  • nodeos程序中最重要的插件是chain,producer两个插件,chain负责链启动,访问等,producer负责块生产
  • 如果是单点完全可以不用启动net插件,但是区块链是多点共识,所以一般至少会启动三个节点,net插件是必须的
  • 要通过API访问链,需要配置chain_api_plugin插件,net插件通过api控制需要配置net_api_plugin插件
  • application除了管理插件,最重要的就是实现了高效快捷的插件事件机制,application值得我们学习

猜你喜欢

转载自blog.csdn.net/whg1016/article/details/129773463
今日推荐