One of our clients has an enterprise solution with several websites in the same EPiServer database and wanted to be able to publish some content just once and then the content would be reflected on each website. But sometimes they wanted to create local content as well in the same page structure which was created by the global content. Sometimes parts of the content shouldn’t be reflected on all sites, just selected ones.
The two latter requirements made the solution much more complex.
If it wasn’t for the requirement to create local content too, the obvious solution would be a custom Page Provider. So we started to investigate if mirroring suited our needs.
We created a site called Global Content which holds all the global content and then three test websites. Then we installed the mirroring service as a stand-alone application. We configured the mirroring service.
We created a couple of mirroring channels and ran the scheduled job. It all worked just fine. Then we tested to create local pages where the mirroring service already created some pages, created some more global pages and then ran the job again. Everything worked just fine.
To meet the requirement that not all sites should receive all, let’s say news articles, the editor could categorize the articles and then the news archive page just listed the selected categories.
In production, the number of websites increased to about 10 and now we had about 30 mirroring channels. Things started to go bad. The mirroring service froze and the CPU utilized 100%! After a while we received a timeout.
“The request channel timed out while waiting for a reply after 00:01:00. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout.”
The error message suggested to beef up the timeout, so we did. But no luck there. We started to fiddle with all the other settings.
We noted there were a lot of requests to the service, and long lived ones. We read some articles about number of concurrent requests and changed the MaxConcurrentRequestsPerCPU to 5000.
The developer support suggested some other changes, like closeTimeout, openTimeout, receiveTimeout, sendTimeout and maxConnections on the binding configuration.
One thing to note is that there wasn’t much content which was mirrored, it seemed to be the number of channels that was causing the error. But we decreased the numberOfPagesInPackage setting.
Nothing seemed to work.
We also received “Error while unloading appdomain. (Exception from HRESULT: 0x80131015)” and “Exception: The ConnectionString property has not been initialized.”.
Now we started to disable some channels so we were down to about 20 channels. Now the job started to work again, sometimes it even ran fast.
OK, so mirroring doesn’t seem to work so well if you’re mirroring to the same server with a lot of channels. Now we looked in to do our custom scheduled job and execute each channel with some timespan between them, but after some digging with reflector that seemed like a huge task.
So this wasn’t the solution after all. But it will work in some cases, and will probably be one part of our final solution where the target content should be exactly as the source but the editor should be able to create local pages.
I remembered an old article from Anders Hattestad in which he used the DDS and created a Page Provider for local pages. Stay tuned for part 2 in this mini series, where we create a more sophisticated Page Provider with some more settings.