(一)功能
使用已存在的連接與rpc-server端通信,發送請求
- 連接復用
- 並發請求
(二)設計思路
對每個要通信的server端維持一個連接池,存放已經建立的連接,需要與server通信時直接從連接池取連接,不用重新創建
- 動態連接池
連接池中連接的數量是動態變化的,如果上一時刻請求多,現在請求少,則連接池中可用連接多;相反,如果上一時刻請求少,現在請求多,則連接池中可用連接少
- 使用epoll監聽連接池中連接
當連接被放入連接池后,使用epoll清理該連接現在到來的數據,因為這些數據是無效數據
(三)數據結構
- con_pool連接池
序號 | 成員 | 類型 | 含義 |
1 | mutexLock | pthread_mutex_t | |
2 | client | xxClient*[POOL_SIZE] | 客戶端維持的對象池 |
3 | socket | int[POOL_SIZE] | 客戶端維持的連接池 |
4 | epfd | int | 用來監控client端連接池中可用連接的epoll fd |
5 | isPurge | int | 標記位,當前連接池是否正在對連接做檢測操作 |
6 | nEvent | int | epoll中監聽fd數量 |
7 | nConn | int | 連接池中可用連接數量 |
8 | nMaxConn | int | 連接池中最大可用連接數量 |
9 | host | int | server端ip |
10 | port | int | server端port |
(四)實現
- con_pool* init_con_pool(host, port)
=> 初始化連接池,分配空間+初始化變量
- int con_purge_data(*pool)
=> 監聽&管理連接池中可用連接,清理錯誤or無效連接
1)可讀事件,read出錯or未讀到數據,則從epoll監聽中刪除fd且關閉連接;read未讀完,繼續加入監聽
2)EPOLLHUP,對方關閉連接,則從epoll監聽中刪除fd且關閉連接
3)EPOLLERR,連接出錯,則從epoll監聽中刪除fd且關閉連接
- int get_from_con_pool(*pool, &fd, **client)
=> 從連接池獲取有效連接
遍歷連接池,找到第一個有效連接fd和client,取出(socket置-1,從epoll中刪除監聽);
如果連接池中沒有可用連接,新建連接
- bool put_to_con_pool(*pool, fd, *client)
=> 將連接放回連接池
在client和socket數組中找到第一個可用空位,將fd,*client放入,並將fd加入epoll監聽
如果沒有空位,連接池滿,直接關閉連接
(五)使用
- 取連接
1)con_purge_data,先保證連接池中連接有效
2)get_from_con_pool,再從連接池取出第一個有效連接
- 放回連接
put_to_con_pool,直接放回連接池
(六)問題
- con_purge_data中有EPOLLIN事件且read返回0時,為什么要關閉連接?
此時client端為tcp被動關閉端,如果不調用close,連接池中會有大量socket處於close_wait狀態,占用socket資源導致打開socket過多,最后崩潰