मैं एक ही आवश्यकता को लागू करने की कोशिश कर रहा हूं: मेरे पास एक जावा सेवा है जिसे एक नेता का चयन करने की आवश्यकता है, और मेरे पास कंसुल में कॉन्फ़िगर किए गए सेवा स्वास्थ्य जांच नहीं हैं।
कंसुल-क्लाइंट से LeaderElectionUtil
का उपयोग समस्याग्रस्त है क्योंकि यदि उपरोक्त सभी कारण बताए गए हैं। दुर्भाग्यवश LeaderElectionUtil
को कस्टमाइज़ करना भी संभव नहीं है क्योंकि इसकी सभी आंतरिक कार्य निजी विधियों का उपयोग करके किया जाता है (इसे protected
का उपयोग करना चाहिए और उपयोगकर्ताओं को सत्र निर्माण को ओवरराइड करना चाहिए - उदाहरण के लिए)।
मैंने कंसुल-क्लाइंट रीडमे में "मूल उपयोग - उदाहरण 1" में दस्तावेज़ के रूप में "सेवा पंजीकरण" को लागू करने का प्रयास किया है, लेकिन मेरे लिए calling AgentClient.pass()
always throws an exception।
तो मेरा समाधान ठीक है जो आपने निर्दिष्ट किया है - एक टीटीएल के साथ एक सत्र है और जब तक सेवा जीवित है तब तक इसे नवीनीकृत करें।
यहाँ मेरी कार्यान्वयन है, जो उपयोगकर्ता की आवश्यकता भी एक कॉलबैक कि अगर सेवा अभी भी नवीकरण के लिए मान्य है की जाँच करने के लिए किया जाता है रजिस्टर करने के लिए है, बस मामले में:
public class SessionHolder implements Runnable {
private static final String TTL_TEMPLATE = "%ss";
private Consul client;
private String id;
private LinkedList<Supplier<Boolean>> liveChecks = new LinkedList<>();
private long ttl;
private boolean shutdown = false;
public SessionHolder(Consul client, String service, long ttl) {
this.client = client;
this.ttl = ttl;
final Session session = ImmutableSession.builder()
.name(service)
.ttl(String.format(TTL_TEMPLATE, ttl))
.build();
id = client.sessionClient().createSession(session).getId();
Thread upkeep = new Thread(this);
upkeep.setDaemon(true);
upkeep.start();
}
public String getId() {
return id;
}
public void registerKeepAlive(Supplier<Boolean> liveCheck) {
liveChecks.add(liveCheck);
}
@Override
public synchronized void run() {
// don't start renewing immediately
try {
wait(ttl/2 * 1000);
} catch (InterruptedException e) {}
while (!isShutdown()) {
if (liveChecks.isEmpty() || liveChecks.stream().allMatch(Supplier::get)) {
client.sessionClient().renewSession(getId());
}
try {
wait(ttl/2 * 1000);
} catch (InterruptedException e) {
// go on, try again
}
}
}
public synchronized boolean isShutdown() {
return shutdown;
}
public synchronized void close() {
shutdown = true;
notify();
client.sessionClient().destroySession(getId());
}
}
तो चुनाव एक नेता और अधिक या कम है के रूप में सरल रूप में:
if (consul.keyValueClient().acquireLock(getServiceKey(service), currentNode, sessionHolder.getId()))
return true; // I'm the leader
एक बात है कि याद की जरूरत है, उस सत्र ठीक से सफाई (क्या मैं SessionHolder.close()
में ऊपर है) के बिना समाप्त हो जाता है, तो, वाणिज्य दूत की lock-delay
सुविधा एक नए नेता निर्वाचित होने की च कर पाएगा है या लगभग 15 सेकंड (डिफ़ॉल्ट, जो दुर्भाग्य से कंसुल-क्लाइंट संशोधित करने के लिए एपीआई प्रदान नहीं करता है)।
यह हल करने के लिए, यह सुनिश्चित करने के अलावा कि उपर्युक्त प्रदर्शन के रूप में स्वयं को ठीक से समाप्त करने के बाद सेवाओं को साफ कर दिया जाए, मैं यह भी सुनिश्चित करता हूं कि सेवा को कम से कम समय के लिए नेता की स्थिति रखें, और नेतृत्व को छोड़ दें consul.keyValueClient().releaseLock()
पर कॉल करके, इसका उपयोग नहीं करते समय। उदाहरण के लिए, मेरे पास एक क्लस्टर सेवा है जहां हम एक बाहरी आरडीबीएमएस से डेटा अपडेट पढ़ने के लिए एक नेता का चयन करते हैं (जिसे तब सभी डेटा को पुनः लोड करने के बजाय सीधे क्लस्टर में वितरित किया जाता है)। चूंकि यह मतदान के माध्यम से किया जाता है, इसलिए प्रत्येक नोड मतदान से पहले निर्वाचित होने का प्रयास करेगा, और यदि चुने गए तो यह डेटाबेस को मतदान करेगा, अद्यतन प्रसारित करेगा और इस्तीफा दे देगा। यदि उसके बाद यह दुर्घटनाग्रस्त हो जाता है, delay-lock
मतदान से दूसरे नोड को नहीं रोकेगा।
- टीटीएल स्वास्थ्य जांच
- पर पंजीयन सत्र बांधने केवल इस चेक
प्रासंगिक:
यह सत्र है, लेकिन ऊपर दिए गए दस्तावेज़ के अनुसार, आप शोल करते हैं डी भी एक कुंजी पर ताला हासिल करने का प्रयास करें। इसके लिए प्रासंगिक कोड साझा करने की देखभाल? – Guss