mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-25 23:53:07 +08:00
improve session manager
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MQTTnet.Adapter;
|
using MQTTnet.Adapter;
|
||||||
@@ -14,7 +15,11 @@ namespace MQTTnet.Server
|
|||||||
public class MqttClientSessionsManager
|
public class MqttClientSessionsManager
|
||||||
{
|
{
|
||||||
private readonly BlockingCollection<MqttEnqueuedApplicationMessage> _messageQueue = new BlockingCollection<MqttEnqueuedApplicationMessage>();
|
private readonly BlockingCollection<MqttEnqueuedApplicationMessage> _messageQueue = new BlockingCollection<MqttEnqueuedApplicationMessage>();
|
||||||
private readonly ConcurrentDictionary<string, MqttClientSession> _sessions = new ConcurrentDictionary<string, MqttClientSession>();
|
|
||||||
|
/// <summary>
|
||||||
|
/// manual locking dictionaries is faster than using concurrent dictionary
|
||||||
|
/// </summary>
|
||||||
|
private readonly Dictionary<string, MqttClientSession> _sessions = new Dictionary<string, MqttClientSession>();
|
||||||
|
|
||||||
private readonly CancellationToken _cancellationToken;
|
private readonly CancellationToken _cancellationToken;
|
||||||
|
|
||||||
@@ -43,12 +48,16 @@ namespace MQTTnet.Server
|
|||||||
|
|
||||||
public Task StopAsync()
|
public Task StopAsync()
|
||||||
{
|
{
|
||||||
foreach (var session in _sessions)
|
lock (_sessions)
|
||||||
{
|
{
|
||||||
session.Value.Stop(MqttClientDisconnectType.NotClean);
|
foreach (var session in _sessions)
|
||||||
}
|
{
|
||||||
|
session.Value.Stop(MqttClientDisconnectType.NotClean);
|
||||||
|
}
|
||||||
|
|
||||||
_sessions.Clear();
|
_sessions.Clear();
|
||||||
|
}
|
||||||
|
_messageQueue.Dispose();
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,10 +69,11 @@ namespace MQTTnet.Server
|
|||||||
public Task<IList<IMqttClientSessionStatus>> GetClientStatusAsync()
|
public Task<IList<IMqttClientSessionStatus>> GetClientStatusAsync()
|
||||||
{
|
{
|
||||||
var result = new List<IMqttClientSessionStatus>();
|
var result = new List<IMqttClientSessionStatus>();
|
||||||
foreach (var session in _sessions)
|
|
||||||
|
foreach (var session in GetSessions())
|
||||||
{
|
{
|
||||||
var status = new MqttClientSessionStatus(this, session.Value);
|
var status = new MqttClientSessionStatus(this, session);
|
||||||
session.Value.FillStatus(status);
|
session.FillStatus(status);
|
||||||
|
|
||||||
result.Add(status);
|
result.Add(status);
|
||||||
}
|
}
|
||||||
@@ -83,12 +93,15 @@ namespace MQTTnet.Server
|
|||||||
if (clientId == null) throw new ArgumentNullException(nameof(clientId));
|
if (clientId == null) throw new ArgumentNullException(nameof(clientId));
|
||||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||||
|
|
||||||
if (!_sessions.TryGetValue(clientId, out var session))
|
lock (_sessions)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Client session '{clientId}' is unknown.");
|
if (!_sessions.TryGetValue(clientId, out var session))
|
||||||
}
|
{
|
||||||
|
throw new InvalidOperationException($"Client session '{clientId}' is unknown.");
|
||||||
|
}
|
||||||
|
|
||||||
return session.SubscribeAsync(topicFilters);
|
return session.SubscribeAsync(topicFilters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task UnsubscribeAsync(string clientId, IList<string> topicFilters)
|
public Task UnsubscribeAsync(string clientId, IList<string> topicFilters)
|
||||||
@@ -96,17 +109,23 @@ namespace MQTTnet.Server
|
|||||||
if (clientId == null) throw new ArgumentNullException(nameof(clientId));
|
if (clientId == null) throw new ArgumentNullException(nameof(clientId));
|
||||||
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
if (topicFilters == null) throw new ArgumentNullException(nameof(topicFilters));
|
||||||
|
|
||||||
if (!_sessions.TryGetValue(clientId, out var session))
|
lock (_sessions)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Client session '{clientId}' is unknown.");
|
if (!_sessions.TryGetValue(clientId, out var session))
|
||||||
}
|
{
|
||||||
|
throw new InvalidOperationException($"Client session '{clientId}' is unknown.");
|
||||||
|
}
|
||||||
|
|
||||||
return session.UnsubscribeAsync(topicFilters);
|
return session.UnsubscribeAsync(topicFilters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteSession(string clientId)
|
public void DeleteSession(string clientId)
|
||||||
{
|
{
|
||||||
_sessions.TryRemove(clientId, out _);
|
lock (_sessions)
|
||||||
|
{
|
||||||
|
_sessions.Remove(clientId);
|
||||||
|
}
|
||||||
_logger.Verbose("Session for client '{0}' deleted.", clientId);
|
_logger.Verbose("Session for client '{0}' deleted.", clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +162,7 @@ namespace MQTTnet.Server
|
|||||||
_retainedMessagesManager.HandleMessageAsync(sender?.ClientId, applicationMessage).GetAwaiter().GetResult();
|
_retainedMessagesManager.HandleMessageAsync(sender?.ClientId, applicationMessage).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var clientSession in _sessions.Values)
|
foreach (var clientSession in GetSessions())
|
||||||
{
|
{
|
||||||
clientSession.EnqueueApplicationMessage(enqueuedApplicationMessage.Sender, applicationMessage);
|
clientSession.EnqueueApplicationMessage(enqueuedApplicationMessage.Sender, applicationMessage);
|
||||||
}
|
}
|
||||||
@@ -158,6 +177,14 @@ namespace MQTTnet.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<MqttClientSession> GetSessions()
|
||||||
|
{
|
||||||
|
lock (_sessions)
|
||||||
|
{
|
||||||
|
return _sessions.Values.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task RunSession(IMqttChannelAdapter clientAdapter, CancellationToken cancellationToken)
|
private async Task RunSession(IMqttChannelAdapter clientAdapter, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var clientId = string.Empty;
|
var clientId = string.Empty;
|
||||||
@@ -263,7 +290,7 @@ namespace MQTTnet.Server
|
|||||||
{
|
{
|
||||||
if (connectPacket.CleanSession)
|
if (connectPacket.CleanSession)
|
||||||
{
|
{
|
||||||
_sessions.TryRemove(connectPacket.ClientId, out _);
|
_sessions.Remove(connectPacket.ClientId);
|
||||||
|
|
||||||
clientSession.Stop(MqttClientDisconnectType.Clean);
|
clientSession.Stop(MqttClientDisconnectType.Clean);
|
||||||
clientSession.Dispose();
|
clientSession.Dispose();
|
||||||
|
|||||||
Reference in New Issue
Block a user