muduo_inspect库源码分析(41)
来源:互联网 发布:设计院改制 知乎 编辑:程序博客网 时间:2024/04/28 00:00
muduo_inspect库通过HTTP方式为服务器提供监控接口
接受了多少个TCP连接
当前有多少个活动连接
一共响应了多少次请求
每次请求的平均响应时间多少毫秒
。。。
Inspector // 包含了一个HttpServer对象
ProcessInspector // 通过ProcessInfo返回进程信息
ProcessInfo // 获取进程相关信息
ProcessInspectort头文件
ProcessInspector.h
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//// This is an internal header file, you should not include this.#ifndef MUDUO_NET_INSPECT_PROCESSINSPECTOR_H#define MUDUO_NET_INSPECT_PROCESSINSPECTOR_H#include <muduo/net/inspect/Inspector.h>#include <boost/noncopyable.hpp>namespace muduo{namespace net{class ProcessInspector : boost::noncopyable{ public: void registerCommands(Inspector* ins); // 注册命令接口 private: static string pid(HttpRequest::Method, const Inspector::ArgList&); static string procStatus(HttpRequest::Method, const Inspector::ArgList&); static string openedFiles(HttpRequest::Method, const Inspector::ArgList&); static string threads(HttpRequest::Method, const Inspector::ArgList&);};}}#endif // MUDUO_NET_INSPECT_PROCESSINSPECTOR_H
ProcessInspectort源文件
ProcessInspector.cc
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//#include <muduo/net/inspect/ProcessInspector.h>#include <muduo/base/ProcessInfo.h>#include <stdio.h>using namespace muduo;using namespace muduo::net;/*命令注册*/void ProcessInspector::registerCommands(Inspector* ins){ /*muduo : proc command : pid commandCallback : pid commnadHelp : print id */ ins->add("proc", "pid", ProcessInspector::pid, "print pid"); ins->add("proc", "status", ProcessInspector::procStatus, "print /proc/self/status"); ins->add("proc", "opened_files", ProcessInspector::openedFiles, "count /proc/self/fd"); ins->add("proc", "threads", ProcessInspector::threads, "list /proc/self/task");}string ProcessInspector::pid(HttpRequest::Method, const Inspector::ArgList&){ char buf[32]; snprintf(buf, sizeof buf, "%d", ProcessInfo::pid()); return buf;}string ProcessInspector::procStatus(HttpRequest::Method, const Inspector::ArgList&){ return ProcessInfo::procStatus();}string ProcessInspector::openedFiles(HttpRequest::Method, const Inspector::ArgList&){ char buf[32]; snprintf(buf, sizeof buf, "%d", ProcessInfo::openedFiles()); return buf;}string ProcessInspector::threads(HttpRequest::Method, const Inspector::ArgList&){ std::vector<pid_t> threads = ProcessInfo::threads(); string result; for (size_t i = 0; i < threads.size(); ++i) { char buf[32]; snprintf(buf, sizeof buf, "%d\n", threads[i]); result += buf; } return result;}
Inspector头文件
Inspector.h
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//// This is a public header file, it must only include public header files.#ifndef MUDUO_NET_INSPECT_INSPECTOR_H#define MUDUO_NET_INSPECT_INSPECTOR_H#include <muduo/base/Mutex.h>#include <muduo/net/http/HttpRequest.h>#include <muduo/net/http/HttpServer.h>#include <map>#include <boost/function.hpp>#include <boost/noncopyable.hpp>#include <boost/scoped_ptr.hpp>namespace muduo{namespace net{class ProcessInspector;// A internal inspector of the running process, usually a singleton.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("proc", "pid", ProcessInspector::pid, "print pid"); // http://192.168.159.188:12345/proc/pid这个http请求就会相应的调用ProcessInspector::pid来处理 void add(const string& module, const string& command, const Callback& cb, const string& help); 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_; MutexLock mutex_; std::map<string, CommandList> commands_; std::map<string, HelpList> helps_; /*commands_ --- > <muduo commandlist>helps_ ----> <muduo helplist>commandlist---> <command callback>HelpList ----> <command helplist>commands_[][]=xxhelps_[][]=xxx */};}}#endif // MUDUO_NET_INSPECT_INSPECTOR_H
Inspector源文件
Inspector.cc
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//#include <muduo/net/inspect/Inspector.h>#include <muduo/base/Thread.h>#include <muduo/net/EventLoop.h>#include <muduo/net/http/HttpRequest.h>#include <muduo/net/http/HttpResponse.h>#include <muduo/net/inspect/ProcessInspector.h>//#include <iostream>//#include <iterator>//#include <sstream>#include <boost/bind.hpp>#include <boost/algorithm/string/classification.hpp>#include <boost/algorithm/string/split.hpp>using namespace muduo;using namespace muduo::net;namespace{Inspector* g_globalInspector = 0;// Looks buggystd::vector<string> split(const string& str){ std::vector<string> result; size_t start = 0; size_t pos = str.find('/'); while (pos != string::npos) { if (pos > start) { result.push_back(str.substr(start, pos-start)); } start = pos+1; pos = str.find('/', start); } if (start < str.length()) // 说明最后一个字符不是'/' { result.push_back(str.substr(start)); } return result;}}Inspector::Inspector(EventLoop* loop, const InetAddress& httpAddr, const string& name) : server_(loop, httpAddr, "Inspector:"+name), processInspector_(new ProcessInspector){ //断言在主线程当中 assert(CurrentThread::isMainThread()); assert(g_globalInspector == 0); g_globalInspector = this; /*设置请求的回调函数,这里的请求是完成了协议的解析之后*/ server_.setHttpCallback(boost::bind(&Inspector::onRequest, this, _1, _2)); /*注册命令*/ processInspector_->registerCommands(this); // 这样子做法是为了防止竞态问题 // 如果直接调用start,(当前线程不是loop所属的IO线程,是主线程)那么有可能,当前构造函数还没返回, // HttpServer所在的IO线程可能已经收到了http客户端的请求了(因为这时候HttpServer已启动),那么就会回调 // Inspector::onRequest,而这时候构造函数还没返回,也就是说对象还没完全构造好。那么就会出现问题了 loop->runAfter(0, boost::bind(&Inspector::start, this)); // little race condition}Inspector::~Inspector(){ assert(CurrentThread::isMainThread()); g_globalInspector = NULL;}void Inspector::add(const string& module, const string& command, const Callback& cb, const string& help){ /*这里要不要加锁??因为在构造函数时 程序是注册完 processInspector_->registerCommands(this); 才执行loop->runAfter(0, boost::bind(&Inspector::start, this)); // little race condition。如果程序进行扩充时,就要了。class TcpInspector : boost::noncopyable{ public: void registerCommands(Inspector* ins); // 注册命令接口 private: static string pid(HttpRequest::Method, const Inspector::ArgList&); static string procStatus(HttpRequest::Method, const Inspector::ArgList&); static string openedFiles(HttpRequest::Method, const Inspector::ArgList&); static string threads(HttpRequest::Method, const Inspector::ArgList&);};MyInspector :public ProcessInspector{ TcpInspector} ;那么MyInspector{ HttpServer server_; boost::scoped_ptr<ProcessInspector> processInspector; boost::scoped_ptr<ProcessInspector> TcpInspector; MutexLock mutex_; std::map<string, CommandList> commands_; std::map<string, HelpList> helps_;}那么MyInspector 在初始化时,会初始化ProcessInspector 和TcpInspector,如果ProcessInspector初始化完毕后,启动了OnreRequest(),而TcpInspector还没注册完,也就是说TcpInspector还在add()函数中,那么不加锁的话,就会出现问题了。 */ MutexLockGuard lock(mutex_); commands_[module][command] = cb; helps_[module][command] = help;}void Inspector::start(){ server_.start();}void Inspector::onRequest(const HttpRequest& req, HttpResponse* resp){ if (req.path() == "/") { string result; MutexLockGuard lock(mutex_); // 遍历helps for (std::map<string, HelpList>::const_iterator helpListI = helps_.begin(); helpListI != helps_.end(); ++helpListI) { const HelpList& list = helpListI->second; for (HelpList::const_iterator it = list.begin(); it != list.end(); ++it) { result += "/"; result += helpListI->first; // module result += "/"; result += it->first; // command result += "\t"; result += it->second; // help result += "\n"; } } resp->setStatusCode(HttpResponse::k200Ok); resp->setStatusMessage("OK"); resp->setContentType("text/plain"); resp->setBody(result); } else { // 以"/"进行分割,将得到的字符串保存在result中 std::vector<string> result = split(req.path()); // boost::split(result, req.path(), boost::is_any_of("/")); //std::copy(result.begin(), result.end(), std::ostream_iterator<string>(std::cout, ", ")); //std::cout << "\n"; bool ok = false; if (result.size() == 0) { // 这种情况是错误的,因此ok仍为false } else if (result.size() == 1) { // 只有module,没有command也是错的,因此ok仍为false string module = result[0]; } else { string module = result[0]; // 查找module所对应的命令列表 std::map<string, CommandList>::const_iterator commListI = commands_.find(module); if (commListI != commands_.end()) { string command = result[1]; const CommandList& commList = commListI->second; // 查找command对应的命令 CommandList::const_iterator it = commList.find(command); if (it != commList.end()) { ArgList args(result.begin()+2, result.end()); // 传递给回调函数的参数表 if (it->second) { resp->setStatusCode(HttpResponse::k200Ok); resp->setStatusMessage("OK"); resp->setContentType("text/plain"); const Callback& cb = it->second; resp->setBody(cb(req.method(), args)); // 调用cb将返回的字符串传给setBody ok = true; } } } } if (!ok) { resp->setStatusCode(HttpResponse::k404NotFound); resp->setStatusMessage("Not Found"); } //resp->setCloseConnection(true); }}
测试程序
#include <muduo/net/inspect/Inspector.h>#include <muduo/net/EventLoop.h>#include <muduo/net/EventLoopThread.h>using namespace muduo;using namespace muduo::net;int main(){ EventLoop loop; EventLoopThread t; // 监控线程 ,这里“线程该没有真正创建,t.startLoop()函数才是真正创建” /*Inspector 的loop 和main thread 的loop是不一样的,也就是说,现在已经有两个loop了*/ Inspector ins(t.startLoop(), InetAddress(12345), "test"); loop.loop();}
在浏览器中输入127.0.0.1:12345/proc/status
Name: inspector_testState: S (sleeping)Tgid: 2030Pid: 2030PPid: 1907TracerPid: 0Uid: 1000 1000 1000 1000Gid: 1000 1000 1000 1000FDSize: 256Groups: 4 20 24 46 116 118 124 1000 VmPeak: 12348 kBVmSize: 12348 kBVmLck: 0 kBVmHWM: 1580 kBVmRSS: 1580 kBVmData: 8408 kBVmStk: 136 kBVmExe: 860 kBVmLib: 2868 kBVmPTE: 32 kBVmSwap: 0 kBThreads: 2SigQ: 0/9772SigPnd: 0000000000000000ShdPnd: 0000000000000000SigBlk: 0000000000000000SigIgn: 0000000000001000SigCgt: 0000000180000000CapInh: 0000000000000000CapPrm: 0000000000000000CapEff: 0000000000000000CapBnd: ffffffffffffffffCpus_allowed: 3Cpus_allowed_list: 0-1Mems_allowed: 1Mems_allowed_list: 0voluntary_ctxt_switches: 22nonvoluntary_ctxt_switches: 14
- muduo_inspect库源码分析(41)
- muduo网络库学习之muduo_inspect 库涉及到的类
- muduo网络库学习之muduo_inspect 库涉及到的类
- muduo_net库源码分析
- cJSON库源码分析
- ASIO库源码分析
- cJSON库源码分析
- muduo库源码分析
- sigslot库源码分析
- sigslot库源码分析
- sigslot库源码分析
- 数值分析源码和库
- muduo_net库源码分析(25)
- boost 源码 ref 库分析
- NineoldAndroids动画库源码分析
- NineoldAndroids动画库源码分析 .
- NineoldAndroids动画库源码分析
- libev事件库源码分析
- 开发者所需要知道的iOS7 SDK新特性
- http实现源码(40-1)
- TCMalloc源码阅读(一)
- NYOJ-6-喷水装置(一)-2013年08月15日00:48:41
- 寻找序列的插入位置 Search Insert Position
- muduo_inspect库源码分析(41)
- AI:从游戏引擎--到AI
- oracle-dblink使用
- (3)打印1到最大的n位数
- 串口回调函数
- 判断是不是回文
- url 传递参数(特殊字符)解决方法
- hdoj水题-1200
- SecureCRT多会话标签实现