Server BlueprintΒΆ
Learning Signals
- Level: Intermediate
- Time: 15β20 minutes
- Prerequisites: Quickstart
This page provides the recommended architectural blueprint for a production-grade Nalix server. It moves beyond the single-file quickstart to a shape that scales as features, security policies, and diagnostic needs grow.
ποΈ Startup ArchitectureΒΆ
A robust server follows a deterministic sequence:
flowchart LR
subgraph Setup ["Phase 1: Setup"]
direction TB
Config["Load Configuration"]
Reg["Register Services"]
end
subgraph Pipeline ["Phase 2: Runtime Pipeline"]
direction TB
Disp["Activate Dispatch"]
Trans["Start Transport"]
end
subgraph Ext ["Phase 3: Extensions"]
direction TB
Boot["Hosted Services"]
end
Config --> Reg
Reg --> Disp
Disp --> Trans
Trans --> Boot
Why this blueprint?
Treating the server startup as a sequence of discrete layers ensures that when the socket starts accepting traffic, every security policy and reporting hook is already "warm" and ready.
π Recommended Directory StructureΒΆ
Consistency is key for maintainability. We recommend the following layout for a Nalix server project:
π Server/
βββ π Bootstrap/ # Service & Dispatch wiring
βββ π Protocols/ # Transport protocol definitions
βββ π Handlers/ # Application logic (Controllers)
βββ π Middleware/ # Security & Policy filters
βββ π Metadata/ # Custom convention providers
βββ π Hosting/ # Entry point & Lifecycle management
π The Blueprint StepsΒΆ
1. Configuration & ValidationΒΆ
Load and validate focused network options before starting the runtime. Fail-fast is better than a runtime error in a worker loop.
var socket = ConfigurationManager.Instance.Get<NetworkSocketOptions>();
socket.Validate();
var dispatchOptions = ConfigurationManager.Instance.Get<DispatchOptions>();
dispatchOptions.Validate();
var connectionLimits = ConfigurationManager.Instance.Get<ConnectionLimitOptions>();
connectionLimits.Validate();
If you use the hosting builder, src/Nalix.Hosting/NetworkApplicationBuilder.cs already does this step for every Configure<TOptions>(...) registration by invoking public Validate() when the option type exposes it.
2. Registry InitializationΒΆ
The InstanceManager serves as the runtime core for shared infrastructure when you wire the stack manually. The hosting builder performs the same registration work for you.
using Microsoft.Extensions.Logging;
using Nalix.Logging;
ILogger logger = NLogix.Host.Instance;
InstanceManager.Instance.Register<ILogger>(logger);
InstanceManager.Instance.Register<IPacketRegistry>(packetRegistry);
3. Dispatch & Middleware SetupΒΆ
Define your application pipeline in a centralized location.
PacketDispatchChannel dispatch = new(options =>
{
options.WithLogging(logger)
.WithErrorHandling((ex, opcode) => logger.Error($"dispatch 0x{opcode:X4}", ex))
.WithMiddleware(new AuthMiddleware())
.WithMiddleware(new AuditMiddleware())
.WithHandler(() => new AccountHandlers())
.WithHandler(() => new MatchHandlers());
});
Centralized Wiring
Keep all WithMiddleware and WithHandler calls in a single bootstrap class. Spreading these across the codebase makes startup order nearly impossible to debug.
4. Protocol ImplementationΒΆ
Keep your protocol thin. It should strictly act as the bridge between raw frames and clean messages.
public sealed class ServerProtocol : Protocol
{
private readonly PacketDispatchChannel _dispatch;
public ServerProtocol(PacketDispatchChannel dispatch)
{
_dispatch = dispatch;
this.IsAccepting = true;
}
public override void ProcessMessage(object? sender, IConnectEventArgs args)
=> _dispatch.HandlePacket(args.Lease, args.Connection);
}
That shape matches src/Nalix.Hosting/DefaultProtocol.cs, which is the built-in implementation used when you do not need custom protocol hooks.
β‘ Lifecycle ManagementΒΆ
Managing the Activation and Shutdown order is critical for preventing connection "dangling."
| phase | Action | Detail |
|---|---|---|
| Startup | dispatch.Activate() |
Warm up the dispatch pipeline before listeners begin accepting traffic. |
| Startup | listener.Activate() |
Open the socket and begin accepting. |
| Shutdown | listener.Deactivate() + Dispose() |
Stop accepting and release transport resources first. |
| Shutdown | protocol.Dispose() |
Dispose protocols after listeners stop. |
| Shutdown | dispatch.Deactivate() |
Stop the dispatch pipeline after listeners and hosted services. |
This order comes directly from src/Nalix.Hosting/NetworkApplication.cs, where ActivateAsync() prepares callbacks, activates dispatch, starts listeners, then activates hosted services; DeactivateAsync() reverses that order and finally waits for ITaskManager.WaitGroupAsync("net/*") and "time/*".
π Diagnostics SurfaceΒΆ
A production-ready blueprint always includes a way to query the internal health.
listener.GenerateReport()- Listener-side transport state and counters.protocol.GenerateReport()- Protocol-side counters and post-process diagnostics.dispatch.GenerateReport()- Dispatch runtime state.
Pro-Tip
Even if you don't have an Admin API, ensure your logs occasionally output these reports during periods of high traffic.
Recommended Next PagesΒΆ
- Production Checklist { .md-button }
- Custom Middleware { .md-button }
- TCP Request/Response { .md-button }