Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IGNITE-23054 Improve cluster status REST endpoint #4614

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

Pochatkin
Copy link
Contributor

@Pochatkin Pochatkin commented Oct 22, 2024

https://issues.apache.org/jira/browse/IGNITE-23054

Cluster status REST and CLI methods are improved:

  • Added different states healthy, cmg majority lost, metastore majority lost
  • When cmg majority lost returns corresponding status instead of timeout exception
  • Impoved integration test's cluster class. Added possibility to select different nodes for CMG and MS groups

assertOutput("cluster", 2, "Metastore majority lost", cmgNodes(), metastoreNodes());

CLUSTER.startNode(0);
Thread.sleep(10000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change this to await().untilAsserted()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@@ -33,6 +33,8 @@ class ItSqlCommandTest extends CliSqlCommandTestBase {
void nonExistingFile() {
execute("sql", "--file", "nonexisting", "--jdbc-url", JDBC_URL);

CLUSTER.stopNode(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed


/**
* Call to get cluster status.
*/
@Singleton
public class ClusterStatusCall implements Call<UrlCallInput, ClusterStatus> {
public class ClusterStatusCall implements Call<UrlCallInput, ClusterState> {
private static final int READ_TIMEOUT = 50_000;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this needs to be 50 seconds? As I understand this depends on the timeout settings in the cluster state retrieval, can we at least point to the place where this is configured in the CMGManager?

@@ -64,24 +73,28 @@ public class ClusterState {
@JsonCreator
public ClusterState(
@JsonProperty("cmgNodes") Collection<String> cmgNodes,
@JsonProperty("msNodes") Collection<String> msNodes,
@JsonProperty("msNodes") Collection<String> msNodes,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@JsonProperty("msNodes") Collection<String> msNodes,
@JsonProperty("msNodes") Collection<String> msNodes,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

);
}

private ClusterStatus mapClusterStatus(org.apache.ignite.internal.cluster.management.ClusterState clusterState) {
Set<String> metaStorageNodes = clusterState.metaStorageNodes();
long presentedMetaStorageNodes = topologyService.allMembers().stream()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
long presentedMetaStorageNodes = topologyService.allMembers().stream()
long presentMetaStorageNodes = topologyService.allMembers().stream()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

.filter(metaStorageNodes::contains)
.count();

if (presentedMetaStorageNodes <= metaStorageNodes.size() / 2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (presentedMetaStorageNodes <= metaStorageNodes.size() / 2) {
if (presentMetaStorageNodes <= metaStorageNodes.size() / 2) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@Pochatkin Pochatkin requested review from rpuch and valepakh and removed request for valepakh November 1, 2024 10:00
public class ClusterStatusCall implements Call<UrlCallInput, ClusterState> {
/**
* We need to overlap timeout from raft client.
* We can't determine timeout value because it's configurable for each node
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can read the node configuration here and just add a couple of seconds to the configured timeout?


/**
* Class that represents the cluster status.
*/
public class ClusterStatus {
public class ClusterState {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have an entity called 'cluster state' in the CMG domain. This one is a different entity and yet it's called identically. Could a distinct name be devised? Something like ClusterRuntimeState, maybe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is CLI output DTO object. So, I have added postfix

Comment on lines 59 to 60
this.cmgNodes = cmgNodes;
this.metadataStorageNodes = metadataStorageNodes;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about making defensive copies? Better safe than sorry, and this class should not have a huge amount of instances

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use builder approach in CLI module

Comment on lines 52 to 57
case MS_MAJORITY_LOST:
return fg(Color.RED).mark("Metastore majority lost");
case HEALTHY:
return fg(Color.GREEN).mark("active");
case CMG_MAJORITY_LOST:
return fg(Color.RED).mark("CMG majority lost");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ordering is a bit strange: why is HEALTHY in the middle?

private final ClusterTag clusterTag;

@Schema(description = "IDs the cluster had before.")
@IgniteToStringInclude
private final @Nullable List<UUID> formerClusterIds;

@Schema(description = "Cluster status.",
requiredMode = RequiredMode.REQUIRED)
private final ClusterStatus clusterStatus;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that entities from different domains are mixed here. This ClusterState class represents the CMG cluster state that is the state stored in the CMG related to the cluster itself. But ClusterStatus is some volatile thing, it might change during runtime however it wants, even if the CMG cluster state does not change.

I believe we should not mix them together. Could a distinct API endpoint (and CLI command) be added to access this volatile information?


/**
* The metastore group has lost its majority. Almost all of the cluster functions are inoperative.
* To restore their operation, it is necessary to return the majority to the metastore group.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* To restore their operation, it is necessary to return the majority to the metastore group.
* To restore their operation, it is necessary to restore the majority to the metastore group.

MS_MAJORITY_LOST,

/**
* The cluster management group has lost its majority. The cluster is completely inoperative until the majority is returned.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* The cluster management group has lost its majority. The cluster is completely inoperative until the majority is returned.
* The cluster management group has lost its majority. The cluster is completely inoperative until the majority is restored.

.count();

if (presentMetaStorageNodes <= metaStorageNodes.size() / 2) {
return ClusterStatus.MS_MAJORITY_LOST;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that we have enough nodes in the physical topology does not necessarily imply we have an MG majority. For instance, something on levels higher than the network might prevent a leader to be elected. The most accurate way would be to try executing a read command against the MS group (like reading its current revision) and handle a timeout.

# Conflicts:
#	modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/MetaStorageManagerImpl.java
#	modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/MetaStorageService.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants