【項目日記】高并發服務器項目總結

在這里插入圖片描述

生活總是讓我們遍體鱗傷,
但到后來,
那些受傷的地方一定會變成我們最強壯的地方。
-- 《老人與海》--

高并發服務器項目總結

  • 模塊關系圖
  • 項目工具模塊
    • 緩沖區模塊
    • 通用類型模塊
    • 套接字socket模塊
    • 信道Channel模塊
    • 多路轉接Poller模塊
  • Reactor模塊
    • 時間輪TimeWheel模塊
  • 連接Connection模塊
  • Accepter模塊
  • TcpServer模塊

模塊關系圖

在這里插入圖片描述

項目工具模塊

緩沖區模塊

底層使用字符容器儲存數據,通過兩個指針:讀偏移和寫偏移管理空間:

  • 對于寫入:確保空間足夠,在寫偏移后拷貝數據,寫偏移向后移動
  • 對于讀取:確保可讀數據足夠,在讀偏移后讀取數據,讀偏移向后移動
  • 空間不足時及時擴容

通用類型模塊

想要實現的效果:

Any a;
a = 123;
a = "123"
a = vector<int>(n , 0);

為了實現這種效果,首先Any類肯定不能帶有模版參數,不然就不能自由轉換了!

  • 可以在內部設計一個內部類placeholder(繼承holder父類),它是一個模板類,是實際儲存數據的對象;
  • 當我們創建了一個Any對象時,會創建一個父類指針,管理placeholder對象
  • 通過模版函數,我們可以實現對placeholder對象賦值。
  • 可以通過交換placeholder對象管理的資源實現自由賦值。

套接字socket模塊

這個模塊對外提供一鍵創建服務端套接字和客戶端套接字的方法(是對內部接口的一個封裝):

  • 創建套接字接口:以數據流的方式創建一個套接字文件
  • 綁定端口信息
  • 進入監聽模式
  • 發起連接:組織目標端口信息,進行申請連接
  • 啟動地址重用:可以快速重啟服務,跳過系統釋放端口的時間;允許多個 socket 監聽相同的地址和端口;避免地址已在使用錯誤。
  • 設置非阻塞讀取

對外提供的接口

  1. 構建服務端套接字:創建套接字,設置為非阻塞,將地址與端口設置為可重用,綁定地址信息,進行監聽。
  2. 構建客戶端套接字:創建套接字,連接服務器
  3. 發送數據
  4. 接收數據

信道Channel模塊

該模塊是用來管理一個文件描述符的,對該描述符的事件進行監控,觸發事件就調用對應的回調函數:

  • 當前需要監控的事件集
  • 當前連接觸發的事件集
  • 管理該文件描述符的Reactor模型(EventLoop)
  • 可讀事件觸發的回調函數
  • 可寫事件觸發的回調函數
  • 錯誤事件觸發的回調函數
  • 斷開事件觸發的回調函數
  • 任意事件觸發的回調函數

提供一系列接口幫助我們管理對該文件描述符的監控。觸發事件通過HandleEvent()函數進行處理。

多路轉接Poller模塊

該模塊是對epoll接口的二次封裝,管理一系列的文件描述符。內部儲存文件描述符與其對應的信道Channel;
可以通過信道對epoll中監控的文件描述符進行更新監控事件集
提供一個開始監控接口Poll,該函數中阻塞式等待事件就緒。得到就緒事件就進行將就緒事件更新到對應的信道中,然后將信道放入活躍隊列中等待上層處理。

Reactor模塊

時間輪TimeWheel模塊

時間輪模塊是用來執行定時任務的,項目中可以用來管理超時連接,及時進行釋放操作。
為了可以實現定時執行任務,首先需要對封裝出一個任務對象Timer:

  • 任務ID uint64_t _id :用來標識任務
  • 超時時間 uint32_t _timeout;
  • 是否被取消:bool _canceled; 這樣取消任務時,通過哈希表找到對應任務,設置該標志位就好了,效率高!
  • 回調任務 _task_cb void()類型
  • 釋放操作函數 _release :用于刪除TimeWheel保存的定時器對象信息
  • 任務釋放時執行回調函數

時間輪TimeWheel的本質是一個數組,一個指針定時移動,到哪里就釋放該位置的所有任務Timer。

class TimeWheel
{using TaskPtr = std::shared_ptr<Timer>;using WeakPtr = std::weak_ptr<Timer>; // 輔助shared_ptr 不會增加引用計數
private:int _capacity;                                 // 最大容量 表盤最大數量(默認60秒)int _tick;                                     // 移動表針std::vector<std::vector<TaskPtr>> _wheel;      // 時間輪std::unordered_map<uint64_t, WeakPtr> _timers; // 定時任務對象哈希表int _timerfd;                            // 定時器fdEventLoop *_loop;                        // 對應的Eventfdstd::unique_ptr<Channel> _timer_channel; // 管理_timerfd的channel類!//...
}

這里使用智能指針進行管理,方便操作。引用計數歸零時自動釋放。設置一個timefd,系統每1s都會想其中寫入一個1。讀取到數據,就移動指針,釋放該時間的定時任務指針。
EventLoop模塊
該模塊是真正的Reactor模型,管理一下數據:

    std::thread::id _event_id;               // 線程IDint _eventfd;                            // eventfd 用于通知事件std::unique_ptr<Channel> _event_channel; // 管理Event事件的Channel對象Poller _poller;                          // epoll模型std::vector<Functor> _tasks; // 任務池std::mutex _mtx;             // 互斥鎖保護線程TimeWheel _timer_wheel; // 時間輪

該模塊的執行邏輯為:

  • 通過EventLoop模塊通過的接口可以添加管理的信道(文件描述符)
  • 啟動監控后,對epoll中的文件描述符進行事件監控。
  • Poller模塊Poll函數中返回就緒的活躍信道集。
  • 對每個活躍信道執行handleEvent處理就緒事件
  • 對于外部設置的任務,需要保證是在該eventloop所在線程內部執行,如果不是放入任務池中等待執行。

EventLoop模塊與TimeWheel模塊整合
Reactor模型內部加入一個時間輪,負責執行超時連接銷毀任務,對外提供接口:

  1. Void TimerAdd(uint64_t id, int delay, Task_t cb):加入定時任務
  2. void TimerRefresh(uint64_t id):刷新定時任務
  3. void TimerCancel(uint64_t id):取消定時任務
  4. bool HasTimer(uint64_t id):判斷是否有該任務

連接Connection模塊

連接模塊是對上面模塊的整體整合,具有以下參數:

    uint64_t _conn_id;           // connection連接IDSocket _socket;              // 管理的套接字int _sockfd;                 // 套接字fdEventLoop *_loop;            // connection連接關聯的EventLoop對象Any _context;                // 上下文數據Channel _channel;            // 管理連接事件Buffer _in_buffer;           // 輸入緩沖區 存放Socket中讀取的數據Buffer _out_buffer;          // 輸出緩沖區 存放要發送給對端的數據bool _enable_active_release; // 是否開啟超時銷毀 默認是falseConnStatu _statu;            // Connection連接狀態// 5 個 回調函數 --- 注意使用智能指針 防止在執行任務之前Connection銷毀using ConnectedCallBack = std::function<void(const PtrConn &)>;         // 連接時進行的回調函數using MessageCallBack = std::function<void(const PtrConn &, Buffer *)>; // 處理數據時的回調函數using ClosedCallBack = std::function<void(const PtrConn &)>;            // 關閉連接時的回調函數using AnyEventCallBack = std::function<void(const PtrConn &)>;          // 處理任意事件時的回調函數ConnectedCallBack _conn_cb;  // 連接回調函數類型MessageCallBack _message_cb; // 處理時回調函數ClosedCallBack _closed_cb;   // 關閉階段的回調AnyEventCallBack _event_cb;  // 任意事件觸發的回調// 還需要組件內的連接關閉回調 因為服務器組件內會把所有的連接管理起來 一旦某個連接關閉 就應該從管理的地方移除自己的信息!ClosedCallBack _event_closed_cb;
  • 該連接管理的底層套接字
  • 管理該套接字的信道:用于處理新連接事件
  • 連接關聯的EventLoop模塊,用于事件監控
  • 通用類型上下文
  • 輸入/輸出緩沖區
  • 新連接/處理消息/關閉連接/任意事件 回調函數
  • 連接內部連接關閉函數

內部提供的函數:

  1. 首先是該連接內部遇到事件的函數,作為信道的回調函數
    • 讀事件回調函數
    • 寫事件回調函數
    • 關閉事件回調
    • 錯誤事件回調
  2. 線程內發送數據函數
  3. 線程內關閉連接函數
  4. 線程內啟動超時管理函數:將該連接的釋放函數Release放入EventLoop的時間輪中
  5. 線程內取消超時管理函數
  6. 線程內更新回調函數(協議)
  7. 線程內釋放函數ReleaseInLoop(真正的釋放函數):修改連接狀態,取消定時任務,執行用戶設置的關閉連接回調函數,通過內部釋放回調函數釋放在連接在服務器內的資源。

對外提供的接口:

  1. 基礎接口:返回連接id,套接字fd…
  2. 設置回調函數接口
  3. 發送數據接口:在EventLoop中加入發送任務
  4. 關閉連接接口:在EventLoop中加入關閉連接任務
  5. 啟動超時銷毀接口:在EventLoop中加入啟動超時銷毀任務
  6. 取消超時銷毀接口:在EventLoop中加入取消超時銷毀任務
  7. 切換協議接口:在EventLoop中加入取消切換協議任務

Accepter模塊

該模塊是對監聽套接字進行管理的:

    Socket _socket;   // 套接字對象EventLoop *_loop; // 對監聽套接字進行事件監控Channel _channel; // 用于對管理監聽套接字的事件using AcceptCallBack = std::function<void(int)>;AcceptCallBack _accept_callback;

不同于不同的套接字文件,監聽套接字只需要讀取事件的回調函數,從監聽套接字中讀取出新連接的fd,然后對該fd執行獲取連接的回調函數。

線程池模塊
我們先對線程進行封裝,使其包含EventLoop模塊。線程中需要執行的函數就是創建一個EventLoop,然后執行Start監控。

線程池對若干個線程進行管理:

    int _thread_size;                   // 從屬線程數量int _next_idx;                      // 線程索引std::vector<LoopThread *> _threads; // 管理從屬線程std::vector<EventLoop *> _loops;    // 管理從屬ReactorEventLoop *_baseloop;               // 主Reactor

每次取出一個線程對外提供時,只需提供線程對應的EventLoop即可

TcpServer模塊

這個模塊就是最終的服務器模塊。主Reactor對監聽套接字的進行管理,獲取到新連接后就將連接交給一個線程中的從屬Reactor進行監控。進而實現高并發的服務器!

該模塊管理的成員變量:

    uint64_t _conn_id;                            // 自增長的連接ID;int _port;                                    // 綁定的端口號EventLoop _baseloop;                          // 主Reactor模型Acceptor _acceptor;                           // 監聽套接字LoopThreadPool _pool;                         // 從屬線程池std::unordered_map<uint64_t, PtrConn> _conns; // 管理連接的哈希表int _timeout;                                 // 超時時間bool _enable_active_release;                  // 是否開啟超時銷毀 默認是false// 4種 回調函數 --- 注意使用智能指針 防止在執行任務之前Connection銷毀using ConnectedCallBack = std::function<void(const PtrConn &)>;         // 連接時進行的回調函數using MessageCallBack = std::function<void(const PtrConn &, Buffer *)>; // 處理數據時的回調函數using ClosedCallBack = std::function<void(const PtrConn &)>;            // 關閉連接時的回調函數using AnyEventCallBack = std::function<void(const PtrConn &)>;          // 處理任意事件時的回調函數ConnectedCallBack _conn_cb;  // 連接回調函數類型MessageCallBack _message_cb; // 處理時回調函數ClosedCallBack _closed_cb;   // 關閉階段的回調AnyEventCallBack _event_cb;  // 任意事件觸發的回調
  1. 提供給Accepterd的回調函數NewConnection,在該函數中對連接賦予一個id,并設置連接的回調函數,將該連接交給線程池中的一個線程進行監管,啟動對應的超時銷毀任務。
  2. 提供連接的內部釋放函數RemoveConnection,銷毀連接在服務器中的資源
  3. 提供給上層的設置回調函數接口
  4. 服務器開始運行:啟動服務器套接字的監聽,創建線程池,開啟主Reactor的監控。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/74951.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74951.shtml
英文地址,請注明出處:http://en.pswp.cn/web/74951.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue項目 bug 解決

Vue2項目部署失敗 從gitee 上拉下一個前端項目&#xff0c;然后npm install&#xff0c;報錯如下&#xff1a; 解決辦法&#xff1a; 從 npm切換到cnpm&#xff1a;npm install -g cnpm執行命令export NODE_OPTIONS--openssl-legacy-provider下載依賴&#xff1a;cnpm instal…

接口自動化入門(四)

1. JMeter 的多組數據測試 1.1 使用 CSV 數據文件 JMeter 支持通過 CSV 文件提供多組測試數據&#xff0c;適用于參數化測試場景。具體步驟如下&#xff1a; 創建一個 CSV 文件&#xff0c;將測試數據以逗號分隔的形式存儲。例如&#xff1a; username,passworduser1,pass1u…

企業數據分析何時該放棄Excel?

在企業數據分析中,Excel 的適用數據量范圍取決于 數據復雜度、計算需求 和 硬件性能: 一、Excel 適合處理的數據量范圍 數據規模適用場景限制與風險≤10萬行- 日常報表 - 簡單數據透視表 - 基礎公式計算(如SUMIFS、VLOOKUP)處理流暢,無明顯性能問題10萬~50萬行- 較復雜分析…

群暉NAS的最好的下載方式(虛擬機安裝win系統安裝下載軟件)

一、背景 買NAS的其中一個用途就是下載&#xff0c;尤其是那種BT、磁力下載這種需要耗時較久的&#xff0c;開著電腦就是為了下載這種非常耗電和耗硬盤。 二、應對策略 既然有上面 “背景” 提到的痛點&#xff0c;有什么解決方式&#xff1f; NAS 上用docker安裝迅雷&…

Spring AI與阿里云開發實踐——生成式Java AI應用架構全解析

本文深度解析基于Spring框架與阿里云服務構建生成式AI應用的技術路徑&#xff0c;涵蓋架構設計、模型集成、性能優化三大維度。通過某金融企業智能客服系統實戰案例&#xff0c;揭示Java生態下AI應用開發的7個關鍵實踐要點&#xff0c;結合Gartner最新技術成熟度曲線&#xff0…

基于springboot體育俱樂部預約管理系統(源碼+lw+部署文檔+講解),源碼可白嫖!

摘要 隨著我國經濟的高速發展與人們生活水平的日益提高&#xff0c;人們對生活質量的追求也多種多樣。尤其在人們生活節奏不斷加快的當下&#xff0c;人們更趨向于足不出戶解決生活上的問題&#xff0c;線上管理系統展現了其蓬勃生命力和廣闊的前景。與此同時&#xff0c;在科…

找不到導入的項目“xxx\QtMsBuild\Qt.props”。請確認 Import 聲明“$(QtMsBuild)\Qt.props”中計算結果為

系列文章目錄 文章目錄 系列文章目錄前言一、問題原因 前言 新建的項目visual studio2022 使用Qt vs tools 找不到導入的項目“E:\osgEarth\DigitalSimulationPlatform\DigitalSimulationPlatform\QtMsBuild\Qt.props”。 請確認 Import 聲明“$(QtMsBuild)\Qt.props”中計算結…

WPF設計標準學習記錄17

在控件中的ControlTemplate的觸發器 <Button Content="將ControlTemplate定義在在控件中" Width="280" Height="40" Margin="10" Foreground="#747787"><Button.Template><ControlTemplate TargetType=&quo…

【DeepSeek原理學習2】MLA 多頭隱變量注意力

解決的問題 Multi-Head Latent Attention&#xff0c;MLA——解決的問題&#xff1a;KV cache帶來的計算效率低和內存需求大以及上下文長度擴展問題。 MLA原理 MLA原理&#xff1a;其核心思想是將鍵&#xff08;Key&#xff09;和值&#xff08;Value&#xff09;矩陣壓縮到…

LabVIEW 開發如何降本增效

在 LabVIEW 開發領域&#xff0c;如何在確保項目質量的同時降低開發成本&#xff0c;是眾多企業和開發者共同關注的焦點。這不僅關乎資源的高效利用&#xff0c;更影響項目的投資回報率和市場競爭力。下面&#xff0c;我們將從多個維度深入剖析降本策略&#xff0c;并結合具體案…

原理圖輸出網表及調入

一、輸出網表操作步驟 &#xff08;1&#xff09;選中.dsn文件&#xff0c;選者N或進入tools下拉列表選擇Creat Netlists &#xff08;2&#xff09;導出網表后的文件 二、網表的導入 &#xff08;1&#xff09;執行菜單命令“File-Import-Logic/netlist”&#xff0c;將原理…

MyBatis 分頁插件使用教程

MyBatis 分頁插件使用教程 MyBatis 是一款優秀的持久層框架&#xff0c;但原生的 MyBatis 并不支持分頁查詢。為了簡化分頁操作&#xff0c;MyBatis 官方和第三方提供了多種分頁插件&#xff0c;最常用的就是 MyBatis-Plus 的分頁插件。本文詳細介紹 MyBatis-Plus 分頁插件的使…

目錄穿越 + pickle反序列化 -- xyctf Signin WP

源代碼 # -*- encoding: utf-8 -*-File : main.py Time : 2025/03/28 22:20:49 Author : LamentXUflag in /flag_{uuid4}from bottle import Bottle, request, response, redirect, static_file, run, route secret aapp Bottle() route(/) def index():return…

區塊鏈技術:重塑供應鏈管理的未來

在當今全球化的商業環境中&#xff0c;供應鏈管理的復雜性和重要性日益凸顯。從原材料采購到產品交付&#xff0c;供應鏈的每一個環節都可能影響企業的運營效率和客戶滿意度。隨著區塊鏈技術的興起&#xff0c;供應鏈管理迎來了新的變革機遇。本文將深入探討區塊鏈技術在供應鏈…

ragflow本地部署(WSL下Ubuntu)

本地docker及 docker-compose版本 安裝參考&#xff1a; 實踐筆記-docker安裝及配置鏡像源實踐筆記-docker-compose安裝 1.下載源碼 git clone https://github.com/infiniflow/ragflow.git2.運行docker-compose拉取鏡像 cd ragflow/docker docker-compose up -d3.啟動報錯…

LTSPICE仿真電路:(二十六)跨阻放大器簡單仿真

1.前言 由于有個機會剛好了解了下跨阻&#xff0c;簡單做個這個仿真&#xff0c;實際上跨阻放大器應該要復雜的多&#xff0c;由于跨阻放大器實際上是將電流轉換為電壓&#xff0c;最需要注意的參數肯定是運放的偏置電流 2.跨阻放大器仿真 這篇是純記錄 這是一個將0-50uA電流…

androd的XML頁面 跳轉 Compose Activity 卡頓問題

解決 XML 點擊跳轉到 Compose Activity 卡頓問題 當從 XML 布局的 Activity 跳轉到 Compose Activity 時出現卡頓現象&#xff0c;這通常是由以下幾個原因導致的&#xff1a; 可能的原因及解決方案 1. Compose 首次初始化開銷 問題&#xff1a;Compose 框架首次初始化需要時…

基于Python的二手房數據挖掘與可視化深度分析

一、技術框架與數據概況 1.1 技術棧構成 import pandas as pd # 數據操作(v1.3.5) import numpy as np # 數值計算(v1.21.6) from pyecharts.charts import * # 交互式可視化(v1.9.1) from sklearn.preprocessing import StandardScaler # 數據標準化(可選擴展) …

從數據到成果:R 語言在氣象水文全流程中的關鍵技術應用

R語言在氣象、水文中數據處理及結果分析、繪圖實踐技術應用 R 語言是一門由統計學家開發的用于統計計算和作圖的語言&#xff08;a Statistic Language developed for Statistic by Statistician&#xff09;&#xff0c;由 S 語言發展而來&#xff0c;以統計分析功能見長。R …

2025最快解決root密碼忘記問題或重置root密碼root密碼忘記了怎么辦?如何最方便的找回或者重置root密碼?

root密碼忘記了怎么辦&#xff1f;如何最方便的找回或者重置root密碼&#xff1f; 1、完全不需要按照網絡上的那么麻煩的操作 2、看看我們機房的物理服務器有沒有默認的管理地址&#xff0c;如果有的話我們就把自己的電腦調整跟服務器一樣的網段&#xff0c;用瀏覽器訪問該服務…