Introducing Umbraco's KeepAlive Ping configuration
Niels Swimberghe - - Umbraco
Follow me on Twitter, buy me a coffee
With the release of Umbraco 8.6.0, there's now a way to configure the built-in KeepAlive behavior (pull request #7164). The new keepAlive
node can be found inside of umbracoSettings.config
which has two attributes:
- keepAlivePingUrl: Change the URL pinged to keep the Umbraco instance alive. Defaults to
"{umbracoApplicationUrl}/api/keepalive/ping"
. - disableKeepAliveTask: Disable the KeepAlive time interval task by setting it to true. Default to
false
.
Here's what the configuration looks like by out of the box:
<?xml version="1.0" encoding="utf-8" ?> <settings> ... <!-- keepAlive @disableKeepAliveTask Disables the periodic KeepAliveTask when set to "true". Use this setting to disable the KeepAliveTask in case you already have an alternative. For example, Azure App Service has keep alive functionality built-in. Defaults to "false". @keepAlivePingUrl The url of the KeepAlivePing action. By default, the url will use the umbracoApplicationUrl setting as the basis. Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/umbraco/api/keepalive/ping Defaults to "{umbracoApplicationUrl}/api/keepalive/ping". --> <keepAlive disableKeepAliveTask="false" keepAlivePingUrl="{umbracoApplicationUrl}/api/keepalive/ping" /> </settings>
The new configurations help you solve the following two issues:
1. KeepAlive doesn't work due to incorrect URL (404) #
Problem #
This is how the KeepAlive functionality works with the default configuration:
- If the
UmbracoApplicationUrl
isn't explicitly configured, the first requests made to Umbraco will populate the UmbracoApplicationUrl with whichever FQDN URL was used to make that request. - On a timed schedule, the
ApplicationUrl
is used as the base URL to ping theKeepAlive
controller. The URL looks like this:{umbracoApplicationUrl}/api/keepalive/ping
- The
OnlyLocalRequests
attribute verifies if the request to theKeepAliveController.Ping
action came from the local machine.
If the request is not made from the local machine, Umbraco returns HTTP 404 response. - The
KeepAliveController.Ping
action receives the request and returns this XML:
<KeepAlivePingResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Umbraco.Web.Editors"> <Message>I'm alive!</Message> <Success>true</Success> </KeepAlivePingResult>
This is a straightforward process, but there's no guarantee that the URL to ping will resolve to the local machine as required by the OnlyLocalRequests attribute. What if the ApplicationUrl
resolves to a public domain name A but the requests are load balanced among two servers with private domain names B & C?
- UmbracoApplicationUrl will hold
https://domain-A.tld/umbraco
- The KeepAlive timer job will ping
https://domain-A.tld/umbraco/api/keepalive/ping
- domain-A.tld will resolve to the public IP of the load balancer which is where the HTTP request will be send to.
- The
OnlyLocalRequests
attribute will reject the HTTP request and return an HTTP 404 response - The KeepAlive job will log the 404 response
Note 1: even though the log will be filled with 404 errors, the KeepAlive functionality still 'kinda' works. Any HTTP request made to the Umbraco instance or any ASP.NET website on a regular basis will keep it alive.
Note 2: most load balancers already have built-in health checks which will check whether the website is up and running using HTTP Requests. These requests also would keep the websites alive making the KeepAlive functionality redundant.
When using self-hosted IIS web servers, you could easily resolve these issues by adding internal DNS records that would make the public domain resolve to localhost. But many hosting platforms do not provide the same level of control and customization. This is the case for Azure App Services which would run into the exact same issue as described above, except you can't even request localhost 80 or 443 in an app service.
Solution #
With the new keepAlive configuration, you can configure which URL to ping using the keepAlivePingUrl
attribute on the keepAlive
node in the umbracoSettings.config
file.
In case of the load balancing scenario, you should configure the keepAlivePingUrl
with the correct internal domain name that resolves to localhost, or you could simply use localhost if your IIS bindings support that:
<?xml version="1.0" encoding="utf-8" ?> <settings> ... <!-- keepAlive @disableKeepAliveTask Disables the periodic KeepAliveTask when set to "true". Use this setting to disable the KeepAliveTask in case you already have an alternative. For example, Azure App Service has keep alive functionality built-in. Defaults to "false". @keepAlivePingUrl The url of the KeepAlivePing action. By default, the url will use the umbracoApplicationUrl setting as the basis. Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/umbraco/api/keepalive/ping Defaults to "{umbracoApplicationUrl}/api/keepalive/ping". --> <!-- For Web Server A --> <keepAlive disableKeepAliveTask="false" keepAlivePingUrl="https://[INTERNAL_DOMAIN_NAME_A]/api/keepalive/ping" /> </settings>
Unfortunately, specifying localhost for Umbraco instances hosted on Azure App Services will not work. Azure App Services won't allow you to request localhost 80 or 443. Luckily, Azure App Service already has its own alternative KeepAlive functionality.
2. Redundant KeepAlive functionality #
Many platforms already provide their own KeepAlive behavior such as Azure App Services, many load balancers, and reverse proxies. One of the new configuration options allows you to disable Umbraco's KeepAlive functionality. To disable the KeepAlive functionality, change the disableKeepAliveTask
from false
to true
.
<?xml version="1.0" encoding="utf-8" ?> <settings> ... <!-- keepAlive @disableKeepAliveTask Disables the periodic KeepAliveTask when set to "true". Use this setting to disable the KeepAliveTask in case you already have an alternative. For example, Azure App Service has keep alive functionality built-in. Defaults to "false". @keepAlivePingUrl The url of the KeepAlivePing action. By default, the url will use the umbracoApplicationUrl setting as the basis. Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/umbraco/api/keepalive/ping Defaults to "{umbracoApplicationUrl}/api/keepalive/ping". --> <!-- For Web Server A --> <keepAlive disableKeepAliveTask="true" /> </settings>
Now that Umbraco's KeepAlive task is disabled, make sure your alternative is enabled. For Azure App Service, enable "Always On" in the General Settings of your app service.
TL;DR #
Umbraco 8.6 introduces the new keepAlive
configuration inside of umbracoSettings.config
which allows you to change these two attributes:
- keepAlivePingUrl: Change the URL pinged to keep the Umbraco instance alive. Defaults to
"{umbracoApplicationUrl}/api/keepalive/ping"
. - disableKeepAliveTask: Disable the KeepAlive time interval task by setting it to true. Default to
false
.