前言
高併發系統中,頻繁建立/關閉 Socket 連線(短連線)效能差;長期保持大量連線(長連線)佔用伺服器資源。連線池結合兩者優點:預先建立連線、閒置時重用、忙碌時等待、動態擴縮。本文提供完整實作範例。
連線模式對比
| 模式 | 優點 | 缺點 | 適用場景 |
| 長連線 | 無連線建立延遲、低延遲 | 佔用伺服器連線數、需心跳維持 | 即時通訊、遊戲、高頻交易 |
| 短連線 | 釋放資源快、併發承載高 | 三次交握開銷大、延遲高 | 低頻請求、REST API、批次處理 |
| 連線池 | 平衡延遲與資源、動態調整 | 實作複雜、需管理狀態 | 高併發、混合負載、企業級應用 |
核心設計:Socket 封裝類別
public class XiegouSocket
{
public Socket Socket { get; set; } // 底層 Socket
public bool IsFree { get; set; } // 閒置標記
public int Index { get; set; } // 池中索引
}
連線池建立完整程式碼
public XiegouSocket[] SocketPool { get; private set; }
public void CreateSocketPool(string ip = "127.0.0.1", int port = 2003, int poolSize = 200)
{
IPAddress serverIp = IPAddress.Parse(ip);
IPEndPoint endPoint = new IPEndPoint(serverIp, port);
SocketPool = new XiegouSocket[poolSize];
for (int i = 0; i < poolSize; i++)
{
var socketWrapper = new XiegouSocket
{
Index = i,
IsFree = true,
Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
};
// 設定發送逾時 1 秒,避免阻塞
socketWrapper.Socket.SetSocketOption(
SocketOptionLevel.Socket,
SocketOptionName.SendTimeout,
1000);
// 建立連線
socketWrapper.Socket.Connect(endPoint);
SocketPool[i] = socketWrapper;
}
}
連線取得與歸還邏輯
// 取得可用連線(簡單版:輪詢尋找)
public XiegouSocket AcquireSocket()
{
lock (SocketPool)
{
// 尋找閒置連線
var freeSocket = SocketPool.FirstOrDefault(s => s.IsFree);
if (freeSocket != null)
{
freeSocket.IsFree = false;
return freeSocket;
}
// 可選:動態擴容或拋出例外/等待
throw new InvalidOperationException("連線池耗盡,無可用連線");
}
}
// 歸還連線
public void ReleaseSocket(XiegouSocket socket)
{
lock (SocketPool)
{
if (socket != null && socket.Index >= 0 && socket.Index < SocketPool.Length)
{
socket.IsFree = true;
}
}
}
// 使用範例
public void SendData(byte[] data)
{
var socket = AcquireSocket();
try
{
socket.Socket.Send(data);
// 接收回應...
}
finally
{
ReleaseSocket(socket);
}
}
進階擴充建議
- 非同步模式:使用
SocketAsyncEventArgs 或 await Socket.SendAsync() 避免阻塞執行緒
- 健康檢查:定期發送心跳封包,移除失效連線並重建
- 公平佇列:用
ConcurrentQueue<XiegouSocket> 管理閒置連線,避免輪詢
- 動態縮放:監控使用率,超過 80% 擴容、低於 20% 縮容
- 連線驗證:取得連線前檢查
Socket.Connected 與 Poll(0, SelectMode.SelectRead)
- 統計監控:記錄取得/歸還耗時、等待次數、錯誤率,整合至 APM 系統
生產環境考量
| 風險 | 緩解措施 |
| 連線洩漏(忘記 Release) | 使用 using 模式包裝 AcquireSocket() 回傳 IDisposable |
| 死連線未偵測 | 啟用 TCP Keep-Alive 或應用層心跳 |
| 執行緒飢餓 | 採用非同步 I/O,避免同步阻塞執行緒池 |
| 連線風暴 | 實作斷路器模式,失敗率過高時快速失敗 |
總結
Socket 連線池是高併發網路程式的核心基礎設施。核心在於預先建立、狀態管理、閒置重用、動態調整。本文提供的基礎實作可直接用於中小型專案;大型系統建議採用成熟框架(如 System.Net.Http.HttpClient 內建連線池、gRPC、WCF、或第三方如 StackExchange.Redis 連線多工)。
- 上一篇文章: C# 播放透明背景 AVI:使用 Animation 控制項替代 MediaPlayer
- 下一篇文章: C# 獨有特性解析:自動屬性、集合初始化器、多行 Lambda
Copyright ©
程式碼之家 All Rights Reserved