muduo網路庫學習之muduo_inspect 庫涉及到的類
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_; }; |
在Inspector 建構函式中(Inspector物件一般在主執行緒中構造):
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 |
首先註冊請求到來時的回撥函式,由前面http 庫分析可知,需要由Inspector::onRequest() 函式填充httpResponse。接著註冊命令的回撥函式, 在ProcessInspector::registerCommands()函式中呼叫了Inspector::add()
函式將命令填充到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; } } } |
如果請求的是根目錄,直接返回 /module/command help
如果是其他目錄,需要將命令的回撥函式執行結果填充到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
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_http 庫涉及到的類HTTP
- muduo網路庫學習之EventLoop(四):EventLoopThread 類、EventLoopThreadPool 類OOPthread
- muduo網路庫學習筆記(1):Timestamp類筆記
- muduo網路庫學習筆記(3):Thread類筆記thread
- muduo網路庫學習之EventLoop(七):TcpClient、ConnectorOOPTCPclient
- muduo網路庫Timestamp類
- muduo網路庫學習之Timestamp類、AtomicIntegerT 類封裝中的知識點封裝
- muduo網路庫學習之ThreadLocal 類、ThreadLocalSingleton類封裝知識點thread封裝
- muduo網路庫學習之BlockinngQueue類、ThreadPool 類、Singleton類封裝中的知識點BloCthread封裝
- muduo網路庫Exception異常類Exception
- muduo網路庫學習之MutexLock類、MutexLockGuard類、Condition類、CountDownLatch類封裝中的知識點MutexCountDownLatch封裝
- muduo網路庫學習筆記(8):高效日誌類的封裝筆記封裝
- muduo網路庫學習之EventLoop(一):事件迴圈類圖簡介和muduo 定時器TimeQueueOOP事件定時器
- muduo網路庫學習筆記(12):TcpServer和TcpConnection類筆記TCPServer
- muduo網路庫學習筆記(6):單例類(執行緒安全的)筆記單例執行緒
- muduo網路庫學習之Logger類、LogStream類、LogFile類封裝中的知識點封裝
- muduo網路庫學習筆記(2):原子性操作筆記
- muduo網路庫AtomicIntegerT原子整數類
- muduo網路庫學習之EventLoop(六):TcpConnection::send()、shutdown()、handleRead()、handleWrite()OOPTCP
- muduo網路庫學習筆記(11):有用的runInLoop()函式筆記OOP函式
- muduo網路庫學習筆記(14):chargen服務示例筆記
- muduo網路庫學習筆記(13):TcpConnection生命期的管理筆記TCP
- muduo網路庫學習筆記(10):定時器的實現筆記定時器
- muduo網路庫學習之Exception類、Thread 類封裝中的知識點(重點講pthread_atfork())Exceptionthread封裝
- muduo網路庫使用心得
- muduo網路庫學習筆記(9):Reactor模式的關鍵結構筆記React模式
- muduo網路庫學習筆記(5):執行緒池的實現筆記執行緒
- muduo網路庫學習筆記(7):執行緒特定資料筆記執行緒
- muduo網路庫學習之EventLoop(二):程式(執行緒)wait/notify 和 EventLoop::runInLoopOOP執行緒AI
- muduo網路庫學習之EventLoop(五):TcpConnection生存期管理(連線關閉)OOPTCP
- muduo網路庫編譯安裝編譯
- muduo網路庫學習筆記(4):互斥量和條件變數筆記變數
- muduo網路庫學習之EventLoop(三):Socket、Acceptor、TcpServer、TcpConnection(連線建立,接收訊息)OOPTCPServer
- muduo網路庫學習筆記(15):關於使用stdio和iostream的討論筆記iOS
- muduo網路庫學習筆記(0):物件導向程式設計風格和基於物件程式設計風格的比較筆記物件程式設計
- 13封裝網路請求類庫封裝
- 資料庫學習線路圖資料庫
- 網路資料庫練習題資料庫