基於線程池、消息隊列和epoll模型實現併發服務器架構

引言

併發是什麼?企業在進行產品開發過程當中爲何須要考慮這個問題?想象一下天貓的雙11和京東的618活動,一秒的點擊量就有幾十萬甚至上百萬,這麼多請求一會兒涌入到服務器,服務器須要對這麼多的請求逐個進行消化掉,假如服務器一秒的處理能力就幾萬,那麼剩下的不能及時獲得處理的這些請求做何處理?總不能讓用戶界面一直等着,所以消息隊列應運而生,全部的請求都統一放入消息隊列,工做線程從消息隊列不斷的消費,消息隊列至關於一個緩衝區,可達到解藕、異步和削峯的目的。html

Kafka、ActiveMQ、RabbitMQ和RockerMQ都是消息隊列的典型,每一種都有其自身的優點和劣勢。本文我用本身編寫的Buffer類模擬消息隊列,若是是企業級須要上線的應用,通常都是基於業界已有的MQ框架上開發。git

需求原型

  1. N個Client從標準輸入接收數據,而後接二連三的發送到Server端;
  2. Server端接收來自每一個Client的數據,將數據中的小寫字母所有轉換成大寫字母,其餘字符保持不變,最後把轉換結果發送給對應的Client。

需求分解

  1. 拿到需求,第一步要作的就是分析需求並選擇合適的設計架構,考慮到Server須要和Client進行通訊,Client來自四面八方,端對端通訊天然選擇TCP,所以Server端須要可以監聽新的鏈接請求和已有鏈接的業務請求;
  2. 又因爲Server須要響應多個Client的業務請求,咱們但願把業務處理交給Server端的工做線程(消費者)來作;
  3. 同時還須要一個IO線程負責監聽Socket描述符,當IO線程監聽到已有鏈接的業務請求時,當即把請求內容封裝成一個任務推入消息隊列尾;
  4. IO線程與工做線程互斥訪問消息隊列,固然工做線程消費一個任務或者IO線程添加一個任務都須要通知對方,也就是同步;
  5. 工做線程處理完畢後,把處理結果交給IO線程,由IO線程負責把結果發送給對應的Client,也就是IO線程與工做線程的分離,這裏工做線程通知IO線程的方式我用eventfd來實現;
  6. 咱們但願引入Log4cpp記錄服務端的日誌,並可以保存到文件中;
  7. 分析完這些,一個總體架構和大致的樣子在腦海中就已經造成了,接着就須要編寫設計文檔和畫流程圖、類圖和時序圖了。

詳細設計文檔

1.UML靜態類圖:github

2.UML動態時序圖:編程

效果

1.如圖,開了三個Client,運行結果正確:bash

2.Server端經過Log4cpp把日誌寫到文件中:服務器

源碼獲取

https://github.com/icoty/cs_threadpool_epoll_mq網絡

目錄結構

.
├── client                   // 客戶端Demo
│   ├── Client.cc
│   ├── Client.exe
│   ├── client.sh    // 進入該目錄下啓動Client Demo: sh client.sh
│   ├── Log4func.cc // 引入日誌模塊從新瘋轉
│   ├── Log4func.h
│   └── Makefile     // 編譯方式:make
├── conf
│   └── my.conf // IP,Port配置文件, 從這裏進行修改
├── include // 頭文件
│   ├── Configuration.hpp // 配置文件,單例類,my.conf的內存化
│   ├── FileName.hpp // 全局定義,Configuration會用到
│   ├── log // 日誌模塊頭文件
│   │   └── Log4func.hpp
│   ├── net // 網絡框架模塊頭文件
│   │   ├── EpollPoller.hpp
│   │   ├── InetAddress.hpp
│   │   ├── Socket.hpp
│   │   ├── SockIO.hpp
│   │   ├── TcpConnection.hpp
│   │   └── TcpServer.hpp
│   ├── String2Upper.hpp // 工做線程轉換成大寫實際走的這裏面的接口
│   ├── String2UpperServer.hpp // Server端的整個工廠
│   └── threadpool // 線程池、鎖、條件變量和消息隊列的封裝
│       ├── Buffer.hpp
│       ├── Condition.hpp
│       ├── MutexLock.hpp
│       ├── Noncopyable.hpp
│       ├── Pthread.hpp
│       ├── Task.hpp
│       └── Threadpool.hpp
├── log // Server端的日誌經過Log4cpp記錄到這個文件中
│   └── log4test.log
├── Makefile // 編譯方式:make
├── README.md 
├── server // server端Demo
│   ├── server.exe
│   └── server.sh // 進入該目錄下啓動Server Demo:sh server.sh
└── src // 源文件
    ├── Configuration.cpp
    ├── log
    │   └── Log4func.cpp
    ├── main.cpp
    ├── net
    │   ├── EpollPoller.cpp
    │   ├── InetAddress.cpp
    │   ├── Socket.cpp
    │   ├── SockIO.cpp
    │   ├── TcpConnection.cpp
    │   └── TcpServer.cpp
    ├── String2Upper.cpp
    ├── String2UpperServer.cpp
    └── threadpool
    ├── Buffer.cpp
    ├── Condition.cpp
    ├── MutexLock.cpp // MutexLockGuard封裝
    ├── Pthread.cpp
    └── Threadpool.cpp

參考文獻

[1] UNIX環境高級編程第3版
[2] cpp reference
[3] UML時序圖
[4] Log4cpp官網下載
[5] Log4cpp安裝架構

相關文章
相關標籤/搜索