EPiServer CMS: How to configure Remote Events with many servers and Firewalls between them

The Event Management System in EPiServer CMS 5 is used to propagate information that a page has changed to other web servers connected to the same database.

This is very important to setup if you have more than one web server or an enterprise site with several start pages because if it does not invalidate cache, the other web sites can potentially return old versions of a page!

Pitfall – Default configuration is using Multicast UDP!

If you read Configuring EPiServer CMS 5 R2 SP2 Enterprise you will learn that all you have to do is to set enableRemoteEvents="true" in web.config.

It is only mentioned briefly that it is using UDP and you may have to change your firewall settings. Too be more specific the default configuration is using multicast UDP broadcast! Tell this to your network guys and watch their reaction…

If you look around you will also find a tech note about the Event Management System Specification and a FAQ about setting up a server to use TCP protocol but not all clues needed are found there – you have to dig with the reflector to find out the rest.

Scenario: 4 start pages, 8 Front-end servers IN DMZ and 2 in LAN

You can change how the Event Management System communicates by changing WCF settings in web.config. It is possible to use TCP instead of UDP and also specify ports to use.

First, the current release (5 R2 SP2) does not support WCF Port Sharing so we need one port opened in the firewall for each start page (that is when you have several siteSettings-tags in web.config).

In our case we need to get four ports (for example port 13000-13003) opened in the firewall for TCP traffic between servers in DMZ and LAN.

Use the sample configuration below as a template to get it to work. In production I suggest using configSource-attribute in web.config to keep the WCF-settings in separate files.

Web.Config

<system.serviceModel>
  <services configSource="system.serviceModel.services.config" />
  <client configSource="system.serviceModel.client.config" />
  <behaviors>
    <serviceBehaviors>
      <behavior name="DebugServiceBehaviour">
        <!--TODO: the option should be only in test environment true in the production should be false-->
        <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <netTcpBinding>
      <binding name="RemoteEventsBinding">
        <security mode="None" />
      </binding>
    </netTcpBinding>
  </bindings>
</system.serviceModel>

system.serviceModel.services.config

Use this to configure WCF Services (listens to incoming messages). Setup one service for each EPiServer site-tag.

  • Name should be unique.
  • Name must be the value of episerver/sites[siteid] plus "/EPiServer.Events.Remote.EventReplication", i.e. if siteId is “sss.se” then name should be “sss.se/EPiServer.Events.Remote.EventReplication”.
  • Each site must use a diffrent port in services/service/endpoint[address].
  • Use "localhost" in the address attribute to bind to all NIC on the machine.
<services>
  <service name="sss.se/EPiServer.Events.Remote.EventReplication" behaviorConfiguration="DebugServiceBehaviour">
    <endpoint name="RemoteEventServiceEndPoint" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://localhost:13000/RemoteEventService" binding="netTcpBinding" />
  </service>
  <service name="sss.no/EPiServer.Events.Remote.EventReplication" behaviorConfiguration="DebugServiceBehaviour">
    <endpoint name="RemoteEventServiceEndPoint" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://localhost:13001/RemoteEventService" binding="netTcpBinding" />
  </service>
  <service name="sss.dk/EPiServer.Events.Remote.EventReplication" behaviorConfiguration="DebugServiceBehaviour">
    <endpoint name="RemoteEventServiceEndPoint" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://localhost:13002/RemoteEventService" binding="netTcpBinding" />
  </service>
  <service name="sss.com/EPiServer.Events.Remote.EventReplication" behaviorConfiguration="DebugServiceBehaviour">
    <endpoint name="RemoteEventServiceEndPoint" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://localhost:13003/RemoteEventService" binding="netTcpBinding" />
  </service>
</services>

system.serviceModel.client.config

And each server that changes the content must also be aware of where to send notifications so we must list all servers and websites.

  • Name should be unique.
  • It is better if address contains IP-addresses than hostnames.
  • There should be one endpoint for each website on a server where port number matches the ports used in the services/service/endpoint[address].
<client>
  <!-- SERVER1 -->
  <endpoint name="sss.se-SERVER1" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://SERVER1:13000/RemoteEventService" binding="netTcpBinding" />
  <endpoint name="sss.no-SERVER1" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://SERVER1:13001/RemoteEventService" binding="netTcpBinding" />
  <endpoint name="sss.dk-SERVER1" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://SERVER1:13002/RemoteEventService" binding="netTcpBinding" />
  <endpoint name="sss.com-SERVER1" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://SERVER1:13003/RemoteEventService" binding="netTcpBinding" />
  <!-- SERVER2 -->
  <endpoint name="sss.se-SERVER2" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://SERVER2:13000/RemoteEventService" binding="netTcpBinding" />
  <endpoint name="sss.no-SERVER2" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://SERVER2:13001/RemoteEventService" binding="netTcpBinding" />
  <endpoint name="sss.dk-SERVER2" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://SERVER2:13002/RemoteEventService" binding="netTcpBinding" />
  <endpoint name="sss.com-SERVER2" contract="EPiServer.Events.ServiceModel.IEventReplication" bindingConfiguration="RemoteEventsBinding" address="net.tcp://SERVER2:13003/RemoteEventService" binding="netTcpBinding" />
  <!-- Repeat pattern above for all other servers and sites -->
</client>

Good luck! And let me know if this helps you or if you get stuck…

Credits to Petter Klang at EPiServer Support and Shahram Shahinzadeh on the backend dev team that has been helping us out.