1

I have a C# web application that uses a component (Progress Telerik Sitefinity CMS) that takes a long time (2 minutes) to initialize. A user who visits the site while in this stage, will be redirected to a page that polls the state every second, until initialization is complete. (This is built-in Sitefinity behavior).

I'm hosting my application within an Azure App Service. If I increase the number of instances (scale up), some of my users end up on the new node while it's still initializing. Problem is, due to the affinity cookie Azure adds, they stay on this node.

I want affinity, except when the site is initializing. In that case, I want to drop the cookie and poll. In that case I get assigned a random node, so an initialzed node is found within seconds.

Question is: how do I achieve this? Much of what happens is handled within Sitefinity, so I resorted to altering content in my global.asax. It doesn't work. I tried to put this in my global.asax.cs:

protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
    var path = HttpContext.Current.Request.Url.AbsolutePath;
    // "/sitefinity/status" is the page the client is redirected to
    // "/appstatus" is used to poll initialization status
    if (path == "/appstatus" || path == "/sitefinity/status")
    {
        // "ARRAffinity" is the Azure affinity cookie
        Response.Cookies.Remove("ARRAffinity");
        // just removing the cookie didn't work so i tried to override it
        Response.Cookies.Add(new HttpCookie("ARRAffinity", "-") { HttpOnly = true });
        // reportedly, this suppresses cookie adding by Azure
        Response.Headers.Add("ARR-Disable-Session-Affinity", "true");
    };
}

How do I force my client to a different node?

EDIT I think I found (part of) the problem here.

  • First, "/" is requested. This returns a 302 redirect, but also the ARRAffinity cookie.
  • Then, "/sitefinity/status" is requested. Both the ARR-Disable-Session-Affinity and the cookie are stripped. This means, the cookie is not cleared on the client.
  • While polling, the client already has the cookie. So the user is never redirected to another node.

So that's might be the problem. Now to solve it...

EDIT

I followed Vesselin Vassilevs suggestion and added this to my sites configuration file:

<appSettings>
    <add key="sf:AppStatusPageResponseCode" value="503" />
</appSettings>

But because I still incidentally reach the initializing node, I also suppressed the affinity cookie , by altering my global.asax.cs:

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        var httpCode = Response.StatusCode;
        var isRedirectBackFromStatusPage = httpCode == 302 && Request.Url.AbsolutePath == "/sitefinity/status";
        var isFinalSitefinityStatusPoll = httpCode == 404 && Request.Url.AbsolutePath == "/appstatus";
        if (isRedirectBackFromStatusPage || isFinalSitefinityStatusPoll)
        {
            var cookie = Request.Cookies["ARRAffinity"];
            if (cookie != null) Response.Cookies.Add(cookie);
            return;
        }
        if (httpCode != 200 || !Response.ContentType.StartsWith("text/html"))
        {
            Response.Headers.Add("ARR-Disable-Session-Affinity", "true");
        };
    }
realbart
  • 3,497
  • 1
  • 25
  • 37

1 Answers1

1

Why not disable the arr affinity cookie altogether? Sitefinity backend works fine with no arr cookie and with multiple instances.

EDIT: We need to tell Azure that the site is not yet ready during the Sitefinity initialization. The problem with that is, that the appStatus page (shown by Sitefinity during init) returns status code 302 and even 200, which makes Azure to believe the site is running ok. I've wrote about this here: https://sitefinitydevelopment.com/blog/sitefinity's-application-status-page-can-cause-you-big-problems.html Depending on your Sitefinity version, you can either implement the custom solution there (manually returning http code 503 during system restart) or set the following setting in the web.config (Sitefinity 9+)

<add key="sf:AppStatusPageResponseCode" value="503" />
Veselin Vasilev
  • 3,698
  • 1
  • 15
  • 21
  • If I disable session affinity altogether, when scaling, half of every request will be routed to the node that's still initializing. This will impact every user on my site, because javascript and images won't load. – realbart Apr 07 '18 at 09:01
  • 2
    Maybe try setting the status code of the Sitefinity status page from 200 to 503 - this will tell the Azure Load Balancer that the web role is not yet ready to receive requests. To do that you need to add this in the appSettings of the web.config: Source: https://docs.sitefinity.com/change-the-application-status-page-response-code – Veselin Vasilev Apr 07 '18 at 11:56
  • Thanks, Veselin. That was the first thing I tried. But for some reason Azure still doesn't see Sitefinity isn't ready. I suspect that is because a random page doesn't return 503, but a 302 redirect TO the 503 status page. If there's a way to tell Azure Sitefinity isn't ready, that would be the best solution. – realbart Apr 07 '18 at 19:25
  • 1
    I wrote about this some time ago here: https://sitefinitydevelopment.com/blog/sitefinity's-application-status-page-can-cause-you-big-problems.html maybe worth the try – Veselin Vasilev Apr 08 '18 at 00:32
  • 1
    if you make an answer out of your suggestion, I will mark it as correct. – realbart Apr 10 '18 at 07:34