|
1 | 1 | ---
|
2 | 2 | title: Use Consul as a membership provider
|
3 | 3 | description: Learn how to use Consul as a membership provider in .NET Orleans.
|
4 |
| -ms.date: 03/09/2022 |
| 4 | +ms.date: 05/12/2023 |
5 | 5 | ---
|
6 | 6 |
|
7 | 7 | # Use Consul as a membership provider
|
8 | 8 |
|
9 |
| -[Consul](https://www.consul.io) is a distributed, highly available, and datacenter-aware service discovery platform that includes simple service registration, health checking, failure detection, and key/value storage. It is built on the premise that every node in the data center is running a Consul agent which is either acting as a server or client which communicates via a scalable gossip protocol. |
| 9 | +[Consul](https://www.consul.io) is a distributed, highly available, and data center-aware service discovery platform that includes simple service registration, health checking, failure detection, and key-value storage. It's built on the premise that every node in the data center is running a Consul agent that is either acting as a server or client. Each agent communicates via a scalable gossip protocol. |
10 | 10 |
|
11 |
| -There is a very detailed overview of Consul including comparisons with similar solutions [here](https://www.consul.io/intro/index.html). |
| 11 | +There's a detailed overview of Consul including comparisons with similar solutions [here](https://www.consul.io/intro/index.html). |
12 | 12 |
|
13 |
| -Consul is written in Go and is [open source](https://github.com/hashicorp/consul); compiled downloads are available for [Mac OS X, FreeBSD, Linux, Solaris and Windows](https://www.consul.io/downloads.html) |
| 13 | +Consul is written in [Go](https://go.dev) and is [open source](https://github.com/hashicorp/consul); compiled downloads are available for [macOS X, FreeBSD, Linux, Solaris and Windows](https://www.consul.io/downloads.html) |
14 | 14 |
|
15 | 15 | ## Why choose Consul?
|
16 | 16 |
|
17 |
| -As an [Orleans Membership Provider](../implementation/cluster-management.md), Consul is a good choice when you need to deliver an on-premise solution that does not require your potential customers to have existing infrastructure and a cooperative IT provider. Consul is a very lightweight single executable, has no dependencies, and as such can easily be built into your middleware solution. And when Consul is already your solution for discovering, checking, and maintaining your microservices, it makes sense to fully integrate with Orleans membership for simplicity and ease of operation. We, therefore, implemented a membership table in Consul (also known as "Orleans Custom System Store"), which fully integrates with Orleans's [Cluster Management](../implementation/cluster-management.md). |
| 17 | +As an [Orleans Membership Provider](../implementation/cluster-management.md), Consul is a good choice when you need to deliver an on-premises solution that doesn't require your potential customers to have existing infrastructure and a cooperative IT provider. Consul is a lightweight single executable, has no dependencies, and as such can easily be built into your middleware solution. When Consul is your solution for discovering, checking, and maintaining your microservices, it makes sense to fully integrate with Orleans membership for simplicity and ease of operation. There also exists a membership table in Consul (also known as "Orleans Custom System Store"), which fully integrates with Orleans's [Cluster Management](../implementation/cluster-management.md). |
18 | 18 |
|
19 | 19 | ## Set up Consul
|
20 | 20 |
|
21 | 21 | There's extensive documentation available on [Consul.io](https://www.consul.io) about setting up a stable Consul cluster, and it doesn't make sense to repeat that here. However, for your convenience, we include this guide so you can quickly get Orleans running with a standalone Consul agent.
|
22 | 22 |
|
23 |
| -1. Create a folder to install Consul into, (for example _C:\Consul_). |
24 |
| -1. Create a subfolder: _C:\Consul\Data_ (Consul will not create this if it doesn't exist). |
| 23 | +1. Create a folder to install Consul into (for example _C:\Consul_). |
| 24 | +1. Create a subfolder: _C:\Consul\Data_ (Consul doesn't create this directory if it doesn't exist). |
25 | 25 | 1. [Download](https://www.consul.io/downloads.html) and unzip _Consul.exe_ into _C:\Consul_.
|
26 | 26 | 1. Open a command prompt at _C:\Consul_ and run the following command:
|
27 | 27 |
|
28 | 28 | ```powershell
|
29 |
| - Consul.exe agent -server -bootstrap -data-dir "C:\Consul\Data" -client=0.0.0.0 |
| 29 | + ./consul.exe agent -server -bootstrap -data-dir "C:\Consul\Data" -client='0.0.0.0' |
30 | 30 | ```
|
31 | 31 |
|
32 | 32 | In the preceding command:
|
33 | 33 |
|
34 |
| - - `agent` Instructs Consul to run the agent process that hosts the services. Without this, the Consul process will attempt to use RPC to configure a running agent. |
35 |
| - - `-server` Defines the agent as a server and not a client (A Consul _client_ is an agent that hosts all the services and data, but does not have voting rights to decide, and cannot become, the cluster leader. |
36 |
| - - `-bootstrap` The first (and only the first!) node in a cluster must be bootstrapped so that it assumes the cluster leadership. |
37 |
| - - `-data-dir [path]` Specifies the path where all Consul data is stored, including the cluster membership table. |
38 |
| - - `-client=0.0.0.0` Informs Consul which IP to open the service on. |
| 34 | + - `agent`: Instructs Consul to run the agent process that hosts the services. Without this switch, the Consul process attempts to use RPC to configure a running agent. |
| 35 | + - `-server`: Defines the agent as a server and not a client (A Consul _client_ is an agent that hosts all the services and data, but doesn't have voting rights to decide, and can't become, the cluster leader. |
| 36 | + - `-bootstrap`: The first (and only the first!) node in a cluster must be bootstrapped so that it assumes the cluster leadership. |
| 37 | + - `-data-dir [path]`: Specifies the path where all Consul data is stored, including the cluster membership table. |
| 38 | + - `-client='0.0.0.0'`: Informs Consul which IP to open the service on. |
39 | 39 |
|
40 |
| - There are many other parameters, and the option to use a JSON configuration file. Please consult the Consul documentation for a full listing of the options. |
| 40 | + There are many other parameters, and the option to use a JSON configuration file. Consult the Consul documentation for a full listing of the options. |
41 | 41 |
|
42 |
| -1. Verify that Consul is running and ready to accept membership requests from Orleans by opening the services endpoint in your browser at `http://localhost:8500/v1/catalog/services`. |
| 42 | +1. Verify that Consul is running and ready to accept membership requests from Orleans by opening the services endpoint in your browser at <http://localhost:8500/v1/catalog/services>, when functioning correctly the browser should display the following JSON: |
43 | 43 |
|
44 |
| -## Configure Orleans |
45 |
| -
|
46 |
| -There is a known issue with the "Custom" membership provider _OrleansConfiguration.xml_ configuration file that will fail to parse correctly. For this reason, you have to provide a placeholder SystemStore in the XML and then configure the provider in code before starting the silo. |
47 |
| -
|
48 |
| -**OrleansConfiguration.xml** |
49 |
| -
|
50 |
| -```xml |
51 |
| -<OrleansConfiguration xmlns="urn:orleans"> |
52 |
| - <Globals> |
53 |
| - <SystemStore SystemStoreType="None" |
54 |
| - DataConnectionString="http://localhost:8500" |
55 |
| - DeploymentId="MyOrleansDeployment" /> |
56 |
| - </Globals> |
57 |
| - <Defaults> |
58 |
| - <Networking Address="localhost" Port="22222" /> |
59 |
| - <ProxyingGateway Address="localhost" Port="30000" /> |
60 |
| - </Defaults> |
61 |
| -</OrleansConfiguration> |
62 |
| -``` |
63 |
| - |
64 |
| -**Code** |
65 |
| - |
66 |
| -```csharp |
67 |
| -public void Start(ClusterConfiguration config) |
68 |
| -{ |
69 |
| - _siloHost = new SiloHost(System.Net.Dns.GetHostName(), config); |
| 44 | + ```json |
| 45 | + { |
| 46 | + "consul": [] |
| 47 | + } |
| 48 | + ``` |
70 | 49 |
|
71 |
| - _siloHost.Config.Globals.LivenessType = |
72 |
| - GlobalConfiguration.LivenessProviderType.Custom; |
73 |
| - _siloHost.Config.Globals.MembershipTableAssembly = |
74 |
| - "OrleansConsulUtils"; |
75 |
| - _siloHost.Config.Globals.ReminderServiceType = |
76 |
| - GlobalConfiguration.ReminderServiceProviderType.Disabled; |
| 50 | +## Configure Orleans |
77 | 51 |
|
78 |
| - _siloHost.InitializeOrleansSilo(); |
| 52 | +To configure Orleans to use Consul as a membership provider, your silo project will need to reference the [Microsoft.Orleans.Clustering.Consul](https://www.nuget.org/packages/Microsoft.Orleans.Clustering.Consul) NuGet package. Once you've done that, you can configure the membership provider in your silo's _Program.cs_ file as follows: |
79 | 53 |
|
80 |
| - var started = _siloHost.StartOrleansSilo(); |
81 |
| - if (started is false) |
82 |
| - { |
83 |
| - throw new SystemException( |
84 |
| - $"Failed to start Orleans silo '{_siloHost.Name}' as a {_siloHost.Type} node"); |
85 |
| - } |
86 |
| -} |
87 |
| -``` |
| 54 | +:::code source="snippets/consul/Silo/Program.cs"::: |
88 | 55 |
|
89 |
| -Alternatively, you could configure the silo entirely in code. The client configuration is much simpler: |
| 56 | +The preceding code: |
90 | 57 |
|
91 |
| -**ClientConfiguration.xml** |
| 58 | +- Creates a <xref:Microsoft.Extensions.Hosting.IHostBuilder> with defaults from the <xref:Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder?displayProperty=nameWithType>. |
| 59 | +- Chains a call to <xref:Microsoft.Extensions.Hosting.GenericHostExtensions.UseOrleans(Microsoft.Extensions.Hosting.IHostBuilder,System.Action{Microsoft.Extensions.Hosting.HostBuilderContext,Orleans.Hosting.ISiloBuilder})> which configures the Orleans silo. |
| 60 | +- Given the <xref:Orleans.Hosting.ISiloBuilder> calls <xref:Orleans.Hosting.ConsulUtilsHostingExtensions.UseConsulSiloClustering%2A>. |
| 61 | +- Configures the cluster membership provider to use Consul, given the Consul `address`. |
92 | 62 |
|
93 |
| -```xml |
94 |
| -<ClientConfiguration xmlns="urn:orleans"> |
95 |
| - <SystemStore SystemStoreType="Custom" |
96 |
| - CustomGatewayProviderAssemblyName="OrleansConsulUtils" |
97 |
| - DataConnectionString="http://192.168.1.26:8500" |
98 |
| - DeploymentId="MyOrleansDeployment" /> |
99 |
| -</ClientConfiguration> |
100 |
| -``` |
| 63 | +To configure the client, reference the same NuGet package and call the <xref:Orleans.Hosting.ConsulUtilsHostingExtensions.UseConsulClientClustering%2A> extension method. |
101 | 64 |
|
102 | 65 | ## Client SDK
|
103 | 66 |
|
104 |
| -If you are interested in using Consul for your service discovery, there are [Client SDKs](https://www.consul.io/downloads_tools.html) for most popular languages. |
| 67 | +If you're interested in using Consul for your service discovery, there are [Client SDKs](https://www.consul.io/downloads_tools.html) for most popular languages. |
105 | 68 |
|
106 |
| -## Implementation detail |
| 69 | +### Implementation detail |
107 | 70 |
|
108 |
| -The Membership Table Provider makes use of [Consul's Key/Value store](https://www.consul.io/intro/getting-started/kv.html) functionality with Check-And-Set (CAS) operations. When each Silo starts, it registers two KV entries, one that contains the Silo details and one that holds the last time the Silo reported it was alive (the latter refers to diagnostics "I am alive" entries and not to failure detection heartbeats, which are sent directly between the silos and are not written into the table). All writes to the table are performed with CAS to provide concurrency control, as necessitated by Orleans's [Cluster Management Protocol](../implementation/cluster-management.md). |
| 71 | +The Membership Table Provider makes use of [Consul's Key/Value store](https://www.consul.io/intro/getting-started/kv.html) functionality with Check-And-Set (CAS) operations. When each Silo starts, it registers two key-value entries, one that contains the Silo details and one that holds the last time the Silo reported it was alive. The latter refers to diagnostics "I'm alive" entries and not to failure detection heartbeats, which are sent directly between the silos and aren't written into the table. All writes to the table are performed with CAS to provide concurrency control, as necessitated by Orleans's [Cluster Management Protocol](../implementation/cluster-management.md). |
109 | 72 |
|
110 |
| -Once the Silo is running, you can view these entries in your web browser at `http://localhost:8500/v1/kv/?keys`, which will display something like: |
| 73 | +Once the Silo is running, you can view these entries in your web browser at <http://localhost:8500/v1/kv/?keys&pretty>, which displays something like: |
111 | 74 |
|
112 | 75 | ```json
|
113 | 76 | [
|
114 |
| - "orleans/MyOrleansDeployment/192.168.1.26:11111@191780753", |
115 |
| - "orleans/MyOrleansDeployment/192.168.1.26:11111@191780753/iamalive" |
| 77 | + "orleans/default/192.168.1.11:11111@43165319", |
| 78 | + "orleans/default/192.168.1.11:11111@43165319/iamalive", |
| 79 | + "orleans/default/version" |
116 | 80 | ]
|
117 | 81 | ```
|
118 | 82 |
|
119 |
| -You'll notice that the keys are prefixed with `orleans`. This is hardcoded in the provider and is intended to avoid keyspace collision with other users of Consul. Each of these keys can be read by appending their key name (without quotes) to the Consul KV root at `http://localhost:8500/v1/kv/`. Doing so presents you with the following: |
| 83 | +All of the keys are prefixed with `orleans`, which is hard coded in the provider and is intended to avoid keyspace collision with other users of Consul. You can use any of these keys to retrieve additional information about Each of these keys can be read by appending their key name (without quotes) to the Consul KV root at `http://localhost:8500/v1/kv/`. Doing so presents you with the following JSON: |
120 | 84 |
|
121 | 85 | ```json
|
122 | 86 | [
|
123 | 87 | {
|
124 | 88 | "LockIndex": 0,
|
125 |
| - "Key": "orleans/MyOrleansDeployment/192.168.1.26:22222@191780753", |
| 89 | + "Key": "orleans/default/192.168.1.11:11111@43165319", |
126 | 90 | "Flags": 0,
|
127 | 91 | "Value": "[BASE64 UTF8 Encoded String]",
|
128 |
| - "CreateIndex": 10, |
129 |
| - "ModifyIndex": 12 |
| 92 | + "CreateIndex": 321, |
| 93 | + "ModifyIndex": 322 |
130 | 94 | }
|
131 | 95 | ]
|
132 | 96 | ```
|
133 | 97 |
|
134 |
| -Decoding the string gives you the actual Orleans Membership data: |
| 98 | +Decoding the Base64 UTF-8 encoded string `Value` gives you the actual Orleans membership data: |
135 | 99 |
|
136 |
| -**`http://localhost:8500/v1/KV/orleans/MyOrleansDeployment/[SiloAddress]`** |
| 100 | +**`http://localhost:8500/v1/KV/orleans/default/[SiloAddress]`** |
137 | 101 |
|
138 | 102 | ```json
|
139 | 103 | {
|
140 | 104 | "Hostname": "[YOUR_MACHINE_NAME]",
|
141 |
| - "ProxyPort": 22222, |
142 |
| - "StartTime": "2016-01-29T16:25:54.9538838Z", |
| 105 | + "ProxyPort": 30000, |
| 106 | + "StartTime": "2023-05-15T14:22:00.004977Z", |
143 | 107 | "Status": 3,
|
| 108 | + "SiloName": "Silo_fcad0", |
144 | 109 | "SuspectingSilos": []
|
145 | 110 | }
|
146 | 111 | ```
|
147 | 112 |
|
148 |
| -**`http://localhost:8500/v1/KV/orleans/MyOrleansDeployment/[SiloAddress]/IAmAlive`** |
| 113 | +**`http://localhost:8500/v1/KV/orleans/default/[SiloAddress]/IAmAlive`** |
149 | 114 |
|
150 | 115 | ```plaintext
|
151 |
| -2016-01-29T16:35:58.9193803Z |
| 116 | +"2023-05-15T14:27:01.1832828Z" |
152 | 117 | ```
|
153 | 118 |
|
154 |
| -When the Clients connect, they read the KVs for all silos in the cluster in one HTTP GET by using the URI `http://192.168.1.26:8500/v1/KV/orleans/MyOrleansDeployment/?recurse`. |
| 119 | +When the clients connect, they read the KVs for all silos in the cluster in one HTTP GET by using the URI `http://192.168.1.26:8500/v1/KV/orleans/default/?recurse`. |
155 | 120 |
|
156 | 121 | ## Limitations
|
157 | 122 |
|
| 123 | +There are a few limitations to be aware of when using Consul as a membership provider. |
| 124 | + |
158 | 125 | ### Orleans extended membership protocol (table version & ETag)
|
159 | 126 |
|
160 |
| -Consul KV currently does not support atomic updates. |
161 |
| -Therefore, the Orleans Consul Membership Provider only implements the Orleans basic membership protocol, as described in [Cluster management in Orleans](../implementation/cluster-management.md), and does not support the Extended Membership Protocol. This Extended protocol was introduced as an additional, but not essential, silo connectivity validation and as a foundation to functionality that has not yet been implemented. |
162 |
| -Providing your infrastructure is correctly configured you will not experience any detrimental effect of the lack of support. |
| 127 | +Consul KV currently doesn't support atomic updates. Therefore, the Orleans Consul Membership Provider only implements the Orleans basic membership protocol, as described in [Cluster management in Orleans](../implementation/cluster-management.md), and doesn't support the Extended Membership Protocol. This Extended protocol was introduced as an extra, but not essential, silo connectivity validation and as a foundation to functionality that hasn't yet been implemented. |
163 | 128 |
|
164 | 129 | ### Multiple datacenters
|
165 | 130 |
|
166 |
| -The key-value pairs in Consul are not currently replicated between Consul datacenters. There is a [separate project](https://github.com/hashicorp/consul-replicate) to address this but it has not yet been proven to support Orleans. |
| 131 | +The key-value pairs in Consul aren't currently replicated between Consul data centers. There's a [separate project](https://github.com/hashicorp/consul-replicate) to address this replication effort, but it hasn't yet been proven to support Orleans. |
167 | 132 |
|
168 | 133 | ### When running on Windows
|
169 | 134 |
|
170 |
| -When Consul starts on Windows it logs the following message: |
| 135 | +When Consul starts on Windows, it logs the following message: |
171 | 136 |
|
172 | 137 | ```Output
|
173 | 138 | ==> WARNING: Windows is not recommended as a Consul server. Do not use in production.
|
174 | 139 | ```
|
175 | 140 |
|
176 |
| -This is displayed simply due to a lack of focus on testing when running in a Windows environment and not because of any actual known issues. |
177 |
| -Read the [discussion](https://groups.google.com/forum/#!topic/consul-tool/DvXYgZtUZyU) before deciding if Consul is the right choice for you. |
| 141 | +This warning message is displayed due to a lack of focus on testing when running in a Windows environment and not because of any actual known issues. Read the [discussion](https://groups.google.com/forum/#!topic/consul-tool/DvXYgZtUZyU) before deciding if Consul is the right choice for you. |
178 | 142 |
|
179 | 143 | ## Potential future enhancements
|
180 | 144 |
|
181 |
| -1. Prove that the Consul KV replication project can support an Orleans cluster in a WAN environment between multiple Consul datacenters. |
| 145 | +1. Prove that the Consul KV replication project can support an Orleans cluster in a WAN environment between multiple Consul data centers. |
182 | 146 | 1. Implement the Reminder Table in Consul.
|
183 | 147 | 1. Implement the Extended Membership Protocol.
|
184 |
| -The team behind Consul does plan on implementing atomic operations, once this functionality is available it will be possible to remove the limitations in the provider. |
| 148 | +The team behind Consul does plan on implementing atomic operations, once this functionality is available it's possible to remove the limitations in the provider. |
0 commit comments