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.