When EPiServer runs in a load-balanced environment, it relies on exchanging remote event messages between participating servers. It could be that a cache item was removed, content changes were published, product prices were updated etc.
At the moment, EPiServer supplies four remote event providers:
- WCF over UDP
- WCF over TCP
- Azure ServiceBus
- Amazon SNS
This post is about implementing a new event provider, using Redis as a broker for remote event messages.
In an earlier post, I demonstrated how to make use of Redis in a web application for caching user data, and I explained the strength and performance of that system. This time I will not store anything, just distribute simple messages.
The four official remote event providers each have their strengths and weaknesses. This section is about briefly listing them up.
WCF over UDP
This is the default provider and the simplest as well. It works by exchanging remote event messages in simple datagrams in a multicast group.
However, UDP does not guarantee delivery of packages, and not all IT departments like multicasting or UDP traffic around their webservers. If that is the case, then we can use the next provider.
WCF over TCP
This is a variant of the first provider. It exchanges remote event messages in TCP packages to known servers. These servers need to be listed as clients in the web.config file on each server.
Because it uses the TCP protocol, it is considered more reliable than the UDP provider. However, each server need to know about the other servers. And to distribute an event message, a server needs to connect to each of the specified servers to deliver it. This is not really efficient and setting up or taking down servers is not that easy, as the list of servers need to be changed on all of the servers.
Cloud platforms does not support custom UDP and TCP flying around between applications and servers. So, this is the provider EPiServer created to support hosting in the Azure cloud.
It works by exchanging messages through a topic in an Azure ServiceBus. Each server, hosting the EPiServer application, subscribes to this topic, and can also publish a message to this topic. When published to the topic, it is sent to all the subscribers.
This way all servers receive the remote event message reliably, and without having any knowledge about other servers.
This provider works exactly like the Azure ServiceBus provider. The main difference is that it utilizes the Amazon SNS (Simple Notification Service), which is the Amazon equivalent of the Azure ServiceBus.
By looking at this short listing, notice that none of the providers offer an on-premise topic broker approach for an on-premise application. Well, an EPiServer documentation page suggests that MSMQ could be applied, but no provider exists for that.
Based on this, I decided to implement an event provider for Redis, since it actually provides such a publish/subscribe feature, very much like that of Azure ServiceBus. The main difference is that Redis is light-weight, open source and easy to set up on-premise. And it can generally be useful in other aspects of an EPiServer solution as well, for instance, as a distributed data or output cache.
These are the characteristics of the event provider I implemented:
- On initialization, the provider sets up a long-running connection to Redis and begins subscribing to a Redis channel (the same as a topic).
- When EPiServer wants to send a remote event message, it gets serialized to a JSON string and then published to the channel.
- Redis receives the message and forwards it to all active subscribers.
- When a message is received, it gets de-serialized and sent along to EPiServer.
- On shutdown, the provider closes the connection and the subscription. In case of a non-graceful shutdown, Redis will detect and remove the inactive subscription.
The source code for this provider is available in my GitHub repository. Also available are a binary file and a package, should you not want to build the code yourself.
For more information about remote event handling and the event API, you might read this documentation page.
Would you consider utilizing Redis (for this or other purposes)?