ServerEvents Redis backplane with sentinel support

Hi guys,
I’m using ServerEvents with Redis backplane, and this is my apphost

namespace Mares.Api.Server.Common
{
    public class MaresAppHost : AppSelfHostBase
    {
        public MaresAppHost(Assembly[] assembliesWithServices)
            : base("Mares API", assembliesWithServices)
        {
            MaresEnvironment.Instance.RegisterLicense();
        }

        public string HostUrl => $"http://*:{ApplicationVariables.Instance.APIPort}/";

        public override void Configure(Container container)
        {
            ServiceEnvironment.Container = container;

            Plugins.Add(new ServerEventsFeature());

            Routes.AddFromAssembly(base.ServiceAssemblies.ToArray());

            var redisHost = ApplicationVariables.Instance.RedisHost;
            if (!string.IsNullOrEmpty(redisHost))
            {
                container.Register<IRedisClientsManager>(
                    new RedisManagerPool(redisHost));

                container.Register<IServerEvents>(c =>
                    new RedisServerEvents(c.Resolve<IRedisClientsManager>()));

                container.Resolve<IServerEvents>().Start();
            }


            SetConfig(new HostConfig
            {
                DebugMode = true,
                EnableFeatures = Feature.All,
            });

            //Prevents Json serialized to add __type part on json string for anonymous types serialization
            //Read this: -http://stackoverflow.com/questions/18842685/servicestack-sessions-doesnt-work-when-using-jsconfig-excludetypeinfo
            JsConfig.ExcludeTypeInfo = true;
            JsConfig.DateHandler = DateHandler.ISO8601;
        }
    }
}

the Redis instance is a Windows Service installed as described here

With this configuration there is no failover when the redis instance goes down. My goal is to have a kind of redis “cluster”, maybe using Sentinel, so my apphosts will connect to this cluster instead of the single redis instance.

Can I do it? if yes, can you please give me some links?
Best regards
Enrico

Please wrap any C# source code with:

```csharp
//source code here
```

The high availability solution in Redis is to use Redis Sentinel.

See the ServiceStack.Redis docs for how to use and enable Redis Sentinel.

Note there is still only 1 Redis Master, but with a Redis Sentinel Solution the sentinel will monitor if the master goes down and promote one of the slaves to be master. For more info you can read about what happens when a Redis Slave and Redis Master is failing.

Also note the recommended way for setting global ServiceStack.Text configuration is to use JsConfig.Init():

JsConfig.Init(new Config {
    DateHandler = DateHandler.ISO8601,
    ExcludeTypeInfo = true,                
});

Hi mythz,

thanks for your reply. I’m trying to set up a sentinel as suggested in the links you gave me. Once understood how iit works, on the AppHost how should I use it?

Can I use something like this?

var redisHost = ApplicationVariables.Instance.RedisHost;
            if (!string.IsNullOrEmpty(redisHost))
            {
                var hosts = redisHost.Split(';');

                //container.Register<IRedisClientsManager>(
                //    new RedisManagerPool(hosts));

                container.Register<IRedisClientsManager>(
                    new RedisSentinel(hosts, "mymaster").Start());

                container.Register<IServerEvents>(c =>
                    new RedisServerEvents(c.Resolve<IRedisClientsManager>()));

                container.Resolve<IServerEvents>().Start();
            }

where redisHost string is

<add key="RedisHost" value="192.168.34.76:50002;127.0.0.1:50002"/>

the address list contain all the sentinel instances with the right port.

Is it right?
Best regards
Enrico

Right, the RedisSentinel constructor expects a single or collection of sentinel hosts, the ports of of sentinels are usually 26379 though.

Perfect, this means that I don’t need to specify the full list of sentinels in the RedisHost app.config key, I should only need my “local” sentinel. Right? I’ll change the default port to 50002 because of some firewall restrictions we use

Thanks
Enrico

Right, if you just provide a single Sentinel Host, RedisSentinel will use it to find the other active sentinel hosts within the same mymaster group.

Hi,
it seems to be working as expected, and this is really cool!

I will test it for a longer period than I will put in production.
Thanks
Enrico

1 Like