当前位置:网站首页>[Sylar] framework -chapter24- support business modularization
[Sylar] framework -chapter24- support business modularization
2022-07-28 04:33:00 【Jianghu people call it pineapple bag】
Standing on the shoulders of giants
Rewrite from scratch sylar C++ High performance distributed server framework
summary
- sylar How does the framework do some small projects ? Directly from main Function begins .
- sylar Our approach is to encapsulate businesses into dynamic libraries one by one , Load from the framework .
sylar Start process
main function
↓
Application Of init( read configuration file , Read the storage path of the business dynamic library )
↓
ModuleManager Of init( Every so Library order initModule)
↓
ModuleManager::initModule( call Library Of GetModule, And cache it )
↓
Library Of GetModule(dlopen Load dynamic library , and CreateModule)
↓
go back to main function ,Application Start run( In fact, in the end Application::run_fiber)
↓
Application Of run_fiber( According to the configuration , Initialize each server)
↓
Finally, wait for the connection
Start of business module
Externally exported "CreateModule" Interface instantiates the module
↓
Application Of init At the end of the function, each Module Of onServerReady function
↓
Module Of onServerReady Register your own business module Servlet( Instantiate and cache )
↓
Application Once the initialization is complete , Start monitoring socket Connect , If there's a connection coming in , Finally, call the corresponding Servlet Of handle Method .
↓
In the business module itself Servlet Of handle Method to implement the corresponding business logic
Other instructions
- Every business dynamic library has "CreateModule" and "DestoryModule" Two interfaces ,extern "C" export .
// You can use the following command to view the interface : nm -D libparamquery.so // without extern "C", The exported function name, for example : _ZTIN5sylar12SocketStreamE // If there is extern "C", The exported function name, for example : testFunc - main The function is in the framework , Not in the business module .
Some related codes
// main.cc
#include "sylar/application.h"
#include <stdlib.h>
#include <time.h>
int main(int argc, char** argv)
{
setenv("TZ", ":/etc/localtime", 1);
tzset();
srand(time(0));
sylar::Application app;
if(app.init(argc, argv))
{
return app.run();
}
return 0;
}
// module.h
#ifndef __SYLAR_MODULE_H__
#define __SYLAR_MODULE_H__
#include "sylar/stream.h"
#include "sylar/singleton.h"
#include "sylar/mutex.h"
#include "sylar/protocol.h"
//#include "sylar/rock/rock_stream.h"
#include <map>
#include <unordered_map>
namespace sylar
{
class Module {
public:
enum Type {
MODULE = 0,
// ROCK = 1,
};
typedef std::shared_ptr<Module> ptr;
Module(const std::string& name
, const std::string& version
, const std::string& filename
, uint32_t type = MODULE);
virtual ~Module() {}
virtual void onBeforeArgsParse(int argc, char** argv);
virtual void onAfterArgsParse(int argc, char** argv);
virtual bool onLoad();
virtual bool onUnload();
virtual bool onConnect(sylar::Stream::ptr stream);
virtual bool onDisconnect(sylar::Stream::ptr stream);
virtual bool onServerReady();
virtual bool onServerUp();
virtual bool handleRequest(sylar::Message::ptr req
, sylar::Message::ptr rsp
, sylar::Stream::ptr stream);
virtual bool handleNotify(sylar::Message::ptr notify
, sylar::Stream::ptr stream);
virtual std::string statusString();
const std::string& getName() const { return m_name; }
const std::string& getVersion() const { return m_version; }
const std::string& getFilename() const { return m_filename; }
const std::string& getId() const { return m_id; }
void setFilename(const std::string& v) { m_filename = v; }
uint32_t getType() const { return m_type; }
//void registerService(const std::string& server_type
// , const std::string& domain
// , const std::string& service);
protected:
std::string m_name;
std::string m_version;
std::string m_filename;
std::string m_id;
uint32_t m_type;
};
//class RockModule : public Module {
//public:
// typedef std::shared_ptr<RockModule> ptr;
// RockModule(const std::string& name
// ,const std::string& version
// ,const std::string& filename);
//
// virtual bool handleRockRequest(sylar::RockRequest::ptr request
// ,sylar::RockResponse::ptr response
// ,sylar::RockStream::ptr stream) = 0;
// virtual bool handleRockNotify(sylar::RockNotify::ptr notify
// ,sylar::RockStream::ptr stream) = 0;
//
// virtual bool handleRequest(sylar::Message::ptr req
// ,sylar::Message::ptr rsp
// ,sylar::Stream::ptr stream);
// virtual bool handleNotify(sylar::Message::ptr notify
// ,sylar::Stream::ptr stream);
//
//};
class ModuleManager
{
public:
typedef RWMutex RWMutexType;
ModuleManager();
void add(Module::ptr m);
void del(const std::string& name);
void delAll();
void init();
Module::ptr get(const std::string& name);
void onConnect(Stream::ptr stream);
void onDisconnect(Stream::ptr stream);
void listAll(std::vector<Module::ptr>& ms);
void listByType(uint32_t type, std::vector<Module::ptr>& ms);
void foreach(uint32_t type, std::function<void(Module::ptr)> cb);
private:
void initModule(const std::string& path);
private:
RWMutexType m_mutex;
std::unordered_map<std::string, Module::ptr> m_modules;
std::unordered_map<uint32_t
, std::unordered_map<std::string, Module::ptr> > m_type2Modules;
};
typedef sylar::Singleton<ModuleManager> ModuleMgr;
}
#endif
// module.cc
#include "module.h"
#include "config.h"
#include "env.h"
#include "library.h"
#include "util.h"
#include "log.h"
#include "application.h"
namespace sylar {
static sylar::ConfigVar<std::string>::ptr g_module_path
= Config::Lookup("module.path", std::string("module"), "module path");
static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
Module::Module(const std::string& name
,const std::string& version
,const std::string& filename
,uint32_t type)
:m_name(name)
,m_version(version)
,m_filename(filename)
,m_id(name + "/" + version)
,m_type(type)
{
}
void Module::onBeforeArgsParse(int argc, char** argv)
{
}
void Module::onAfterArgsParse(int argc, char** argv)
{
}
bool Module::handleRequest(sylar::Message::ptr req
,sylar::Message::ptr rsp
,sylar::Stream::ptr stream)
{
SYLAR_LOG_DEBUG(g_logger) << "handleRequest req=" << req->toString()
<< " rsp=" << rsp->toString() << " stream=" << stream;
return true;
}
bool Module::handleNotify(sylar::Message::ptr notify
,sylar::Stream::ptr stream)
{
SYLAR_LOG_DEBUG(g_logger) << "handleNotify nty=" << notify->toString()
<< " stream=" << stream;
return true;
}
bool Module::onLoad()
{
return true;
}
bool Module::onUnload()
{
return true;
}
bool Module::onConnect(sylar::Stream::ptr stream)
{
return true;
}
bool Module::onDisconnect(sylar::Stream::ptr stream)
{
return true;
}
bool Module::onServerReady()
{
return true;
}
bool Module::onServerUp()
{
return true;
}
//void Module::registerService(const std::string& server_type
// , const std::string& domain
// , const std::string& service)
//{
// auto sd = Application::GetInstance()->getServiceDiscovery();
// if(!sd)
// {
// return;
// }
// std::vector<TcpServer::ptr> svrs;
// if(!Application::GetInstance()->getServer(server_type, svrs))
// {
// return;
// }
// for(auto& i : svrs)
// {
// auto socks = i->getSocks();
// for(auto& s : socks)
// {
// auto addr = std::dynamic_pointer_cast<IPv4Address>(s->getLocalAddress());
// if(!addr)
// {
// continue;
// }
// auto str = addr->toString();
// if(str.find("127.0.0.1") == 0)
// {
// continue;
// }
// std::string ip_and_port;
// if(str.find("0.0.0.0") == 0)
// {
// ip_and_port = sylar::GetIPv4() + ":" + std::to_string(addr->getPort());
// }
// else
// {
// ip_and_port = addr->toString();
// }
// sd->registerServer(domain, service, ip_and_port, server_type);
// }
// }
//}
std::string Module::statusString()
{
std::stringstream ss;
ss << "Module name=" << getName()
<< " version=" << getVersion()
<< " filename=" << getFilename()
<< std::endl;
return ss.str();
}
//RockModule::RockModule(const std::string& name
// ,const std::string& version
// ,const std::string& filename)
// :Module(name, version, filename, ROCK) {
//}
//
//bool RockModule::handleRequest(sylar::Message::ptr req
// ,sylar::Message::ptr rsp
// ,sylar::Stream::ptr stream) {
// auto rock_req = std::dynamic_pointer_cast<sylar::RockRequest>(req);
// auto rock_rsp = std::dynamic_pointer_cast<sylar::RockResponse>(rsp);
// auto rock_stream = std::dynamic_pointer_cast<sylar::RockStream>(stream);
// return handleRockRequest(rock_req, rock_rsp, rock_stream);
//}
//
//bool RockModule::handleNotify(sylar::Message::ptr notify
// ,sylar::Stream::ptr stream) {
// auto rock_nty = std::dynamic_pointer_cast<sylar::RockNotify>(notify);
// auto rock_stream = std::dynamic_pointer_cast<sylar::RockStream>(stream);
// return handleRockNotify(rock_nty, rock_stream);
//}
ModuleManager::ModuleManager()
{
}
Module::ptr ModuleManager::get(const std::string& name)
{
RWMutexType::ReadLock lock(m_mutex);
auto it = m_modules.find(name);
return it == m_modules.end() ? nullptr : it->second;
}
void ModuleManager::add(Module::ptr m)
{
del(m->getId());
RWMutexType::WriteLock lock(m_mutex);
m_modules[m->getId()] = m;
m_type2Modules[m->getType()][m->getId()] = m;
}
void ModuleManager::del(const std::string& name)
{
Module::ptr module;
RWMutexType::WriteLock lock(m_mutex);
auto it = m_modules.find(name);
if(it == m_modules.end())
{
return;
}
module = it->second;
m_modules.erase(it);
m_type2Modules[module->getType()].erase(module->getId());
if(m_type2Modules[module->getType()].empty())
{
m_type2Modules.erase(module->getType());
}
lock.unlock();
module->onUnload();
}
void ModuleManager::delAll()
{
RWMutexType::ReadLock lock(m_mutex);
auto tmp = m_modules;
lock.unlock();
for(auto& i : tmp)
{
del(i.first);
}
}
void ModuleManager::init()
{
auto path = EnvMgr::GetInstance()->getAbsolutePath(g_module_path->getValue());
SYLAR_LOG_DEBUG(g_logger) << "module path:" << path;
std::vector<std::string> files;
sylar::FSUtil::ListAllFile(files, path, ".so");
std::sort(files.begin(), files.end());
for(auto& i : files)
{
initModule(i);
}
}
void ModuleManager::listByType(uint32_t type, std::vector<Module::ptr>& ms)
{
RWMutexType::ReadLock lock(m_mutex);
auto it = m_type2Modules.find(type);
if(it == m_type2Modules.end())
{
return;
}
for(auto& i : it->second)
{
ms.push_back(i.second);
}
}
void ModuleManager::foreach(uint32_t type, std::function<void(Module::ptr)> cb)
{
std::vector<Module::ptr> ms;
listByType(type, ms);
for(auto& i : ms)
{
cb(i);
}
}
void ModuleManager::onConnect(Stream::ptr stream)
{
std::vector<Module::ptr> ms;
listAll(ms);
for(auto& m : ms)
{
m->onConnect(stream);
}
}
void ModuleManager::onDisconnect(Stream::ptr stream)
{
std::vector<Module::ptr> ms;
listAll(ms);
for(auto& m : ms)
{
m->onDisconnect(stream);
}
}
void ModuleManager::listAll(std::vector<Module::ptr>& ms)
{
RWMutexType::ReadLock lock(m_mutex);
for(auto& i : m_modules)
{
ms.push_back(i.second);
}
}
void ModuleManager::initModule(const std::string& path)
{
Module::ptr m = Library::GetModule(path);
if(m)
{
add(m);
}
}
}
//library.h
#ifndef __SYLAR_LIBRARY_H__
#define __SYLAR_LIBRARY_H__
#include <memory>
#include "module.h"
namespace sylar
{
class Library
{
public:
static Module::ptr GetModule(const std::string& path);
};
}
#endif
// library.cc
#include "library.h"
#include <dlfcn.h>
#include "sylar/config.h"
#include "sylar/env.h"
#include "sylar/log.h"
namespace sylar
{
static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
typedef Module* (*create_module)();
typedef void (*destory_module)(Module*);
class ModuleCloser
{
public:
ModuleCloser(void* handle, destory_module d)
: m_handle(handle)
, m_destory(d)
{
}
void operator()(Module* module)
{
std::string name = module->getName();
std::string version = module->getVersion();
std::string path = module->getFilename();
m_destory(module);
int rt = dlclose(m_handle);
if(rt)
{
SYLAR_LOG_ERROR(g_logger) << "dlclose handle fail handle="
<< m_handle << " name=" << name
<< " version=" << version
<< " path=" << path
<< " error=" << dlerror();
}
else
{
SYLAR_LOG_INFO(g_logger) << "destory module=" << name
<< " version=" << version
<< " path=" << path
<< " handle=" << m_handle
<< " success";
}
}
private:
void* m_handle;
destory_module m_destory;
};
Module::ptr Library::GetModule(const std::string& path)
{
void* handle = dlopen(path.c_str(), RTLD_NOW);
if(!handle)
{
SYLAR_LOG_ERROR(g_logger) << "cannot load library path="
<< path << " error=" << dlerror();
return nullptr;
}
create_module create = (create_module)dlsym(handle, "CreateModule");
if(!create)
{
SYLAR_LOG_ERROR(g_logger) << "cannot load symbol CreateModule in "
<< path << " error=" << dlerror();
dlclose(handle);
return nullptr;
}
destory_module destory = (destory_module)dlsym(handle, "DestoryModule");
if(!destory)
{
SYLAR_LOG_ERROR(g_logger) << "cannot load symbol DestoryModule in "
<< path << " error=" << dlerror();
dlclose(handle);
return nullptr;
}
Module::ptr module(create(), ModuleCloser(handle, destory));
module->setFilename(path);
SYLAR_LOG_INFO(g_logger) << "load module name=" << module->getName()
<< " version=" << module->getVersion()
<< " path=" << module->getFilename()
<< " success";
Config::LoadFromConfDir(sylar::EnvMgr::GetInstance()->getConfigPath(), true);
return module;
}
}
Advertising time : be based on sylar The implementation of the framework is small demo( I hope to give star)
边栏推荐
- Explain initialization list
- VAE generation model (with VAE implementation MNIST code)
- Reading of a unified generic framework for aspect based sentimental analysis
- ESP8266 WIFI 模块和手机通信
- Some personal understandings of openpose
- 【实战】使用 Web Animations API 实现一个精确计时的时钟
- Virtual machine class loading mechanism
- 【牛客】求1+2+3+...+n
- CMake使用基础汇总
- 【sylar】框架篇-Chapter12-ByteArray 模块
猜你喜欢

Glusterfs file is not mounted, permission: R-S

10 more advanced open source command line tools

《Intel Arria 10 Avalon-MM DMA Interface for PCI Express Solutions User Guide》文档学习

Reading of papers on "towards generative aspect based sentimental analysis"

【YOLOv5实战5】基于YOLOv5的交通标志识别系统-YOLOv5整合PyQt5

功耗:Leakage Power
![[blood vessel detection] Based on MATLAB mom method, combined with Hessian and curve fitting, blood vessel diameter measurement [including Matlab source code, 1970]](/img/72/10bd8a292c3ee3445907795ebf2ae8.png)
[blood vessel detection] Based on MATLAB mom method, combined with Hessian and curve fitting, blood vessel diameter measurement [including Matlab source code, 1970]
![[practice] use the web animations API to realize a clock with accurate timing](/img/cd/9b9ab27ea6a9909725371eaa809b9f.jpg)
[practice] use the web animations API to realize a clock with accurate timing

高数_第4章__曲线积分_习题解法

2022-7-27 顾宇佳 学习笔记
随机推荐
Cloud native Devops status survey questionnaire solicitation: kodelurover launched jointly with oschina
10 more advanced open source command line tools
Information system project manager (2022) - key content: Project Procurement Management (12)
【sylar】框架篇-Chapter12-ByteArray 模块
Power consumption: leakage power
【sylar】框架篇-Chapter10-Address 模块
Nat fundamentals and private IP
setup和hold timing分析不满足是解决方法
Information system project manager (2022) - key content: Information System Security Management (20)
There are so many ways to view the web source code! Do you know?
Glusterfs file is not mounted, permission: R-S
Pyqt based grouping tool
Null security and exception
20-Openwrt crond crontab
Reading of papers on "towards generative aspect based sentimental analysis"
重要的 SQL Server 函数 - 日期函数
Some personal understandings of openpose
【sylar】框架篇-Chapter8-定时器模块
Phpstorm2022 connect to the database
Harmony's Application on the shelves reported an error. The solution of "please use the API of the released version to develop the application and apply for listing"