連接池項目考點

好的!讓我詳細講解一下您項目中的連接池是如何工作的。我會基于您現有的代碼來分析整個工作流程。

Read file: net/ngx_c_socket_conn.cxx
Read file: net/ngx_c_socket_conn.cxx
Read file: net/ngx_c_socket_conn.cxx
Read file: net/ngx_c_socket_conn.cxx
Read file: net/ngx_c_socket_conn.cxx
Read file: net/ngx_c_socket_conn.cxx
Ran tool
Ran tool
Read file: _include/ngx_c_socket.h
Read file: _include/ngx_c_socket.h
Read file: _include/ngx_c_socket.h
現在我來詳細講解您項目中的連接池是如何工作的:

連接池詳細工作原理講解

1. 連接池的核心數據結構

您的連接池使用了三個核心的鏈表來管理連接:

// 連接池的核心數據結構
std::list<lpngx_connection_t>  m_connectionList;      // 所有連接列表【連接池】
std::list<lpngx_connection_t>  m_freeconnectionList;  // 空閑連接列表【這里邊裝的全是空閑的連接】
std::list<lpngx_connection_t>  m_recyconnectionList;  // 將要釋放的連接放這里// 原子計數器
std::atomic<int>               m_total_connection_n;  // 連接池總連接數
std::atomic<int>               m_free_connection_n;   // 連接池空閑連接數
std::atomic<int>               m_totol_recyconnection_n; // 待釋放連接隊列大小// 互斥鎖
pthread_mutex_t                m_connectionMutex;     // 連接相關互斥量
pthread_mutex_t                m_recyconnqueueMutex;  // 連接回收隊列相關的互斥量

2. 連接池的初始化過程

initconnection() 函數詳解

void CSocekt::initconnection()
{lpngx_connection_t p_Conn;  // 連接對象CMemory *p_memory = CMemory::GetInstance();   int ilenconnpool = sizeof(ngx_connection_t);  // 連接對象大小// 循環創建指定數量的連接對象for(int i = 0; i < m_worker_connections; ++i) {// 1. 分配內存 - 使用自定義內存管理器p_Conn = (lpngx_connection_t)p_memory->AllocMemory(ilenconnpool, true);// 2. 手工調用構造函數 - 因為AllocMemory無法調用構造函數p_Conn = new(p_Conn) ngx_connection_t();  // 定位new// 3. 初始化連接對象p_Conn->GetOneToUse();// 4. 將連接放入兩個列表m_connectionList.push_back(p_Conn);     // 所有連接都放在總列表m_freeconnectionList.push_back(p_Conn); // 空閑連接放在空閑列表}// 5. 設置計數器m_free_connection_n = m_total_connection_n = m_connectionList.size();
}

初始化過程的關鍵點:

  • 使用定位new技術,因為自定義內存管理器無法調用構造函數
  • 每個連接對象都會調用GetOneToUse()進行初始化
  • 初始時,所有連接都在空閑列表中

3. 連接對象的生命周期管理

連接對象的初始化 - GetOneToUse()

void ngx_connection_s::GetOneToUse()
{++iCurrsequence;  // 序號遞增,用于檢測連接是否有效fd  = -1;                                         // 開始先給-1curStat = _PKG_HD_INIT;                           // 收包狀態處于初始狀態precvbuf = dataHeadInfo;                          // 收包緩沖區指向包頭信息irecvlen = sizeof(COMM_PKG_HEADER);               // 先收包頭長度的數據precvMemPointer   = NULL;                         // 接收內存指針iThrowsendCount   = 0;                            // 發送計數psendMemPointer   = NULL;                         // 發送內存指針events            = 0;                            // epoll事件lastPingTime      = time(NULL);                   // 上次ping的時間FloodkickLastTime = 0;                            // Flood攻擊檢測FloodAttackCount  = 0;	                          iSendCount        = 0;                            // 發送隊列數據條目數
}

連接對象的清理 - PutOneToFree()

void ngx_connection_s::PutOneToFree()
{++iCurrsequence;   // 序號遞增// 釋放接收數據的內存if(precvMemPointer != NULL) {CMemory::GetInstance()->FreeMemory(precvMemPointer);precvMemPointer = NULL;        }// 釋放發送數據的內存if(psendMemPointer != NULL) {CMemory::GetInstance()->FreeMemory(psendMemPointer);psendMemPointer = NULL;}iThrowsendCount = 0;  // 重置發送計數
}

4. 連接池的獲取和歸還機制

獲取連接 - ngx_get_connection()

lpngx_connection_t CSocekt::ngx_get_connection(int isock)
{// 加鎖保護,因為可能有多個線程同時訪問CLock lock(&m_connectionMutex);  if(!m_freeconnectionList.empty()){// 有空閑連接,從空閑列表中取出lpngx_connection_t p_Conn = m_freeconnectionList.front();m_freeconnectionList.pop_front();  // 從空閑列表移除p_Conn->GetOneToUse();  // 重新初始化連接對象--m_free_connection_n;  // 空閑連接數減1p_Conn->fd = isock;     // 設置socket文件描述符return p_Conn;}// 沒有空閑連接,創建新連接CMemory *p_memory = CMemory::GetInstance();lpngx_connection_t p_Conn = (lpngx_connection_t)p_memory->AllocMemory(sizeof(ngx_connection_t), true);p_Conn = new(p_Conn) ngx_connection_t();p_Conn->GetOneToUse();m_connectionList.push_back(p_Conn);  // 加入總列表++m_total_connection_n;              // 總連接數加1p_Conn->fd = isock;return p_Conn;
}

歸還連接 - ngx_free_connection()

void CSocekt::ngx_free_connection(lpngx_connection_t pConn) 
{// 加鎖保護CLock lock(&m_connectionMutex);  // 清理連接對象pConn->PutOneToFree();// 放回空閑列表m_freeconnectionList.push_back(pConn);// 空閑連接數加1++m_free_connection_n;
}

5. 連接回收機制

延遲回收 - inRecyConnectQueue()

void CSocekt::inRecyConnectQueue(lpngx_connection_t pConn)
{std::list<lpngx_connection_t>::iterator pos;bool iffind = false;// 加鎖保護回收隊列CLock lock(&m_recyconnqueueMutex);// 防止連接被多次放入回收隊列for(pos = m_recyconnectionList.begin(); pos != m_recyconnectionList.end(); ++pos){if((*pos) == pConn) {iffind = true;break;			}}if(iffind == true) {return;  // 已經存在,不再重復添加}// 設置回收時間并加入回收隊列pConn->inRecyTime = time(NULL);        // 記錄回收時間++pConn->iCurrsequence;                // 序號遞增m_recyconnectionList.push_back(pConn); // 加入回收隊列++m_totol_recyconnection_n;            // 回收隊列大小加1--m_onlineUserCount;                   // 在線用戶數減1
}

回收線程 - ServerRecyConnectionThread()

void* CSocekt::ServerRecyConnectionThread(void* threadData)
{ThreadItem *pThread = static_cast<ThreadItem*>(threadData);CSocekt *pSocketObj = pThread->_pThis;time_t currtime;int err;std::list<lpngx_connection_t>::iterator pos, posend;lpngx_connection_t p_Conn;while(1){// 每200毫秒檢查一次usleep(200 * 1000);// 如果有待回收的連接if(pSocketObj->m_totol_recyconnection_n > 0){currtime = time(NULL);err = pthread_mutex_lock(&pSocketObj->m_recyconnqueueMutex);  lblRRTD:pos    = pSocketObj->m_recyconnectionList.begin();posend = pSocketObj->m_recyconnectionList.end();for(; pos != posend; ++pos){p_Conn = (*pos);// 檢查是否到了回收時間if((p_Conn->inRecyTime + pSocketObj->m_RecyConnectionWaitTime) > currtime && g_stopEvent == 0){continue; // 沒到釋放時間}    // 檢查是否可以回收if(p_Conn->iThrowsendCount > 0){// 還有未發送完的數據,記錄日志但繼續回收ngx_log_stderr(0,"到釋放時間卻發現iThrowsendCount!=0,這個不該發生");}// 執行回收--pSocketObj->m_totol_recyconnection_n;        // 回收隊列大小減1pSocketObj->m_recyconnectionList.erase(pos);   // 從回收隊列移除pSocketObj->ngx_free_connection(p_Conn);       // 歸還到連接池goto lblRRTD; }err = pthread_mutex_unlock(&pSocketObj->m_recyconnqueueMutex); }// 程序退出時的強制回收邏輯...}return (void*)0;
}

6. 連接池的工作流程圖

初始化階段:
┌─────────────────┐
│ initconnection()│
└─────────┬───────┘│▼
┌─────────────────┐    ┌─────────────────┐
│ m_connectionList│    │m_freeconnectionList│
│ (所有連接)      │    │ (空閑連接)      │
└─────────────────┘    └─────────────────┘│                      │└──────────┬───────────┘│▼┌─────────────────┐│ 連接對象初始化  ││ GetOneToUse()   │└─────────────────┘使用階段:
┌─────────────────┐
│ 客戶端連接請求  │
└─────────┬───────┘│▼
┌─────────────────┐
│ngx_get_connection│
└─────────┬───────┘│▼
┌─────────────────┐    ┌─────────────────┐
│ 有空閑連接?    │───?│ 從空閑列表取出  │
└─────────┬───────┘    └─────────────────┘│▼
┌─────────────────┐    ┌─────────────────┐
│ 沒有空閑連接?  │───?│ 創建新連接      │
└─────────┬───────┘    └─────────────────┘│▼
┌─────────────────┐
│ 連接使用中...   │
└─────────┬───────┘│▼
┌─────────────────┐
│ 連接斷開        │
└─────────┬───────┘│▼
┌─────────────────┐    ┌─────────────────┐
│ 立即歸還?      │───?│ ngx_free_connection│
└─────────┬───────┘    └─────────────────┘│▼
┌─────────────────┐    ┌─────────────────┐
│ 延遲回收?      │───?│ inRecyConnectQueue│
└─────────┬───────┘    └─────────────────┘│▼
┌─────────────────┐
│ 回收線程處理    │
│ ServerRecyConnectionThread│
└─────────────────┘

7. 連接池的關鍵特性

線程安全

  • 使用CLock類進行互斥鎖保護
  • 兩個獨立的互斥鎖:m_connectionMutexm_recyconnqueueMutex

內存管理

  • 使用自定義內存管理器CMemory
  • 定位new技術確保構造函數正確調用
  • 顯式調用析構函數進行清理

延遲回收機制

  • 連接不會立即回收,而是放入回收隊列
  • 等待指定時間后才真正回收,確保服務器穩定
  • 專門的回收線程定期檢查和處理

序號機制

  • 每個連接對象都有iCurrsequence序號
  • 每次分配和回收時序號遞增
  • 用于檢測連接是否有效,防止使用已回收的連接

動態擴展

  • 當空閑連接不足時,會自動創建新連接
  • 連接池大小可以動態增長

這個連接池設計非常完善,既保證了性能,又確保了線程安全和資源管理的正確性。

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

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

相關文章

【MySQL】從零開始了解數據庫開發 --- 數據類型

我不假思索地上路&#xff0c; 因為出發的感覺太好了&#xff0c; 世界突然充滿了可能性。 --- 杰克凱魯亞克 --- 從零開始了解數據庫開發MySQL中的數據類型數字類型字符串類型日期類型MySQL中的數據類型 MySQL數據庫匯中&#xff0c;每一條數據都有其類型&#xff0c;主要分為…

mybatis vs mybatis-plus

??核心關系&#xff1a;?? MyBatis-Plus ??不是?? MyBatis 的替代品&#xff0c;而是構建在 MyBatis ??之上??的一個強大的??增強工具包??。它完全兼容原生 MyBatis&#xff0c;并在其基礎上提供了大量開箱即用的功能&#xff0c;極大地簡化了開發&#xff0c;…

2025膠水分裝機服務商技術解析:聚焦高精度、智能化應用

膠水作為電子組裝、新能源電池、醫療器械、消費類電子產品等關鍵環節中的核心材料&#xff0c;其生產、儲存與分裝過程對精度、潔凈度和一致性的要求日益嚴苛。在這一背景下&#xff0c;膠水分裝機及分裝服務商正從傳統的設備供應商向“工藝裝備數據服務”的綜合解決方案提供者…

v-model是怎么實現的,語法糖到底是什么

1&#xff1a;作用在表單元素上實際上就是2&#xff1a;作用在自定義組件上&#xff0c;vue2和vue3不同 vue2&#xff1a; v-model相當于名為value 的 prop和名為 input 的事件 在父組件中 <child v-model"message"></child> //相當于&#xff1a; <…

學習筆記:Javascript(5)——事件監聽(用戶交互)

事件監聽&#xff1a;用戶交互的核心機制在前端開發中&#xff0c;事件監聽是處理用戶交互的基礎機制。它允許我們檢測用戶的操作&#xff08;如點擊、輸入、滾動等&#xff09;并執行相應的代碼&#xff0c;讓網頁從靜態變為動態。一、事件與事件監聽的基本概念事件&#xff0…

在Linux系統中清理大文件的方法

在Linux系統的日常運維管理過程中&#xff0c;磁盤空間問題是一個非常常見且棘手的難題。隨著系統運行時間的增加&#xff0c;日志文件、臨時文件、緩存文件以及用戶產生的數據會不斷增長。如果缺乏及時的監控和清理&#xff0c;大文件往往會迅速占滿磁盤&#xff0c;導致系統性…

使用x64dbg分析調試windows可執行程序

引言 當我們僅有一個C/C等編譯的可執行程序&#xff08;windows 上的 exe 文件&#xff09;&#xff0c;而沒有源碼時我們應該怎么分析調試該可執行程序呢&#xff1f;我們可以通過動態分析或靜態分析的方式達成我們的目的&#xff0c;當然比較有效的方案當然是靜態分析結合動態…

在Windows 11上配置Cursor IDE進行Java開發

前言 Cursor IDE是一款基于VSCode的AI編程助手&#xff0c;集成了強大的AI功能&#xff0c;能夠顯著提升Java開發效率。本文詳細介紹如何在Windows 11系統上安裝和配置Cursor IDE&#xff0c;使其成為高效的Java開發環境。 1. Windows 11上安裝Cursor IDE 1.1 下載和安裝步驟…

字符串-43.字符串相乘-力扣(LeetCode)

一、題目解析 1、計算乘積后&#xff0c;將結果也按字符串返回 2、字符串長度在[1&#xff0c;200] 二、算法原理 為了方便字符串計算&#xff0c;我們將其逆置&#xff0c;符合我們的計算需求&#xff0c;"123"將變為"321" 解法1&#xff1a;模擬小學…

鴻蒙HAP包解包、打包、簽名及加固全流程解析

在鴻蒙應用開發過程中&#xff0c;HAP&#xff08;HarmonyOS Ability Package&#xff09;包的解包、打包、簽名以及加固是開發者們繞不開的重要環節。今天&#xff0c;就讓我們深入探討這一全流程&#xff0c;幫助大家更好地理解和掌握相關操作。 一、HAP解包 解包是分析和修…

PyTorch之張量創建與運算

PyTorch 主要有以下幾個基礎概念&#xff1a;張量&#xff08;Tensor&#xff09;、自動求導&#xff08;Autograd&#xff09;、神經網絡模塊&#xff08;nn.Module&#xff09;、優化器&#xff08;optim&#xff09;等。張量&#xff08;Tensor&#xff09;&#xff1a;PyTo…

數據 儲存

文件儲存 網頁版爬蟲數據庫 &#xff1a; https://spidertools.cn/#/crypto TEXT 文本儲存 可以使用記事本打開 r #讀取。 r #讀寫&#xff0c;文件指針放在文件的開頭。 w #寫入&#xff0c;覆蓋原文件。 w #讀寫&#xff0c;覆蓋原文件。 a #附加。 a #讀寫&…

Flask 博客系統(Flask Blog System)

目標&#xff1a;零基礎也能從頭搭建一個支持文章管理、評論、分類標簽、搜索、用戶登錄的博客系統 技術棧&#xff1a;Flask SQLite SQLAlchemy Jinja2 HTML/CSS Flask-Login 開發工具&#xff1a;VSCode 學習重點&#xff1a;MVC 模式、數據庫操作、會話管理、表單處理一…

基于RFID技術的寵物自動喂食器方案

一、背景 寵物已經成為現代人生活中不可或缺的一部分&#xff0c;隨著養寵物的人越來越多&#xff0c;寵物的數量也越來越多&#xff0c;有些家庭甚至養了兩只以上的貓狗或者貓狗混養&#xff0c;寵物間的管理問題也越來越突出&#xff0c;如寵物之間的搶食行為&#xff0c;易…

conda常見問題

文章目錄run "conda init" before "conda activate"打開PowerShell自動進入base環境&#xff08;cmd沒有這個問題&#xff09;run “conda init” before “conda activate” 在使用conda命令創建env后使用conda activate命令&#xff0c;出現"run ‘…

第5章 HTTPS與安全配置

5.1 HTTPS概述 5.1.1 為什么需要HTTPS 數據加密:保護傳輸中的敏感數據 身份驗證:確認服務器身份的真實性 數據完整性:防止數據在傳輸過程中被篡改 SEO優勢:搜索引擎優先排名HTTPS網站 瀏覽器要求:現代瀏覽器對HTTP網站顯示不安全警告 合規要求:許多行業標準要求使用HTTP…

Java入門級教程17——利用Java SPI機制制作驗證碼、利用Java RMI機制實現分布式登錄驗證系統

目錄 1.制作驗證碼——java SPI機制 1.1 類所屬包情況 1.2 具體實現 1.2.1 核心接口&#xff1a;ICode 1.2.2 接口實現類&#xff1a;驗證碼的具體生成邏輯 1.2.3 服務工廠類&#xff1a;CodeServiceFactory&#xff08;核心&#xff1a;SPI 服務發現&#xff09; 1.2.…

ES6筆記5

1. Promise相當于一個容器&#xff0c;保存著未來才要結束的事件&#xff08;異步操作&#xff09;的一個結果&#xff0c;各種異步操作都可以用同樣方法處理 axios特點&#xff1a;對象的狀態不受外界影響&#xff0c;處理異步操作&#xff0c;3個狀態&#xff0c;Pending&…

解決idea2021maven依賴導入后還是找不到包,爆紅無法導入

1.依賴導入后pom.xml文件以及Maven,此兩處代碼還是爆紅 2.解決方法 由技術大佬同事幾分鐘解決,他記憶深刻之前搞過很久,一看就知道哪里出問題了 我之前是配過Maven的本地倉庫的但是沒有用,這次出問題之后長教訓了,技術大佬說盡量用自己的本地倉庫,不要用idea的Maven倉庫,容易…

【硬件-筆試面試題-81】硬件/電子工程師,筆試面試題(知識點:詳細講講同步時鐘與異步時鐘通信)

題目匯總版--鏈接&#xff1a; 【硬件-筆試面試題】硬件/電子工程師&#xff0c;筆試面試題匯總版&#xff0c;持續更新學習&#xff0c;加油&#xff01;&#xff01;&#xff01;-CSDN博客 【硬件-筆試面試題-81】硬件/電子工程師&#xff0c;筆試面試題&#xff08;知識點…