-
Notifications
You must be signed in to change notification settings - Fork 558
Preliminary readiness management #1107
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
Changes from all commits
1064873
67294ab
558b2f4
ab6d323
39e8045
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package com.linkedin.d2.balancer.servers; | ||
|
|
||
| public class NoOpReadinessStatusManager implements ReadinessStatusManager | ||
bohhyang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| @Override | ||
| public void registerAnnouncerStatus(AnnouncerStatus status) | ||
| { | ||
| // no-op | ||
| } | ||
|
|
||
| @Override | ||
| public void onAnnouncerStatusUpdated() | ||
| { | ||
| // no-op | ||
| } | ||
|
|
||
| @Override | ||
| public void addWatcher(ReadinessStatusWatcher watcher) | ||
| { | ||
| // no-op | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| package com.linkedin.d2.balancer.servers; | ||
|
|
||
| import java.util.Objects; | ||
| import javax.annotation.Nonnull; | ||
|
|
||
|
|
||
| /** | ||
| * This interface manages the readiness status of the server. | ||
| * Currently, it's based on D2 announcements' statuses as a preliminary design, can be extended in future for internal | ||
| * components' readiness status. | ||
| * See the <a href="preliminary design doc">https://shorturl.at/hmjz8</a> for details of determining the readiness status based on | ||
| * D2 announcements. Treating D2 announcements as the app servers’ intent to serve traffic, the readiness status is | ||
| * determined by the combination of D2 announcements' sent status. | ||
| */ | ||
| public interface ReadinessStatusManager | ||
| { | ||
| void registerAnnouncerStatus(AnnouncerStatus status); | ||
|
|
||
| void onAnnouncerStatusUpdated(); | ||
|
|
||
| void addWatcher(ReadinessStatusWatcher watcher); | ||
|
|
||
| interface ReadinessStatusWatcher | ||
| { | ||
| void onReadinessStatusChanged(ReadinessStatus newStatus); | ||
| } | ||
|
|
||
| enum ReadinessStatus | ||
| { | ||
| /** | ||
| * There is a time gap between when a serving intent changes (either static config loaded at startup, or dynamic | ||
| * markup/markdown API is called at runtime) and when the intent is fulfilled ---- (de-)announcement sent successfully. | ||
| * During this gap, the intent is not fulfilled, and the readiness status is INCONSISTENT. Or, the (de-)announcements | ||
| * failed to be sent, the readiness status is also INCONSISTENT. | ||
| * This status can be deprecated in future when the readiness status is based on internal components' readiness | ||
| * rather than D2 announcements' statuses. | ||
| */ | ||
| INCONSISTENT, | ||
| /** | ||
| * When all D2 clusters are intended to be de-announced and the de-announcements are sent successfully, or never | ||
| * announced before. | ||
| * Note: if readinessStatusManager.requireStaticD2ServersAnnounced is set to true, and some D2 clusters have | ||
| * isToBeAnnouncedFromStaticConfig set to true, then any of them is de-announced will become NOT_SERVING. | ||
| */ | ||
| NOT_SERVING, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: should we mention that (just considering I could also imagine an argument for
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. INCONSISTENT is when some announcement/de-announcement happened and still ongoing or failed. At start up, no announcement is made yet, so not serving is default. I will comment it in the impl class in container. The interface here should be general. |
||
| /** | ||
| * When the D2 clusters that are intended to be announced have sent announcements successfully. | ||
| * (And if any D2 cluster is intended to be de-announced, the corresponding de-announcement is also sent successfully) | ||
| * Note: if readinessStatusManager.requireStaticD2ServersAnnounced is set to true, all D2 clusters that have | ||
| * isToBeAnnouncedFromStaticConfig set to true must be announced for the readiness status to be SERVING. | ||
| */ | ||
| SERVING | ||
| } | ||
|
|
||
| class AnnouncerStatus | ||
| { | ||
| // whether this announcer is to be announced and defined in static config | ||
| private final boolean isToBeAnnouncedFromStaticConfig; | ||
|
|
||
| private volatile AnnouncementStatus announcementStatus; | ||
|
|
||
| public AnnouncerStatus(boolean isToBeAnnouncedFromStaticConfig, AnnouncementStatus announcementStatus) | ||
| { | ||
| this.isToBeAnnouncedFromStaticConfig = isToBeAnnouncedFromStaticConfig; | ||
| this.announcementStatus = announcementStatus; | ||
| } | ||
|
|
||
| public boolean isToBeAnnouncedFromStaticConfig() | ||
| { | ||
| return isToBeAnnouncedFromStaticConfig; | ||
| } | ||
|
|
||
| public boolean isAnnounced() | ||
| { | ||
| return AnnouncementStatus.ANNOUNCED.equals(announcementStatus); | ||
| } | ||
|
|
||
| public boolean isDeAnnounced() | ||
| { | ||
| return AnnouncementStatus.DE_ANNOUNCED.equals(announcementStatus); | ||
| } | ||
|
|
||
| public boolean isAnnouncing() | ||
| { | ||
| return AnnouncementStatus.ANNOUNCING.equals(announcementStatus); | ||
| } | ||
|
|
||
| public boolean isDeAnnouncing() | ||
| { | ||
| return AnnouncementStatus.DE_ANNOUNCING.equals(announcementStatus); | ||
| } | ||
|
|
||
| public AnnouncementStatus getAnnouncementStatus() | ||
| { | ||
| return announcementStatus; | ||
| } | ||
|
|
||
| public void setAnnouncementStatus(AnnouncementStatus announcementStatus) | ||
| { | ||
| this.announcementStatus = announcementStatus; | ||
| } | ||
|
|
||
| public boolean isEqual(AnnouncerStatus other) | ||
| { | ||
| return other != null && this.isToBeAnnouncedFromStaticConfig == other.isToBeAnnouncedFromStaticConfig | ||
| && Objects.equals(this.announcementStatus, other.announcementStatus); | ||
| } | ||
|
|
||
| public String toString() | ||
| { | ||
| return "AnnouncerStatus{isToBeAnnouncedFromStaticConfig=" + isToBeAnnouncedFromStaticConfig | ||
| + ", announcementStatus=" + announcementStatus + "}"; | ||
| } | ||
|
|
||
| public enum AnnouncementStatus | ||
| { | ||
| DE_ANNOUNCED, // de-announcement sent successfully | ||
| DE_ANNOUNCING, // a de-announcement is to be or is being sent | ||
| ANNOUNCING, // an announcement is to be or is being sent | ||
| ANNOUNCED // announcement sent successfully | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: what's
preliminaryabout it? Would it make more sense to sayinitial implementation of readiness management systemor similar?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, please see the doc in the PR description, also explained in this class's doc. It's preliminary as a short-term solution since it's based on d2 announcements, which shouldn't be in long run with topology aware SD will change it to base on internal components' readiness.