一:源码分析
今天剖析muduo inspect库。muduo_inspect库通过HTTP的方式为服务器提供监控接口。比如提供以下功能:
- 接收了多少个TCP连接
- 当前有多少个活动连接
- 一共响应了多少次请求
- 每次请求的平均响应时间为多少ms
- ...
inspect库主要有Inspector类组成,它包含了一个HttpServer对象,并同过ProcessInspector类返回进程信息,ProcessInfo类获取进程相关信息。
以查看进程id为例,用法如下:
浏览器输入ip,端口,"proc"是进程模块,“pid”是命令,获取进程pid。当然也可以获取其他资源。
首先我们来看它的类:
class Inspector : boost::noncopyable
{
public:
typedef std::vector<string> ArgList;
typedef boost::function<string (HttpRequest::Method, const ArgList& args)> Callback;
Inspector(EventLoop* loop,
const InetAddress& httpAddr,
const string& name);
~Inspector();
/// Add a Callback for handling the special uri : /mudule/command
//添加监控器对应的回调函数
//如 add("proc", "pid", ProcessInspector::pid, "print pid")
//http:/192.168.33.147:12345/proc/pid这个http请求就会相应调用ProcessInspector::pid来处理
void add(const string& module, //模块
const string& command, //命令
const Callback& cb, //回调执行方法
const string& help); //帮助信息
void remove(const string& module, const string& command);
private:
typedef std::map<string, Callback> CommandList; //命令列表,对于客端发起的每个命令,有一个回调函数处理
typedef std::map<string, string> HelpList; //针对客端命令的帮助信息列表
void start();
void onRequest(const HttpRequest& req, HttpResponse* resp);
HttpServer server_;
boost::scoped_ptr<ProcessInspector> processInspector_; //暴露的接口,进程磨成
boost::scoped_ptr<PerformanceInspector> performanceInspector_; //性能模块
boost::scoped_ptr<SystemInspector> systemInspector_; //系统模块
MutexLock mutex_;
std::map<string, CommandList> modules_; //模块,对应佑趍odule -- command -- callback
std::map<string, HelpList> helps_; //帮助,对应于module -- command -- help
};
然后是构造函数:
Inspector::Inspector(EventLoop* loop,
const InetAddress& httpAddr,
const string& name)
: server_(loop, httpAddr, "Inspector:"+name), //初始化http服务器
processInspector_(new ProcessInspector), //进程检查器
systemInspector_(new SystemInspector) //系统检查器
{
assert(CurrentThread::isMainThread()); //只能在主线程构造
assert(g_globalInspector == 0);
g_globalInspector = this; //注册全局观察器
server_.setHttpCallback(boost::bind(&Inspector::onRequest, this, _1, _2)); //注册http服务器的回调函数
processInspector_->registerCommands(this); //注册命令,实际上就是填充两个map对应的命令,回调函数,help信息
systemInspector_->registerCommands(this);
//这样子做法是为了防止竞态问题
//如果直接调用start,(当前线程不是loop所在的I/O线程,是主线程),那么有可能,当前构造函数还没返回,