Dispatch Contracts
Trên trang này
Namespace: Nalix.Runtime.Dispatching
Assembly: Nalix.Runtime
Trang này đề cập các contract dispatch công khai trong Nalix.Runtime.Dispatching: IPacketDispatch, IDispatchChannel<TPacket> và IDispatchSession.
Ánh xạ mã nguồn
src/Nalix.Runtime/Dispatching/IPacketDispatch.cssrc/Nalix.Runtime/Dispatching/IDispatchChannel.cssrc/Nalix.Runtime/Internal/Routing/DispatchChannel.cs
1. IPacketDispatch
namespace Nalix.Runtime.Dispatching;
public interface IPacketDispatch : IActivatable, IReportable
{
void HandlePacket(IBufferLease lease, IConnection connection);
}
IPacketDispatch là interface điểm vào giữa các listener mạng (Nalix.Network) và tầng thực thi lúc chạy (Nalix.Runtime):
void HandlePacket(IBufferLease lease, IConnection connection): Nhận một khungleaseđã giải mã/giải nén từconnection. Triển khai (PacketDispatchChannel) gọilease.Retain()trước khi đưa vào hàng đợi, nên bên gọi transport có thể dispose tham chiếu lease của chính nó ngay khi hàm trả về.IActivatable: Cung cấpActivate(CancellationToken)vàDeactivate(CancellationToken)để bắt đầu và dừng các vòng lặp worker dispatch chạy nền.IReportable: Cung cấpGenerateReport()vàWriteReportData(Utf8JsonWriter)cho telemetry lúc chạy.
2. IDispatchChannel<TPacket> và IDispatchSession
namespace Nalix.Runtime.Dispatching;
public interface IDispatchSession : IDisposable
{
IConnection Connection { get; }
bool TryDequeue([NotNullWhen(true)] out IBufferLease raw);
}
public interface IDispatchChannel<TPacket> where TPacket : IPacket
{
long TotalPackets { get; }
void Push(IConnection connection, IBufferLease raw);
bool TryClaim([NotNullWhen(true)] out IDispatchSession session);
}
Vì sao cần IDispatchSession (mô hình actor-mailbox)
Nếu cho phép nhiều luồng worker cùng lấy gói tin từ một kết nối, thứ tự gói tin của client đó có thể bị đảo lộn. Vì vậy IDispatchChannel<TPacket> dùng mô hình claim actor-mailbox:
- Một worker gọi
TryClaim(out IDispatchSession session)để giành quyền xử lý độc quyền đối với mailbox của một kết nối đã sẵn sàng. - Khi đang giữ
session, không worker nào khác có thể claim kết nối đó. Worker rút tối đa_maxDrainPerWakegói tin theo thứ tự ưu tiên (URGENT$\rightarrow$NONE) quasession.TryDequeue(out IBufferLease raw). - Dispose
session(session.Dispose()) sẽ giải phóng claim và tự động đưa lại kết nối vào vòng sẵn sàng nếu vẫn còn gói tin đang chờ.