As discussed at Disable Session affinity cookie (ARR cookie) for Azure web apps - Azure App Service, ARRAffinity cookie is a built-in feature of Azure App Service to facilitate session data management. Today we would like to study a typical case to help those concerned to avoid potential business impact.
Symptom
-
At most of the time, the web app works fine, then suddenly, the issue comes up.
-
When the issue was happening: The user was kept directing to the login page, it seems the user was kept logging out by someone else.
The web app has below settings:
- The ARRAffinity was enabled on the Azure portal.
- There were 2 customer domains binding to it
- There was a direct rule in the web.config: The requests to the domain comtos.com would be direct to www.comtos.com
- The site was running on multiple worker instances and has the auto scale rules to change the worker instances.
Troubleshooting
After the investigation, we found out that the issue caused by the ARRAffinity. And it can reproduced by the below steps:
-
Access the web app through the root domain (Here we are testing with domain boqianwebsite.org and www.boqianwebsite.org ), we can see the value of domain attribute for the ARRAffinity cookie is root domain boqianwebsite.org .
-
If the worker instance is removed from the service plan, and the ARRAffinity of this removed instance would become invalid. To simulate this operation, we update the above ARRAffinity to an invalid value.
- Access the web app through the subdomain http://www.boqianwebsite.org , we will see that the invalid ARRAffinity cookie was still the request header. However, in the response header, a new ARRAffinity is set with www.boqianwebsite.org as the domain value.
- If we keep refreshing the page www.boqianwebsite.org , the request headers will always contain two ARRAffinity cookies:
- A fixed invalid ARRAffinity for root domain (boqianwebsite.org )
- A ARRAffinity for the subdomain (www.boqianwebsite.org ) is keep changing from the response header when refreshing the page
Cause
This issue are caused by 2 facts:
- If the ARRAffinity cookies have a different domain value, the browser will take it as a different cookies. That's why when we are accessing the subdomain after the root domain, a new ARRAfifnity Cookies was set in the response header.
- The App Service always pick up the first ARRAffinity value from the request header. If the first ARRAffiniity value is invalid due to the instance has been removed from the service plan (by scale in or UD walk), the FrontEnd will try to find a new valid worker instance with a new ARRAffinity value to the client. But this new ARRAffinity value will always be saved into the second subdomain's cookies, which cannot be picked up by the App Service FrontEnd.
Solution
To solve this problem, we have 2 options:
- Ignore the domain name and keep only one ARRAffinity Cookies at the client side
- Update the App Service FrontEnd to pick up the ARRAffinity, which has the same domain name as the request has.
Considering the implementation of those two options and the customer's environment (they has direction rule, which hoping the user can access the site from the subdomain instead of root domain), we chose the option 1: We keep the subdomain's ARRAffinity cookies only, then the app service FrontEnd can always pick up the correct one. And this can be easy achieve by adding the below path of code into the web.config: Set ARRAffinity Cookies after direction.
<httpProtocol>-->
<redirectHeaders> -->
<!-- disable the ARRAffinity cookie, returned only when redirection occurs. -->
<add name="Arr-Disable-Session-Affinity" value="true" />
</redirectHeaders>
</httpProtocol>
After this change, when we access the web app with the root domain http://boqianwebsite.org , we can see that there is a new header added in the response Arr-Disable-Session-Affinity: true , but there is no ARRAffinity cookies was set.
The ARRAffinity was set only when the request directed to the subdomain www.boqianwebsite.org , and if we refresh the page, this cookies keeps the same.
Hope above case study helps!
Reference: