<html>
<head>
<base href="https://wiki.asterisk.org/wiki">
<link rel="stylesheet" href="/wiki/s/2042/1/7/_/styles/combined.css?spaceKey=TOP&forWysiwyg=true" type="text/css">
</head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
<h2><a href="https://wiki.asterisk.org/wiki/display/TOP/State+Replication">State Replication</a></h2>
<h4>Page <b>edited</b> by <a href="https://wiki.asterisk.org/wiki/display/~khunt">Ken Hunt</a>
</h4>
<br/>
<h4>Changes (1)</h4>
<div id="page-diffs">
<table class="diff" cellpadding="0" cellspacing="0">
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" >State Replicators provide a mechanism for replicating the state of an Asterisk SCF component to support fail-over scenarios. State Replicators will be developed specifically for each component for which replication is required. The State Replicator is a remote process from the component for which it provides state replication. The State Replicator maintains run-time state data, not configuration data (input) or results necessarily intended to be persistent (output). While the State Replicator concept does not imply persistent storage, there is nothing to preclude a given implementation of a State Replicator from using relational, object or any persistent storage mechanism if a developer chooses to utilize such mechanisms as a way to achieve fault-tolerance for the implementation of the State Replicator itself. <br> <br></td></tr>
<tr><td class="diff-unchanged" >h3. Design Details <br> <br></td></tr>
<tr><td class="diff-snipped" >...<br></td></tr>
<tr><td class="diff-unchanged" > <br>It has been discussed that, for C++, reusable components could be developed to support both State Replicator and Listener-side implementations of these interfaces, templatized on the Slice-defined, component-specific types. <br></td></tr>
<tr><td class="diff-added-lines" style="background-color: #dfd;"> <br>h3. Replication and Component Initialization <br> <br>We refer to a set of same-type components, where one is active and another one or more are in standby mode (to takeover in the event of failover), as a *replica group*. Each component that supports replication is required to implement the *Replica* interface in the AsteriskSCF.System.Component namespace, which provides *activate()* and *standby()* operations to control the component's roles in the replica group. During startup, every component that participates in a replica group will initialize itself to standby mode. <br> <br>The determination of which component is active and which is standby is expected to be made by configuring technologies external to Asterisk SCF. Examples of such technologies would be Pacemaker or Windows Cluster Server. Asterisk SCF provides a python script which has access to the Replica interfaces of the Asterisk SCF components to provide a mechanism for these external technologies to activate specific component instances. This script is used both to activate a component in a replica group during startup as well as to activate a standby component when a failure is detected, or the previously active component needs to be shut down for maintenance. <br> <br>| !ReplicaManagement.png|border=0! | <br>| {center}{*}Figure 4. Active Component Selection{*}{center} | <br> <br>As depicted by a switch in Figure 4, a key concept in the failover process is the notion of a movable IP address. The connection labled "Shared" in the diagram is actually moved from one node to another by the external failover system. To maintain communication with and control of every component in a replica group, we require another dedicated IP address for each node. The Component developer must ensure that the Replica interface is created on an [Object Adapter|http://www.zeroc.com/doc/Ice-3.4.1-IceTouch/manual/Adv_server.33.4.html] that can be configured to be on a the dedicated IP address. In Figure 4, we call this the Management Adapter. <br> <br>To get a reference to the StateReplicator that an active component sends updates to, and a standby component listens to, each component in a replica group should use a property named: <br>{noformat} <br> <AdapterName>.StateReplicatorName <br>{noformat} <br> <br>To allow running a component that was designed to support replication outside of a replica group, the component should set the property: <br>{noformat} <br> <AdapterName>.Standalone=true <br>{noformat} <br> <br>If this property is not set, it defaults to false. <br></td></tr>
</table>
</div> <h4>Full Content</h4>
<div class="notificationGreySide">
<h3><a name="StateReplication-Overview"></a>Overview</h3>
<p>State Replicators provide a mechanism for replicating the state of an Asterisk SCF component to support fail-over scenarios. State Replicators will be developed specifically for each component for which replication is required. The State Replicator is a remote process from the component for which it provides state replication. The State Replicator maintains run-time state data, not configuration data (input) or results necessarily intended to be persistent (output). While the State Replicator concept does not imply persistent storage, there is nothing to preclude a given implementation of a State Replicator from using relational, object or any persistent storage mechanism if a developer chooses to utilize such mechanisms as a way to achieve fault-tolerance for the implementation of the State Replicator itself.</p>
<h3><a name="StateReplication-DesignDetails"></a>Design Details</h3>
<p>The State Replicator process is remote from the component for which it is providing state replication. A simple interface exists to add/set data items in the set, or to remove data items from the set. As with all Asterisk SCF services, the State Replicator concept is manifest in a set of type-safe interfaces.</p>
<p>To support our goal of type-safe interfaces, we eschew the notion of a single base data type which all State Replicator implementations would be bound to. Since Slice (which is used to define the Asterisk SCF interfaces) does not currently support templated types, this implies that we will have an occurrence of a State Replicator "pattern", defined in Slice, for every component-specific State Replicator implementation.</p>
<p>The essence of the State Replicator pattern is the notion that the component pushes its state changes to the State Replicator, who is expected to, in short order, push the state changes to all registered listeners. All standby replicas of the component would be registered as listeners. Standby replicas are thus given constant updates of changes occurring in the active component, to enable expedient transition to an active state.</p>
<p>Figure 1 shows the basic structure of the State Replicator pattern. The <Type>StateReplicator, <Type>StateItem, etc. naming is intended to represent the fact that there are specializations required for a given instantiation of the pattern. Below the pattern representation is a contrived example for a service called ChannelServiceX to help clarify this point.</p>
<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<td class='confluenceTd'> <span class="image-wrap" style=""><img src="/wiki/download/attachments/4816996/DataStorePatternInternalKey.png?version=3&modificationDate=1283978909000" style="border: 1px solid black" /></span> </td>
</tr>
<tr>
<td class='confluenceTd'> <div class="" align="center"><b>Figure 1. The State Replicator</b> <b>Pattern - Internally Keyed</b></div>
</td>
</tr>
</tbody></table>
</div>
<p>In Figure 1, we assume that both the State Replicator and the component consuming the data understand the internal structure of each StateItem, and therefore know which field can server as the identity of the item. A minor variation of the State Replicator pattern is shown in Figure 2, where the key is external to StateItem.</p>
<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<td class='confluenceTd'> <span class="image-wrap" style=""><img src="/wiki/download/attachments/4816996/DataStorePatternExternalKey.png?version=3&modificationDate=1283978917069" style="border: 1px solid black" /></span> </td>
</tr>
<tr>
<td class='confluenceTd'> <div class="" align="center"><b>Figure 2. The State Replicator</b> <b>Pattern - Externally Keyed</b></div>
</td>
</tr>
</tbody></table>
</div>
<p>Several design choices are worthy of discussion:</p>
<ol>
        <li>Only one operation is defined to both add and update a state item. The setStateItems() operation is capable of both, and for multiple state items in a single call. This reduces the number of network calls to a single operation for many internal state changes.</li>
        <li>If you have concerns of transactional safety, you may want to define a specific StateItem subtype that exists to indicate removal of a named element. This would remove the need for calls to removeStateItems() altogether, and any internal transaction could then be updated within the State Replicator with a single operation invocation. This would alleviate the need for any external transaction monitoring.</li>
        <li>There is a set of accessors (i.e. 'get') operations, but the expected usage would be that only late-joiners use this interface to "catch up" to the current state of the active component. The intent is that state changes are pushed to registered listeners as they occur to allow very fast failover. However, there is nothing to prevent implementations from using a pull model.</li>
</ol>
<p>Figure 3. shows a dynamic view of the State Replicator pattern. In this view, the active component does not register as a listener, but is assumed to be configurable to do so if it were brought up or transitioned to a standby mode.</p>
<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<td class='confluenceTd'> <span class="image-wrap" style=""><img src="/wiki/download/attachments/4816996/DataStoreSequenceDiagram.PNG?version=4&modificationDate=1283978924378" style="border: 1px solid black" /></span> </td>
</tr>
<tr>
<td class='confluenceTd'> <div class="" align="center"><b>Figure 3. State Replicator</b> <b>Sequence Diagram</b></div>
</td>
</tr>
</tbody></table>
</div>
<p>It has been discussed that, for C++, reusable components could be developed to support both State Replicator and Listener-side implementations of these interfaces, templatized on the Slice-defined, component-specific types. </p>
<h3><a name="StateReplication-ReplicationandComponentInitialization"></a>Replication and Component Initialization</h3>
<p>We refer to a set of same-type components, where one is active and another one or more are in standby mode (to takeover in the event of failover), as a <b>replica group</b>. Each component that supports replication is required to implement the <b>Replica</b> interface in the AsteriskSCF.System.Component namespace, which provides <b>activate()</b> and <b>standby()</b> operations to control the component's roles in the replica group. During startup, every component that participates in a replica group will initialize itself to standby mode. </p>
<p>The determination of which component is active and which is standby is expected to be made by configuring technologies external to Asterisk SCF. Examples of such technologies would be Pacemaker or Windows Cluster Server. Asterisk SCF provides a python script which has access to the Replica interfaces of the Asterisk SCF components to provide a mechanism for these external technologies to activate specific component instances. This script is used both to activate a component in a replica group during startup as well as to activate a standby component when a failure is detected, or the previously active component needs to be shut down for maintenance. </p>
<div class='table-wrap'>
<table class='confluenceTable'><tbody>
<tr>
<td class='confluenceTd'> <span class="image-wrap" style=""><img src="/wiki/download/attachments/4816996/ReplicaManagement.png?version=1&modificationDate=1305562976101" style="border: 0px solid black" /></span> </td>
</tr>
<tr>
<td class='confluenceTd'> <div class="" align="center"><b>Figure 4. Active Component Selection</b></div>
</td>
</tr>
</tbody></table>
</div>
<p>As depicted by a switch in Figure 4, a key concept in the failover process is the notion of a movable IP address. The connection labled "Shared" in the diagram is actually moved from one node to another by the external failover system. To maintain communication with and control of every component in a replica group, we require another dedicated IP address for each node. The Component developer must ensure that the Replica interface is created on an <a href="http://www.zeroc.com/doc/Ice-3.4.1-IceTouch/manual/Adv_server.33.4.html" class="external-link" rel="nofollow">Object Adapter</a> that can be configured to be on a the dedicated IP address. In Figure 4, we call this the Management Adapter. </p>
<p>To get a reference to the StateReplicator that an active component sends updates to, and a standby component listens to, each component in a replica group should use a property named:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre> <AdapterName>.StateReplicatorName
</pre>
</div></div>
<p>To allow running a component that was designed to support replication outside of a replica group, the component should set the property:</p>
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
<pre> <AdapterName>.Standalone=true
</pre>
</div></div>
<p>If this property is not set, it defaults to false. </p>
</div>
<div id="commentsSection" class="wiki-content pageSection">
<div style="float: right;">
<a href="https://wiki.asterisk.org/wiki/users/viewnotifications.action" class="grey">Change Notification Preferences</a>
</div>
<a href="https://wiki.asterisk.org/wiki/display/TOP/State+Replication">View Online</a>
|
<a href="https://wiki.asterisk.org/wiki/pages/diffpagesbyversion.action?pageId=4816996&revisedVersion=16&originalVersion=15">View Changes</a>
|
<a href="https://wiki.asterisk.org/wiki/display/TOP/State+Replication?showComments=true&showCommentArea=true#addcomment">Add Comment</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>