One of charts from the benchmarking section below.
Stl.Rpc is a new communication library for .NET. It was originally built to replace HTTP+WebSocket-based communication stack in Fusion and Actual Chat. There were two main reasons to do that:
request → response [→ maybe invalidation]
. And even though it looks quite similar to the standard request -> response
sequence, none of existing protocols is “extendable” enough to accommodate its 3rd message. Earlier Fusion was using WebSocket-based side channel to transmit it, but even this was more complicated than it seems (too many moving parts), not speaking about some weird issues this “dual channel” option implies.1. Reference Stl.Rpc packages:
<PackageReference Include="Stl.Rpc.Server" Version="6.8.9" />
— on the server side<PackageReference Include="Stl.Rpc" Version="6.8.9" />
— on the client side<PackageReference Include="Stl.Generators" Version="6.8.9" />
— on both sides2. Declare your service interface and tag it with IRpcService
. It must be available both on your server and on your client (so typically you must declare such interfaces in “Contracts” library).
public interface IGreeter : **IRpcService**
{
Task<Message> SayHello(string name, CancellationToken cancellationToken = default);
}
IRpcService
tag makes Stl.Generators
package to generate a proxy type for IGreeter
.
3. Make sure any type you reference from your service interface is MemoryPack-serializable:
**[DataContract, MemoryPackable(GenerateType.VersionTolerant)]**
public **partial** record Message(
**[property: DataMember(Order = 0), MemoryPackOrder(0)]** string Text
);
In this case we also make it DataContract-serializable, and thus MessagePack-serializable. Stl.Rpc supports MessagePack too, which means you can switch to it as well.
4. Configure server:
var builder = WebApplication.CreateBuilder();
var rpc = builder.Services**.AddRpc(); // Registers RpcHub and other components
rpc.AddWebSocketServer(); // Adds server-side WebSocket support for Stl.Rpc
rpc.AddServer<IGreeter, Greeter>(); // Exposes Greeter as IGreeter (singleton)**
var app = builder.Build();
**app.UseWebSockets(); // Enables WebSockets on Kestrel
app.MapRpcWebSocketServer(); // Maps /rpc/ws endpoint to Stl.Rpc server**
await app.RunAsync(**"<http://localhost:22222/>"**);
5. Configure client:
var services = new ServiceCollection();
var rpc = services**.AddRpc(); // Registers RpcHub and other components
rpc.AddWebSocketClient("<http://localhost:22222/>"); // Adds client-side WebSocket support
rpc.AddClient<IGreeter>(); // Exposes IGreeter client (singleton)**
var serviceProvider = services.BuildServiceProvider();
6. Use it: