Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ Disallowing concurrent execution of a microflow can be useful if a microflow wou
| Disabled *(default)* | It is possible to execute the microflow more than once concurrently. |
| Enabled | It is not possible to execute the microflow more than once concurrently; the user receives a message or another microflow is executed instead. |

{{% alert color="info" %}}
This property relates to microflows running on a single node in a clustered environment. See [Cluster-Wide Locking](/refguide/clustered-mendix-runtime/#cluster-lock) in *Clustered Mendix Runtime* for more information.
{{% /alert %}}

#### Error Message

**Error message** defines the message the user gets when concurrent execution is not allowed and the user tries to start the microflow while it is already being executed. This will not be shown if there is an **Error microflow** defined.
Expand Down
11 changes: 1 addition & 10 deletions content/en/docs/refguide/runtime/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,7 @@ The user interacts with the Mendix Client, which then makes requests, via the [r

Passing state from the Runtime Server to the Mendix Client enables the Runtime Server to be stateless, which means that any Runtime Server instance can respond to a request from the Mendix Client. A load balancer decides which Runtime Server instance will respond to a request. When a user session ends, the Runtime Server removes references to that session.

If there is more than one instance of an app, one of the instances is the *Cluster Leader*. This is responsible for Performing database synchronization tasks. It also schedules a number of cluster management activities which can then be picked up by any node. These include:

* Session cleanup handling
* Cluster node expiration handling
* Background job expiration handling
* Unblocking blocked users
* Executing scheduled events
* Clearing persistent sessions after a new deploy

More information on multiple instances is in [Clustered Mendix Runtime](/refguide/clustered-mendix-runtime/).
If there is more than one instance of an app, some cluster management activities, such as database synchronization, are coordinated across the instances. For details, see [Clustered Mendix Runtime](/refguide/clustered-mendix-runtime/#cluster-leader-follower).

### External Services

Expand Down
43 changes: 25 additions & 18 deletions content/en/docs/refguide/runtime/clustered-mendix-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,30 @@ This means that a Mendix cluster requires a load balancer to distribute the load

## Cluster Leader and Cluster Followers{#cluster-leader-follower}

Mendix Runtime has the concept of a cluster leader. This is a single node within a Mendix Runtime cluster that performs the initial database synchronization with Domain Model changes and initiates other cluster management activities which can be be picked by any node in a multi-node environment. These are the activities:
Database synchronization is coordinated across cluster nodes depending on how Mendix Runtime is started:

* **Session cleanup handling** – each node expires its sessions (meaning, not being used for a configured timespan) and the cluster leader removes the sessions persisted in the database
* In exceptional cases (for example, a node crash), some sessions may not be removed from the database, in which case the cluster leader makes sure this removal still happens
* **Cluster node expiration handling** – removing cluster nodes after they have expired (meaning, not giving a heartbeat for a configured timespan)
* **Background job expiration handling** – removing data about background jobs after the information has expired (meaning, older than a specific timespan)
* **Unblocking blocked users**
* **Cleanup unreferenced files** - removing from storage any file documents that have been deleted, replaced, or were never committed
* **Executing Scheduled Events** – legacy scheduled events are only executed on the cluster leader; task queue based scheduled events are executed on an arbitrary cluster node
* **Performing database synchronization after new deploy**
* **Clear persistent sessions after new deploy** – invalidating all existing sessions so that they get in sync with the latest model version
* **Leader-based startup** – This is used when the Runtime is started through the administrative API. This is how most managed deployments start the app: for example, the Cloud Foundry buildpack, SAP BTP, or an on-premises installation managed with the Mendix Service Console. With this mechanism, exactly one node is the *cluster leader* and the other nodes are *cluster followers*. The cluster leader initially synchronizes the database with any Domain Model changes and clears persistent sessions after a new deploy; see [Cluster Startup](#cluster-startup) below. The cluster leader node is controlled by the `com.mendix.core.isClusterSlave` custom setting (see [Runtime Customization](/refguide/custom-settings/#commendixcoreisClusterSlave)).

The Cloud Foundry Buildpack determines which cluster node becomes the cluster leader and which become cluster followers.
{{% alert color="info" %}}If you deploy manually using the Mendix Service Console (or another on-premises installation managed through the administrative API), you are responsible for configuring the cluster leader yourself by setting `com.mendix.core.isClusterSlave` to `true` on every node except one.{{% /alert %}}

## Cluster Startup
* **Leaderless startup** – This is used when the Runtime is started directly from a configuration file instead of through the administrative API. [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/) (previously called Portable App Distribution, or PAD) always runs this way: its start script always launches the Runtime with a configuration file. In this model, there is no cluster leader. Database synchronization is coordinated using a database lock: whichever node acquires the lock performs the synchronization while the other nodes wait. The `com.mendix.core.isClusterSlave` setting has no effect when using this mechanism and is ignored. Persistent sessions are not explicitly cleared as a separate deploy step in this model; they are left to expire normally, as described in [Sessions Are Always Persistent](#sessions-are-always-persistent) below.

Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app the whole cluster is restarted and the cluster leader determines whether database synchronization is required. This means that there will be some downtime when the app is deployed while this is done.
## Other Cluster Management Activities

If database synchronization is required, all the cluster followers will wait until the cluster leader finishes the database synchronization. When the database synchronization has finished, all the cluster nodes will become fully functional.
Besides the startup activities described above, Mendix Runtime nodes also perform the following recurring cluster management activities. These run independently of the leader-based or leaderless startup model, and are not tied to a single designated node:

If no database synchronization is required, all the cluster nodes will become fully functional directly after startup.
* **Session cleanup handling** – removing expired sessions from the database is handled by an arbitrary cluster node
* **Cluster node expiration handling** – every node independently removes other cluster nodes that have expired (meaning, not giving a heartbeat for a configured timespan)
Comment thread
MarkvanMents marked this conversation as resolved.
Resolved
* **Background job expiration handling** – removing data about background jobs after the information has expired (meaning, older than a specific timespan) is handled by an arbitrary cluster node
* **Unblocking blocked users** is handled by an arbitrary cluster node
* **Cleanup of unreferenced files** – each node removes its own file documents that were deleted, replaced, or never committed; cleaning up files left behind by a crashed node is handled by an arbitrary cluster node
Comment thread
MarkvanMents marked this conversation as resolved.
Resolved
* **Executing Scheduled Events** – scheduled events are executed by an arbitrary cluster node; for details, see [Task Queue](/refguide/task-queue/)

## Cluster Startup {#cluster-startup}

Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app the whole cluster should be restarted, and the database may need to be synchronized with the updated Domain Model, as described in [Cluster Leader and Cluster Followers](#cluster-leader-follower), above.

Once database synchronization has finished, all the cluster nodes become fully functional. If no database synchronization is required, all the cluster nodes become fully functional directly after startup.

## File Storage {#file-storage}

Expand All @@ -65,12 +68,16 @@ It is possible to configure `After-Startup` and `Before-Shutdown` microflows in

While running a multi-node cluster, you cannot predict the node on which a microflow will be executed. Therefore, it is not possible to debug such a microflow execution in a cluster from Mendix Studio Pro. However, you can still debug a microflow while running a single instance of the Mendix Runtime.

### Cluster-Wide Locking (Guaranteed Single Execution)
### Cluster-Wide Locking (Guaranteed Single Execution){#cluster-lock}

Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single-node Mendix Runtime, this can be guaranteed with a lock which is local to a Java virtual machine (a JVM-local lock). In a cluster, you cannot set a JVM-local lock across the separate JVMs that make up the cluster.

If the activity can be modeled as a microflow or Java action, you can use a [Task Queue](/refguide/task-queue/) with a cluster-wide scope and a single thread to guarantee it runs on only one node at a time (see [Limitations](/refguide/task-queue/#limitations) in *Task Queue*). Keep in mind that this is an at-least-once guarantee rather than a strict exactly-once guarantee: if the node running the task fails, another node picks it up and reruns it, so the activity must be idempotent (safe to run multiple times with the same parameters). For details, see [Behavior If App Stops Unexpectedly](/refguide/task-queue/#behavior-if-app-stops-unexpectedly) in *Task Queue*.

Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single node Mendix Runtime, this could be guaranteed by using JVM locks. However, in a distributed scenario, those JVMs run on different machines, so there is no locking system available. Mendix does not support cluster-wide locking, either. If this cannot be circumvented, you might need to resort to an external distributed lock manager. However, keep in mind that locking in a distributed system is complex and prone to failure (for example, via lock starvation or lock expiration.).
Mendix Runtime does not provide a cluster-wide locking mechanism for other cases, for example holding a lock for an arbitrary duration around work that cannot be modeled as a queued task. In these cases, you need to use an external distributed lock manager. Keep in mind that locking in a distributed system is complex and prone to failure (for example, through lock starvation or lock expiration).

{{% alert color="info" %}}
For the reason described above, the **Disallow concurrent execution** property of a microflow only applies to a single node.
The **Disallow** property in the [Concurrent Execution Section](/refguide/microflow/#concurrent) of a microflow is implemented as a JVM-local lock. It prevents the microflow from being executed more than once at the same time on a single node, but it does not prevent the same microflow from running concurrently on different nodes of a cluster. To guarantee single execution across the cluster, use a cluster-wide Task Queue instead, as described above.
{{% /alert %}}

## Dirty State in a Cluster
Expand Down
2 changes: 1 addition & 1 deletion content/en/docs/refguide/runtime/custom-settings/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
| <a id="ClientCertificateUsages" href="#ClientCertificateUsages">ClientCertificateUsages</a> | Only use this when you have multiple client certificates and you want to configure specific certificates for specific servers.<br/> This setting defines which service must use which client certificate. See **NoClientCertificateUsages** if you want to make sure that no client certificate is used for a certain host or web service. The value of **ClientCertificateUsages** must be a comma-separated list of key/value items. A key/value item must be specified as `"identifier": "path to certificate"`.<br/>For web services, use the imported web service name as the identifier.<br/>For REST services, use the host name of the remote server as the identifier.<br/>Please note that any backslash in the path must be doubled. The whole value must be enclosed by braces (`{ }`). For example: {{< figure src="/attachments/refguide/runtime/custom-settings/code_snippet.png" class="no-border" >}} | |
| <a id="NoClientCertificateUsages" href="#NoClientCertificateUsages">NoClientCertificateUsages</a> | Comma-separated list of host names or imported web service names that should never be contacted using a client certificate. | |
| <a id="ClusterManagerActionInterval" href="#ClusterManagerActionInterval">ClusterManagerActionInterval</a> | The interval (in milliseconds) used for performing all cluster manager actions. These are actions such as unblocking users and removing invalid sessions. See [Session Timing Constraints and Defaults](/refguide/tricky-custom-runtime-settings/#session-timing) in *Advanced Custom Settings* for important details about valid values and their relationship to other session settings. | 300000 (5 minutes) |
| <a id="commendixcoreisClusterSlave" href="#commendixcoreisClusterSlave">com.<wbr>mendix.<wbr>core.<wbr>isClusterSlave</a> | Set to `true` in a high-availability scenario when this is *not* the [Cluster Leader](/refguide/clustered-mendix-runtime/#cluster-leader-follower). The buildpack will usually enforce this setting, but it may need to be set for some on-premises deployments. | `false` |
| <a id="commendixcoreisClusterSlave" href="#commendixcoreisClusterSlave">com.<wbr>mendix.<wbr>core.<wbr>isClusterSlave</a> | Set to `true` on every node except the [Cluster Leader](/refguide/clustered-mendix-runtime/#cluster-leader-follower) in a high-availability scenario. This setting only applies when the Runtime is started through the administrative API (the leader-based startup model); it has no effect when the Runtime is started directly from a configuration file (the leaderless startup model), which is always the case for [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/). See [Cluster Leader and Cluster Followers](/refguide/clustered-mendix-runtime/#cluster-leader-follower) for details on both models.<br/>{{% alert color="info" %}}Managed platforms, such as the Cloud Foundry buildpack, usually set this for you. For a manual, on-premises installation managed through the administrative API (for example, using the Mendix Service Console), you need to set this yourself on all nodes except one.{{% /alert %}} | `false` |

Check failure on line 56 in content/en/docs/refguide/runtime/custom-settings/_index.md

View workflow job for this annotation

GitHub Actions / vale

[vale] reported by reviewdog 🐶 [Mendix.Capitalization] Use ''Mendix'' (capitalized) Raw Output: {"message": "[Mendix.Capitalization] Use ''Mendix'' (capitalized)", "location": {"path": "content/en/docs/refguide/runtime/custom-settings/_index.md", "range": {"start": {"line": 56, "column": 84}}}, "severity": "ERROR"}
| <a id="commendixcoreLenientDateTimeParsing" href="#commendixcoreLenientDateTimeParsing">com.<wbr>mendix.<wbr>core.<wbr>LenientDateTimeParsing</a> | When set to `true`, the `parseDateTime` function will use more lenient parsing, as it did in Mendix 9. For example `parseDateTime("yyyyMMdd", "2021-11-10")` will return `2020-11-01` as a date if this is set to true, which is probably not the intended result.. If set to `false`, which is the default, this example will throw an error as it is expecting `20211110`. It is recommended to not enable this setting to avoid unexpected results. | `false` |
| <a id="commendixcoreSameSiteCookies" href="#commendixcoreSameSiteCookies">com.<wbr>mendix.<wbr>core.<wbr>SameSiteCookies</a> | The [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) property can be included in all cookies that are returned by the embedded HTTP server. The possible values are `Strict`, `Lax`, and `None`. The default is `Strict`. Setting it to `None` is typically needed only when an application is embedded in an iframe of another application with a different domain. Newer browsers may require the connection to be secure (HTTPS) when set to `None`. If the connection is plain HTTP, then this setting must be changed to `Strict` (recommended) or `Lax`. | |
| <a id="commendixcoreScheduledEventsCleanupAge" href="#commendixcoreScheduledEventsCleanupAge">com.<wbr>mendix.<wbr>core.<wbr>ScheduledEventsCleanupAge</a> | This setting specifies (in milliseconds) how old objects in the System.<wbr>ScheduledEventInformation table have to be before they are removed from the database. See [Scheduled Events - Legacy](/refguide9/scheduled-events-legacy/#cleanup) for more details. | 365 days for projects migrated from Mendix 9 and 7 days for new projects or projects with an empty database. |
Expand Down
2 changes: 1 addition & 1 deletion content/en/docs/refguide/runtime/runtime-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ This is the storage location for data files used by the app. More specifically,

Database Synchronization is initiated when an app is started. It manages changes to the database structure which must be applied when you deploy an app after updating the domain model. For example, if a user adds a new attribute to an entity, the database structure must be updated to support this.

If there is more than one instance of the Runtime Server, this activity is carried out by the cluster leader. While this activity takes place, all other instances pause until the database synchronization is complete.
If there is more than one instance of the Runtime Server, this activity is coordinated across the cluster. Depending on how the Runtime is started, either the cluster leader performs the synchronization while the other instances pause until it is complete, or the instances use a database lock to agree on which instance performs it. For details, see [Cluster Leader and Cluster Followers](/refguide/clustered-mendix-runtime/#cluster-leader-follower) in *Clustered Mendix Runtime*.

### External Service Calls

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ Disallowing concurrent execution of a microflow can be useful if a microflow wou
| Disabled *(default)* | It is possible to execute the microflow more than once concurrently. |
| Enabled | It is not possible to execute the microflow more than once concurrently; the user receives a message or another microflow is executed instead. |

{{% alert color="info" %}}
This property relates to microflows running on a single node in a clustered environment. See [Cluster-Wide Locking](/refguide10/clustered-mendix-runtime/#cluster-lock) in *Clustered Mendix Runtime* for more information.
{{% /alert %}}

#### Error Message

**Error message** defines the message the user gets when concurrent execution is not allowed and the user tries to start the microflow while it is already being executed. This will not be shown if there is an **Error microflow** defined.
Expand Down
11 changes: 1 addition & 10 deletions content/en/docs/refguide10/runtime/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,7 @@ The user interacts with the Mendix Client, which then makes requests, via the [r

Passing state from the Runtime Server to the Mendix Client enables the Runtime Server to be stateless, which means that any Runtime Server instance can respond to a request from the Mendix Client. A load balancer decides which Runtime Server instance will respond to a request. When a user session ends, the Runtime Server removes references to that session.

If there is more than one instance of an app, one of the instances is the *Cluster Leader*. This is responsible for Performing database synchronization tasks. It also schedules a number of cluster management activities which can then be picked up by any node. These include:

* Session cleanup handling
* Cluster node expiration handling
* Background job expiration handling
* Unblocking blocked users
* Executing scheduled events
* Clearing persistent sessions after a new deploy

More information on multiple instances is in [Clustered Mendix Runtime](/refguide10/clustered-mendix-runtime/).
If there is more than one instance of an app, some cluster management activities, such as database synchronization, are coordinated across the instances. For details, see [Clustered Mendix Runtime](/refguide10/clustered-mendix-runtime/#cluster-leader-follower).

### External Services

Expand Down
Loading
Loading