muduo网络库学习之muduo_inspect 库涉及到的类
2016-09-12 11:01
375 查看
原文:http://blog.csdn.net/jnu_simba/article/details/15816361
muduo inspect 库通过HTTP方式为服务器提供监控接口, 现在只实现进程相关信息的监控,通过成员ProcessInspector 实现。
ProcessInspector // 通过ProcessInfo返回进程信息
ProcessInfo // 获取进程相关信息
我们可以参照 ProcessInspector 实现一个如TcpStateInspector,作为Inspector的成员,这样就可以实现对Tcp连接状态的监控。比如实现以下功能:
接受了多少个TCP连接
当前有多少个活动连接
一共响应了多少次请求
每次请求的平均响应时间多少毫秒
......
Inspector类:
C++ Code
在Inspector 构造函数中(Inspector对象一般在主线程中构造):
C++ Code
首先注册请求到来时的回调函数,由前面http 库分析可知,需要由Inspector::onRequest() 函数填充httpResponse。接着注册命令的回调函数, 在ProcessInspector::registerCommands()函数中调用了Inspector::add()
函数将命令填充到commands_ 和 helps_ 中, 并且启动Inspector 服务器。
当请求到来,调用Inspector::onRequest() 函数:
C++ Code
如果请求的是根目录,直接返回 /module/command help
如果是其他目录,需要将命令的回调函数执行结果填充到body,
resp->setBody(cb(req.method(), args)); //当前的命令都没有传递参数
测试程序:
Inspector_test.cc:
C++ Code
运行程序,用浏览器访问,输出如下:
服务器端输出如下:
simba@ubuntu:~/Documents/build/debug/bin$ ./inspector_test
20131113 10:50:13.759144Z 4532 TRACE IgnoreSigPipe Ignore SIGPIPE - EventLoop.cc:51
20131113 10:50:13.761764Z 4532 TRACE updateChannel fd = 4 events = 3 - EPollPoller.cc:104
20131113 10:50:13.762399Z 4532 TRACE EventLoop EventLoop created 0xBFE11FD4 in thread 4532 - EventLoop.cc:76
20131113 10:50:13.762869Z 4532 TRACE updateChannel fd = 5 events = 3 - EPollPoller.cc:104
20131113 10:50:13.764532Z 4533 TRACE updateChannel fd = 7 events = 3 - EPollPoller.cc:104
20131113 10:50:13.765484Z 4533 TRACE EventLoop EventLoop created 0xB73D9F44 in thread 4533 - EventLoop.cc:76
20131113 10:50:13.766082Z 4533 TRACE updateChannel fd = 8 events = 3 - EPollPoller.cc:104
20131113 10:50:13.767294Z 4532 TRACE loop EventLoop 0xBFE11FD4 start looping - EventLoop.cc:108
20131113 10:50:13.768760Z 4533 TRACE loop EventLoop 0xB73D9F44 start looping - EventLoop.cc:108
20131113 10:50:13.769373Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:13.770502Z 4533 TRACE printActiveChannels {8: IN } - EventLoop.cc:271
20131113 10:50:13.771500Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:13.772050Z 4533 TRACE printActiveChannels {7: IN} - EventLoop.cc:271
20131113 10:50:13.772521Z 4533 TRACE readTimerfd TimerQueue::handleRead() 1 at 1384339813.772477 - TimerQueue.cc:62
20131113 10:50:13.772950Z 4533 WARN HttpServer[Inspector:test] starts listenning on 0.0.0.0:12345 - HttpServer.cc:155
20131113 10:50:13.772992Z 4533 TRACE updateChannel fd = 9 events = 3 - EPollPoller.cc:104
20131113 10:50:18.749088Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:18.749152Z 4533 TRACE printActiveChannels {9: IN} - EventLoop.cc:271
20131113 10:50:18.749195Z 4533 INFO TcpServer::newConnection [Inspector:test] - new connection [Inspector:test:0.0.0.0:12345#1] from 192.168.56.1:4610 - TcpServer.cc:93
20131113 10:50:18.749425Z 4533 DEBUG TcpConnection TcpConnection::ctor[Inspector:test:0.0.0.0:12345#1] at 0xB6A00748 fd=11 - TcpConnection.cc:65
20131113 10:50:18.749442Z 4533 TRACE newConnection [1] usecount=1 - TcpServer.cc:111
20131113 10:50:18.749455Z 4533 TRACE newConnection [2] usecount=2 - TcpServer.cc:113
20131113 10:50:18.749504Z 4533 TRACE updateChannel fd = 11 events = 3 - EPollPoller.cc:104
20131113 10:50:18.749581Z 4533 TRACE newConnection [5] usecount=2 - TcpServer.cc:123
20131113 10:50:18.760683Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:18.760745Z 4533 TRACE printActiveChannels {11: IN} - EventLoop.cc:271
20131113 10:50:23.778871Z 4532 TRACE poll nothing happended - EPollPoller.cc:74
20131113 10:50:28.772115Z 4533 TRACE poll nothing happended - EPollPoller.cc:74
20131113 10:50:33.602472Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:33.602541Z 4533 TRACE printActiveChannels {11: IN } - EventLoop.cc:271
20131113 10:50:33.806468Z 4532 TRACE poll nothing happended - EPollPoller.cc:74
20131113 10:50:43.613810Z 4533 TRACE poll nothing happended - EPollPoller.cc:74
20131113 10:50:43.816815Z 4532 TRACE poll nothing happended - EPollPoller.cc:74
第一次访问的是根目录,给出的是可用的命令提示,如第一行
即/module/command help
可用的四个命令的module都是proc(ProcessInspector),如前所述,如果我们再实现一个TcpStateInspector作为Inspector的成员,可以做成模块/tcpstate.
help 只是对命名功能的描述。
接着根据提示进入某个目录如/proc/status,就会给出当前服务器进程的一些状态信息。
程序运行的时候有两个线程,两个loop,主线程的loop 占据3,4,5 (epollfd, timerfd, eventfd)文件描述符但什么都不做(在实际工作中可以作为正常的服务线程);而监控线程占据6,7,8 (epollfd, timerfd, eventfd)文件描述符而且监听9 描述符。fd=10是idlefd_。fd =8 发生可读事件是因为在主线程中(不在loop所在,inspector服务所在线程)调用loop->runAfter(),故需要唤醒一下inspector线程,其实只是add一个定时器。fd=7发生可读事件是因为定时器超时,处理过程中会回调Inspector::start(),也就是开始启动TcpServer监听。
浏览器访问,建立连接,fd=11,前后访问两个目录,发生两次可读事件。
参考:
《UNP》
muduo manual.pdf
《linux 多线程服务器编程:使用muduo c++网络库》
muduo inspect 库通过HTTP方式为服务器提供监控接口, 现在只实现进程相关信息的监控,通过成员ProcessInspector 实现。
ProcessInspector // 通过ProcessInfo返回进程信息
ProcessInfo // 获取进程相关信息
我们可以参照 ProcessInspector 实现一个如TcpStateInspector,作为Inspector的成员,这样就可以实现对Tcp连接状态的监控。比如实现以下功能:
接受了多少个TCP连接
当前有多少个活动连接
一共响应了多少次请求
每次请求的平均响应时间多少毫秒
......
Inspector类:
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // 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; // 如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() { server_.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_; }; |
C++ Code
1 2 3 4 5 6 7 | server_.setHttpCallback(boost::bind(&Inspector::onRequest, this, _1, _2)); processInspector_->registerCommands(this); // 这样子做法是为了防止竞态问题 // 如果直接调用start,(当前线程不是loop所属的IO线程,是主线程)那么有可能,当前构造函数还没返回, // HttpServer所在的IO线程可能已经收到了http客户端的请求了(因为这时候HttpServer已启动),那么就会回调 // Inspector::onRequest,而这时候构造函数还没返回,也就是说对象还没完全构造好 loop->runAfter(0.1, boost::bind(&Inspector::start, this)); // little race condition |
函数将命令填充到commands_ 和 helps_ 中, 并且启动Inspector 服务器。
当请求到来,调用Inspector::onRequest() 函数:
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | void Inspector::onRequest(const HttpRequest &req, HttpResponse *resp) { if (req.path() == "/") { string result; .... resp->setStatusCode(HttpResponse::k200Ok); resp->setStatusMessage("OK"); resp->setContentType("text/plain"); resp->setBody(result); } else { // 以"/"进行分割,将得到的字符串保存在result中 std::vector<string> result = split(req.path()); 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; } } } |
如果是其他目录,需要将命令的回调函数执行结果填充到body,
resp->setBody(cb(req.method(), args)); //当前的命令都没有传递参数
测试程序:
Inspector_test.cc:
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #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; // 监控线程 Inspector ins(t.startLoop(), InetAddress(12345), "test"); loop.loop(); } |
服务器端输出如下:
simba@ubuntu:~/Documents/build/debug/bin$ ./inspector_test
20131113 10:50:13.759144Z 4532 TRACE IgnoreSigPipe Ignore SIGPIPE - EventLoop.cc:51
20131113 10:50:13.761764Z 4532 TRACE updateChannel fd = 4 events = 3 - EPollPoller.cc:104
20131113 10:50:13.762399Z 4532 TRACE EventLoop EventLoop created 0xBFE11FD4 in thread 4532 - EventLoop.cc:76
20131113 10:50:13.762869Z 4532 TRACE updateChannel fd = 5 events = 3 - EPollPoller.cc:104
20131113 10:50:13.764532Z 4533 TRACE updateChannel fd = 7 events = 3 - EPollPoller.cc:104
20131113 10:50:13.765484Z 4533 TRACE EventLoop EventLoop created 0xB73D9F44 in thread 4533 - EventLoop.cc:76
20131113 10:50:13.766082Z 4533 TRACE updateChannel fd = 8 events = 3 - EPollPoller.cc:104
20131113 10:50:13.767294Z 4532 TRACE loop EventLoop 0xBFE11FD4 start looping - EventLoop.cc:108
20131113 10:50:13.768760Z 4533 TRACE loop EventLoop 0xB73D9F44 start looping - EventLoop.cc:108
20131113 10:50:13.769373Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:13.770502Z 4533 TRACE printActiveChannels {8: IN } - EventLoop.cc:271
20131113 10:50:13.771500Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:13.772050Z 4533 TRACE printActiveChannels {7: IN} - EventLoop.cc:271
20131113 10:50:13.772521Z 4533 TRACE readTimerfd TimerQueue::handleRead() 1 at 1384339813.772477 - TimerQueue.cc:62
20131113 10:50:13.772950Z 4533 WARN HttpServer[Inspector:test] starts listenning on 0.0.0.0:12345 - HttpServer.cc:155
20131113 10:50:13.772992Z 4533 TRACE updateChannel fd = 9 events = 3 - EPollPoller.cc:104
20131113 10:50:18.749088Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:18.749152Z 4533 TRACE printActiveChannels {9: IN} - EventLoop.cc:271
20131113 10:50:18.749195Z 4533 INFO TcpServer::newConnection [Inspector:test] - new connection [Inspector:test:0.0.0.0:12345#1] from 192.168.56.1:4610 - TcpServer.cc:93
20131113 10:50:18.749425Z 4533 DEBUG TcpConnection TcpConnection::ctor[Inspector:test:0.0.0.0:12345#1] at 0xB6A00748 fd=11 - TcpConnection.cc:65
20131113 10:50:18.749442Z 4533 TRACE newConnection [1] usecount=1 - TcpServer.cc:111
20131113 10:50:18.749455Z 4533 TRACE newConnection [2] usecount=2 - TcpServer.cc:113
20131113 10:50:18.749504Z 4533 TRACE updateChannel fd = 11 events = 3 - EPollPoller.cc:104
20131113 10:50:18.749581Z 4533 TRACE newConnection [5] usecount=2 - TcpServer.cc:123
20131113 10:50:18.760683Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:18.760745Z 4533 TRACE printActiveChannels {11: IN} - EventLoop.cc:271
20131113 10:50:23.778871Z 4532 TRACE poll nothing happended - EPollPoller.cc:74
20131113 10:50:28.772115Z 4533 TRACE poll nothing happended - EPollPoller.cc:74
20131113 10:50:33.602472Z 4533 TRACE poll 1 events happended - EPollPoller.cc:65
20131113 10:50:33.602541Z 4533 TRACE printActiveChannels {11: IN } - EventLoop.cc:271
20131113 10:50:33.806468Z 4532 TRACE poll nothing happended - EPollPoller.cc:74
20131113 10:50:43.613810Z 4533 TRACE poll nothing happended - EPollPoller.cc:74
20131113 10:50:43.816815Z 4532 TRACE poll nothing happended - EPollPoller.cc:74
第一次访问的是根目录,给出的是可用的命令提示,如第一行
/proc/opened_files count /proc/self/fd
即/module/command help
可用的四个命令的module都是proc(ProcessInspector),如前所述,如果我们再实现一个TcpStateInspector作为Inspector的成员,可以做成模块/tcpstate.
help 只是对命名功能的描述。
接着根据提示进入某个目录如/proc/status,就会给出当前服务器进程的一些状态信息。
程序运行的时候有两个线程,两个loop,主线程的loop 占据3,4,5 (epollfd, timerfd, eventfd)文件描述符但什么都不做(在实际工作中可以作为正常的服务线程);而监控线程占据6,7,8 (epollfd, timerfd, eventfd)文件描述符而且监听9 描述符。fd=10是idlefd_。fd =8 发生可读事件是因为在主线程中(不在loop所在,inspector服务所在线程)调用loop->runAfter(),故需要唤醒一下inspector线程,其实只是add一个定时器。fd=7发生可读事件是因为定时器超时,处理过程中会回调Inspector::start(),也就是开始启动TcpServer监听。
浏览器访问,建立连接,fd=11,前后访问两个目录,发生两次可读事件。
参考:
《UNP》
muduo manual.pdf
《linux 多线程服务器编程:使用muduo c++网络库》
相关文章推荐
- muduo网络库学习之muduo_inspect 库涉及到的类
- muduo网络库学习之muduo_http 库涉及到的类
- muduo网络库学习之EventLoop(一):事件循环类图简介和muduo 定时器TimeQueue
- 找了份工作, 会涉及到STM32芯片. 把最近学习的东西跟大家分享一下.
- 硬件学习应涉及到的几个方面?
- muduo网络库学习之Timestamp类、AtomicIntegerT 类封装中的知识点
- muduo网络库学习之EventLoop(四):EventLoopThread 类、EventLoopThreadPool 类
- 无监督特征学习涉及的基本概念
- muduo网络库学习之EventLoop(五):TcpConnection生存期管理(连接关闭)
- muduo网络库学习之Exception类、Thread 类封装中的知识点(重点讲pthread_atfork())
- muduo网络库学习之EventLoop(三):Socket、Acceptor、TcpServer、TcpConnection(连接建立,接收消息)
- 一个非常非常非常基础的程序,写的不好,但是一般的文件读写操作及字符处理函数都涉及到了..新手学习用的
- winCE嵌入式开发学习(二)续--wince体系结构涉及操作系统部分
- 关于LSA的相关学习---短文本聚类涉及到的知识,一种主题模型(原载于我的百度空间)
- 【Rails学习笔记】更新、显示和删除用户(涉及分页)(下)
- 记录《自己动手写网络爬虫 》书中涉及的内容学习一些算法
- WebGIS : 学习mapbar,51ditu,google maps的制作原理和涉及到的技术
- 学习数组类时,碰到typeof(),对其实验引起的一连串知识点、学习小结和思考练习(涉及成员对象变量、成员常量、抽象类Type等知识)
- [sql server] 问题总结17---一个项目涉及到的50个Sql语句(爱新觉罗.毓华整理版)(很值得学习)
- muduo网络库学习之BlockinngQueue<T>类、ThreadPool 类、Singleton类封装中的知识点