Closed LCastilloSymbiotic closed 2 years ago
In 3.x, there is no example for IMemberDiscoveryService
because its actual implementation fully depends on the external discovery mechanism. It can be Consul, etcd, Kubernetes or even file watcher. However, you must use IMemberDiscoveryService
carefully: one node can be removed or added at a time. This restriction is not implemented by the interface or underlying Raft implementation. Otherwise, there is a non-zero probability to have more than one leader in the cluster for a short period of time.
In 4.x, this situation is solved completely. No more IMemberDiscoveryService
or configurable list of cluster members. Raft defines its own membership protocol that is implemented in the upcoming major version. For now, 4.x is available as a preview package on NuGet.
Ok ok, a question in version 4.x are there examples of how to use this new union members model?
Best regards,
Luis
In case of 4.x, the programming model follows recommendations from Raft paper:
AddMemberAsync
or RemoveMemberAsync
Also I recommend to read this article about node bootstrapping.
Hi In 3.x, Is it possible to add a node manually?
I am trying something like this:
private readonly IRaftCluster _cluster;
IPEndPoint checkIP = new IPEndPoint(IPAddress.Loopback), 3262);
_cluster.Members.Aggregate(checkIP);
But I get an error for the type as it requests an IClusterMember
Yes, the configuration is tracked by RaftCluster
at runtime via IOptionsMonitor. So you can change the configuration at run-time. If you're using the file for storing configuration, then just open and edit it (add new member to members
section).
Don't you have an example of how to do that?
This is my normal host creation:
private static Task UseAspNetCoreHost(int port, string? persistentStorage = null)
{
var configuration = new Dictionary<string, string>
{
{"partitioning", "false"},
{"lowerElectionTimeout", "150" },
{"upperElectionTimeout", "300" },
{"requestJournal:memoryLimit", "5" },
{"requestJournal:expiration", "00:01:00" }
};
//Set local URI
LocalURI = String.Format("{0}{1}", "https://", NodesMembers[0].ToString());
//Set nodes members
for (int i = 0; i < NodesMembers.Count; i++)
{
configuration.Add(String.Format("members:{0}", i),
String.Format("{0}{1}", "https://", NodesMembers[i].ToString()));
}
if (!string.IsNullOrEmpty(persistentStorage))
configuration[CustomPersistentState.LogLocation] = persistentStorage;
return new HostBuilder().ConfigureWebHost(webHost =>
{
webHost.UseKestrel(options =>
{
options.ListenLocalhost(port, listener => listener.UseHttps(LoadCertificate()));
})
.UseStartup<StartupReplication>();
})
.ConfigureLogging(builder => builder.AddConsole().SetMinimumLevel(LogLevel.Error))
.ConfigureAppConfiguration(builder => builder.AddInMemoryCollection(configuration))
.JoinCluster()
.Build()
.RunAsync();
}
Raft impl for ASP.NET Core fully relies on Configuration Model and Options pattern from the framework:
As far as I know, in-memory configuration doesn't support change tracking. Therefore, you need to write your own configuration provider with in-memory storage capabilities or change another source of configuration, e.g. json file. You can find a lot of examples in the articles mentioned above.
Writing configs in eg .json doesn't make it static? I think about it in this sense, I imagine that the data from the configuration file is loaded when the cluster is created, but once it is up, it does not check the file again or does it?
It does.
When I insert the configuration from a dictionary like this:
var configuration = new Dictionary<string, string>
{
{"partitioning", "false"},
{"lowerElectionTimeout", "150" },
{"upperElectionTimeout", "300" },
{"requestJournal:memoryLimit", "5" },
{"requestJournal:expiration", "00:01:00" },
{"members:0", "https://192.168.31.144:3262" }
};
As I understand it, the equivalent in JSON is the following file:
{
"partitioning": "false",
"lowerElectionTimeout": "150",
"upperElectionTimeout": "300",
"requestJournal": {
"memoryLimit": "5",
"expiration": "00:01:00"
},
"members": {
"0": "https://192.168.31.144:3262"
}
}
When I insert the dictionary configuration like this, everything works perfectly:
.ConfigureAppConfiguration(builder => builder.AddInMemoryCollection(configuration))
But if I insert it via JSON this way it doesn't work, do you know why?
.ConfigureAppConfiguration(builder => builder.AddJsonFile("settingsRaft.json", optional: false, reloadOnChange: true))
If you had an example I would really appreciate it.
I'm not sure that the configuration mentioned above satisfies the requirements of JSON-based configuration in ASP.NET Core. Probably, the array or members should be defined in another way.
.NET JSON configuration uses JSON arrays instead of indexing array elements directly:
{
"members": ["https://192.168.31.144:3262"]
}
Closing the issue due to inactivity.
Hi,
Do you have a example to use
IMemberDiscoveryService?
I would like to add members dynamically in the cluster...Best regards,
Luis