|
|
@ -3,6 +3,8 @@ using CellularManagement.WebSocket.Connection; |
|
|
|
using CellularManagement.WebSocket.Models; |
|
|
|
using Microsoft.AspNetCore.Http; |
|
|
|
using Microsoft.Extensions.Logging; |
|
|
|
using System.Diagnostics; |
|
|
|
using Microsoft.Extensions.Options; |
|
|
|
|
|
|
|
namespace CellularManagement.WebSocket.Middleware; |
|
|
|
|
|
|
@ -17,17 +19,20 @@ public class WebSocketMiddleware |
|
|
|
private readonly IWebSocketMessageQueueManager _messageQueueManager; |
|
|
|
private readonly ILogger<WebSocketMiddleware> _logger; |
|
|
|
private readonly int _bufferSize = 1024 * 4; |
|
|
|
private readonly WebSocketOptions _options; |
|
|
|
|
|
|
|
public WebSocketMiddleware( |
|
|
|
RequestDelegate next, |
|
|
|
IWebSocketConnectionManager connectionManager, |
|
|
|
IWebSocketMessageQueueManager messageQueueManager, |
|
|
|
ILogger<WebSocketMiddleware> logger) |
|
|
|
ILogger<WebSocketMiddleware> logger, |
|
|
|
IOptions<WebSocketOptions> options) |
|
|
|
{ |
|
|
|
_next = next; |
|
|
|
_connectionManager = connectionManager; |
|
|
|
_messageQueueManager = messageQueueManager; |
|
|
|
_logger = logger; |
|
|
|
_options = options.Value; |
|
|
|
_logger.LogInformation("初始化 WebSocket 中间件,缓冲区大小:{BufferSize}字节", _bufferSize); |
|
|
|
} |
|
|
|
|
|
|
@ -80,33 +85,88 @@ public class WebSocketMiddleware |
|
|
|
{ |
|
|
|
_logger.LogInformation("开始处理 WebSocket 连接,连接ID:{ConnectionId}", connectionId); |
|
|
|
|
|
|
|
var stopwatch = new Stopwatch(); |
|
|
|
var messageCount = 0; |
|
|
|
var totalBytes = 0L; |
|
|
|
|
|
|
|
using var messageStream = new MemoryStream(); |
|
|
|
var buffer = new byte[_bufferSize]; |
|
|
|
var receiveResult = await webSocket.ReceiveAsync( |
|
|
|
new ArraySegment<byte>(buffer), CancellationToken.None); |
|
|
|
_logger.LogDebug("收到第一条消息,连接ID:{ConnectionId},消息类型:{MessageType},数据大小:{DataSize}字节", |
|
|
|
connectionId, receiveResult.MessageType, receiveResult.Count); |
|
|
|
|
|
|
|
while (!receiveResult.CloseStatus.HasValue) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
var message = new WebSocketMessage |
|
|
|
stopwatch.Start(); |
|
|
|
|
|
|
|
// 检查消息大小
|
|
|
|
if (messageStream.Length + receiveResult.Count > _options.MaxMessageSize) |
|
|
|
{ |
|
|
|
ConnectionId = connectionId, |
|
|
|
Data = buffer.Take(receiveResult.Count).ToArray(), |
|
|
|
MessageType = receiveResult.MessageType |
|
|
|
}; |
|
|
|
_logger.LogWarning("消息大小超过限制,连接ID:{ConnectionId},当前大小:{CurrentSize},最大限制:{MaxSize}", |
|
|
|
connectionId, messageStream.Length + receiveResult.Count, _options.MaxMessageSize); |
|
|
|
await webSocket.CloseAsync( |
|
|
|
WebSocketCloseStatus.MessageTooBig, |
|
|
|
"Message too big", |
|
|
|
CancellationToken.None); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 处理消息分片
|
|
|
|
if (receiveResult.MessageType == WebSocketMessageType.Text || |
|
|
|
receiveResult.MessageType == WebSocketMessageType.Binary) |
|
|
|
{ |
|
|
|
await messageStream.WriteAsync(buffer, 0, receiveResult.Count); |
|
|
|
|
|
|
|
if (receiveResult.EndOfMessage) |
|
|
|
{ |
|
|
|
var message = new WebSocketMessage |
|
|
|
{ |
|
|
|
ConnectionId = connectionId, |
|
|
|
Data = messageStream.ToArray(), |
|
|
|
MessageType = receiveResult.MessageType, |
|
|
|
IsComplete = true |
|
|
|
}; |
|
|
|
|
|
|
|
_logger.LogDebug("准备处理消息,连接ID:{ConnectionId},消息类型:{MessageType},数据大小:{DataSize}字节", |
|
|
|
connectionId, message.MessageType, message.Data.Length); |
|
|
|
// 使用背压机制
|
|
|
|
if (!await _messageQueueManager.TryQueueIncomingMessage(message)) |
|
|
|
{ |
|
|
|
_logger.LogWarning("消息队列已满,等待处理,连接ID:{ConnectionId}", connectionId); |
|
|
|
await Task.Delay(100); // 等待队列处理
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
await _messageQueueManager.QueueIncomingMessage(message); |
|
|
|
_logger.LogDebug("消息已入队,连接ID:{ConnectionId}", connectionId); |
|
|
|
messageCount++; |
|
|
|
totalBytes += messageStream.Length; |
|
|
|
messageStream.SetLength(0); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (receiveResult.MessageType == WebSocketMessageType.Close) |
|
|
|
{ |
|
|
|
await webSocket.CloseAsync( |
|
|
|
receiveResult.CloseStatus.Value, |
|
|
|
receiveResult.CloseStatusDescription, |
|
|
|
CancellationToken.None); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
stopwatch.Stop(); |
|
|
|
|
|
|
|
// 记录性能指标
|
|
|
|
if (messageCount % 100 == 0) |
|
|
|
{ |
|
|
|
_logger.LogInformation( |
|
|
|
"连接性能统计,连接ID:{ConnectionId},消息数:{MessageCount},总字节数:{TotalBytes}," + |
|
|
|
"平均处理时间:{AverageTime}ms,吞吐量:{Throughput}MB/s", |
|
|
|
connectionId, |
|
|
|
messageCount, |
|
|
|
totalBytes, |
|
|
|
stopwatch.ElapsedMilliseconds / messageCount, |
|
|
|
(totalBytes / 1024.0 / 1024.0) / (stopwatch.ElapsedMilliseconds / 1000.0)); |
|
|
|
} |
|
|
|
|
|
|
|
receiveResult = await webSocket.ReceiveAsync( |
|
|
|
new ArraySegment<byte>(buffer), CancellationToken.None); |
|
|
|
_logger.LogDebug("收到新消息,连接ID:{ConnectionId},消息类型:{MessageType},数据大小:{DataSize}字节", |
|
|
|
connectionId, receiveResult.MessageType, receiveResult.Count); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|