Custom ScaleOut
To take full control over scaling you can create a custom ScaleOut
. You have already seen how to ScaleOut
using the default scaling over sockets as well as using the Azure Service Bus
.
Full control over when to scale
By default XSockets calls the ScaleOut
module when a new message arrives at the server. So basically the server scales out all incoming messages. This is fine when you want to just scale messages that all clients should get. But what if you call a service layer that do CRUD operations from the controller? This would mean that all servers would try to do the CRUD operation since they all got the message. This is not what we want!
To prevent this we can take full control over what to scale. It is pretty easy once you understand the concept.
Adding a module for custom ScaleOut
You can find the template for custom ScaleOut
under the XSockets.NET 5 templates.
This template will provide something like this.
using System;
using System.Threading.Tasks;
using XSockets.Core.Common.Enterprise;
using XSockets.Core.Common.Protocol;
using XSockets.Core.Common.Socket.Event.Interface;
using XSockets.Enterprise.Scaling;
[Export(typeof(IXSocketsScaleOut), Rewritable = Rewritable.No, InstancePolicy = InstancePolicy.Shared)]
public class CustomScaleOut : BaseScaleOut
{
/// <summary>
/// Called at startup, setup/prepare your scaleout
/// </summary>
public override void Init()
{
throw new NotImplementedException();
}
/// <summary>
/// Publish the message to the scaleout so that other servers can receive it
/// </summary>
/// <param name="message"></param>
public override Task Publish(MessageDirection direction, IMessage message, ScaleOutOrigin scaleOutOrigin)
{
throw new NotImplementedException();
}
/// <summary>
/// Subscribe for messages published from other servers by using AzureServiceBus or similar techniques
///
/// You can ofcourse do polling to a data source, but performance will be suffering from that.
/// </summary>
public override Task Subscribe()
{
throw new NotImplementedException();
}
}
The class above provides 3 methods
Init
In there you can setup what ever custom stuff your ScaleOut
need
Subscribe
In subscribe you setup the mechanism for getting data from your ScaleOut
source. Take a look at the Azure Service Bus
example.
Publish
The publish method is where you can decide what to do with a message. You can make the decision based on the origin of the message.
When XSockets scales automatically the origin
will be set to Auto
. So to ignore the auto-scaling you can just say.
if(origin == ScaleOutOrigin.Auto) return;
You can of course combine the decision based on the topic of the message as well. Maybe some topics are on a black-list and should not be scaled. This is up to you.
Calling the ScaleOut
If you want to have full control over what to scale (and when) you can call the ScaleOut
module by getting the instance from the PluginFramework
and use it.
//Call the service layer to save sensordata
this.SensorService.Save(telemetryData);
//The save was a succes, so scale that to all servers
var message = new Message(telemetryData, "sensorUpdate", this.Alias);
await Composable.GetExport<IXSocketsScaleOut>().Publish(MessageDirection.Out, message, ScaleOutOrigin.Custom);
In the code above we call the ScaleOut
after successfully saving telemetry data. This means that the other servers will get a notification about the new data. The other servers can then tell the clients connected about this.
Taking full control of the ScaleOut
can of course be done is the Azure Service Bus
sample as well. Just ignore the messages with origin
set to Auto
and call the ScaleOut
like above.