Session Store & Service
Trên trang này
Namespaces: Nalix.Abstractions.Networking.Sessions, Nalix.Runtime.Sessions
Assembly: Nalix.Runtime
SessionService, InMemorySessionStore, SessionFactory, DefaultSessionPersistencePolicy và SessionPersistenceObserver quản lý các ảnh chụp phiên có thể tiếp tục (SessionEntry / SessionScope) khi client ngắt kết nối và sau đó kết nối lại qua giao thức SessionResume 0-RTT (SessionResumeStage.REQUEST).
Nguồn mã
src/Nalix.Abstractions/Networking/Sessions/ISessionService.cssrc/Nalix.Abstractions/Networking/Sessions/ISessionStore.cssrc/Nalix.Abstractions/Networking/Sessions/ISessionFactory.cssrc/Nalix.Abstractions/Networking/Sessions/ISessionPersistencePolicy.cssrc/Nalix.Abstractions/Networking/Sessions/SessionEntry.cssrc/Nalix.Abstractions/Networking/Sessions/SessionScope.cssrc/Nalix.Runtime/Sessions/SessionService.cssrc/Nalix.Runtime/Sessions/InMemorySessionStore.cssrc/Nalix.Runtime/Sessions/SessionFactory.cssrc/Nalix.Runtime/Sessions/DefaultSessionPersistencePolicy.cssrc/Nalix.Runtime/Sessions/SessionPersistenceObserver.cssrc/Nalix.Runtime/Options/SessionStoreOptions.cs
Vòng đời lưu và tiếp tục phiên
sequenceDiagram
participant C as Client
participant H as ConnectionHub
participant OBS as SessionPersistenceObserver
participant SSV as SessionService
participant ST as ISessionStore (InMemorySessionStore)
Note over C,H: 1. Client Disconnects
H->>H: UnregisterConnection(connection)
H-->>OBS: Raise ConnectionUnregistered(connection)
OBS->>OBS: Create SnapshotConnection (clones Attributes, Secret, Sequence Numbers)
OBS->>SSV: SaveSessionAsync(snapshot)
SSV->>SSV: ISessionPersistencePolicy.ShouldPersist(snapshot)
SSV->>ST: StoreAsync(SessionEntry)
Note over C,H: 2. Client Reconnects (0-RTT Resume)
C->>H: SessionResume (SessionToken, Nonce, Proof)
H->>SSV: ConsumeAsync(sessionToken, predicate)
SSV->>ST: ConsumeAsync(sessionToken, predicate)
ST-->>SSV: Atomic Remove -> Return SessionScope(entry)Hợp đồng công khai và triển khai
1. ISessionService và SessionService
namespace Nalix.Runtime.Sessions;
public sealed class SessionService : ISessionService, IDisposable, IReportable
{
public SessionService(
ISessionFactory? factory = null,
ISessionStore? store = null,
ISessionPersistencePolicy? policy = null);
public ValueTask SaveSessionAsync(
IConnection connection,
CancellationToken cancellationToken = default);
public ValueTask<SessionScope> ConsumeAsync(
ulong sessionToken,
Func<SessionEntry, bool>? predicate = null,
CancellationToken cancellationToken = default);
public string GenerateReport();
public void WriteReportData(Utf8JsonWriter writer);
public void Dispose();
}
- Lập lịch bộ quét dọn: Khi
_storetriển khaiIWorker(nhưInMemorySessionStore),SessionServicetự động lập lịch nó trênTaskManager.ScheduleWorker(hostedWorker)và disposeIWorkerHandlekhi gọiSessionService.Dispose(). - An toàn với pool: Nếu
_store.StoreAsync(entry, ct)ném một ngoại lệ không nghiêm trọng,SessionServicegọi ngayentry.Return()đểSessionEntrylấy từ pool vàObjectMap<AttributeKey, object>đã thuê của nó không bị rò rỉ.
2. InMemorySessionStore (ISessionStore, IWorker, IReportable)
namespace Nalix.Runtime.Sessions;
public sealed class InMemorySessionStore : ISessionStore, IWorker, IReportable
{
public const int DefaultMaxSessions = 65_536;
public int MaxSessions { get; set; }
public ValueTask StoreAsync(
SessionEntry entry,
CancellationToken cancellationToken = default);
public ValueTask<SessionScope> ConsumeAsync(
ulong sessionToken,
Func<SessionEntry, bool>? predicate = null,
CancellationToken cancellationToken = default);
public ValueTask ExecuteAsync(IWorkerContext context, CancellationToken cancellationToken);
}
- Tiêu thụ một lần, nguyên tử (
SEC-33):ConsumeAsynckiểm traentry.Snapshot.ExpiresAtUnixMilliseconds > Clock.UnixMillisecondsNow(), đánh giápredicate(entry)tùy chọn TRƯỚC khi xóa entry (nếupredicatetrả vềfalsethì không xóa), và dùng thao tác xóa khóa-giá trị nguyên tử (ICollection<KeyValuePair<ulong, SessionEntry>>.Remove) để chỉ một lời gọi đồng thời có thể tiêu thụ một token hợp lệ. Trả vềSessionScope(scope.IsValid == truekhi đã tiêu thụ; disposeSessionScopesẽ trảSessionEntryvề pool). - Chỉ mục hết hạn theo nhóm phút (
_expiryBuckets): Gom các session token vào các bucket 60 giây (ExpiresAtUnixMilliseconds / 60_000) để tác vụ nềnExecuteAsyncchỉ duyệt các bucket đã đến hạn. - Loại bỏ khi đầy (
DefaultMaxSessions = 65,536): Khi_store.Count >= MaxSessions, xóa các entry đã hết hạn trước, sau đó đến các entry cũ nhất, và gọientry.Return().
3. DefaultSessionPersistencePolicy và SessionPersistenceObserver
SessionPersistenceObserverđăng ký vàoIConnectionHub.ConnectionUnregistered, chụp mộtSnapshotConnection(sao chépAttributes,Secret,Level,Algorithmvà bộ đếm sequence TCP/UDP trước khiConnection.Dispose()xóa chúng về 0), rồi gọiSaveSessionAsynctrong nền.DefaultSessionPersistencePolicy.ShouldPersist(IConnection)đánh giá ba quy tắc theo thứ tự:- Policy 1 (Cổng handshake): Nếu
!connection.GetRuntimeState().HandshakeEstablished, trả vềfalse. - Policy 2 (Phiên mật mã đang hoạt động): Nếu
!connection.Secret.IsZero(đã thiết lập khóa mã hóa 32 byte đang hoạt động), trả vềtruengay. - Policy 3 (Dự phòng theo số lượng attribute): Nếu không, trả về
connection.Attributes.Count > _options.MinAttributesForPersistence(mặc định10).
- Policy 1 (Cổng handshake): Nếu