2016-04-05 5 views
5

के साथ आवेदन लीडर चुनाव मैं कंसुल का उपयोग करके आवेदन लीडर चुनाव कैसे करें, इसके बारे में अपना सिर प्राप्त करने की कोशिश कर रहा हूं। मैं जावा कंसुल-क्लाइंट से लीडर चयन का उपयोग कर रहा हूं।जावा कंसुल-क्लाइंट

मैं एक नेता का चयन कर सकता हूं, और सभी नोड नेता पर सहमत होते हैं, लेकिन यदि नेता आवेदन मर जाता है, तो अन्य नोड्स अनजान लगते हैं और getLeaderInfoForService को कॉल करते समय मृत नेता को जारी रखना जारी रखते हैं - यानी कोई नया नेतृत्व चुनाव नहीं होता है।

नेता Electrion गाइड (https://www.consul.io/docs/guides/leader-election.html) का उल्लेख है:

"ध्यान दें कि डिफ़ॉल्ट रूप से सत्र केवल गपशप विफलता डिटेक्टर का उपयोग करता है यही है, सत्र डिफ़ॉल्ट कम्मी के रूप में एक नोड द्वारा आयोजित माना जाता है जब तक। स्वास्थ्य जांच ने नोड को अस्वास्थ्यकर घोषित नहीं किया है। वांछित होने पर अतिरिक्त चेक निर्दिष्ट किए जा सकते हैं। "

तो इससे मुझे लगता है कि शायद मुझे सत्र में एक एप्लीकेशन लेवल हेल्थ चेक (टीटीएल इत्यादि) जोड़ने की ज़रूरत है, ताकि जब एप्लिकेशन विफल हो जाए तो सत्र को अमान्य कर दिया जाएगा? क्या यह सही विचार है और यदि जावा क्लाइंट के माध्यम से ऐसा करने का कोई तरीका है? मैं नेता चुनने के लिए ठीक हूं और एक नेता चुनने के लिए अपना कोड लिख रहा हूं लेकिन ऐसा लगता है कि सत्र क्लाइंट में भी इसके साथ जुड़े स्वास्थ्य जांच के साथ सत्र बनाने का कोई तरीका नहीं है?

या शायद यह हासिल करने का एक बेहतर तरीका है (नेता पुन: चुनाव के लिए आवेदन स्तर विफलता का पता लगाने)? मैं फंस गया हूं इसलिए किसी भी पॉइंटर्स की सराहना की जाएगी।

उत्तर

2

इसलिए अगर किसी और को इस समस्या में आता है तो मैंने इसे हल किया।

मैं लीडर चयन का उपयोग नहीं कर सका, लेकिन मैंने अपनी खुद की कक्षा को एक ही तरह की चीज करने के लिए बनाया, लेकिन निर्माण सत्र विधि में मैंने 10 के टीटीएल को जोड़ा।

private String createSession(String serviceName) { 
    final Session session = 
ImmutableSession.builder().name(serviceName).ttl("10s").build(); 

return client.sessionClient().createSession(session).getId(); 
} 

इस के लिए काम करने के लिए आप एक पृष्ठभूमि धागा कि कम से कम एक बार सत्र पर renewSession कॉल हर 10 सेकंड की आवश्यकता होगी।

+0

यह सत्र है, लेकिन ऊपर दिए गए दस्तावेज़ के अनुसार, आप शोल करते हैं डी भी एक कुंजी पर ताला हासिल करने का प्रयास करें। इसके लिए प्रासंगिक कोड साझा करने की देखभाल? – Guss

1

मैं एक ही आवश्यकता को लागू करने की कोशिश कर रहा हूं: मेरे पास एक जावा सेवा है जिसे एक नेता का चयन करने की आवश्यकता है, और मेरे पास कंसुल में कॉन्फ़िगर किए गए सेवा स्वास्थ्य जांच नहीं हैं।

कंसुल-क्लाइंट से 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 मतदान से दूसरे नोड को नहीं रोकेगा।

  • टीटीएल स्वास्थ्य जांच
  • पर पंजीयन सत्र बांधने केवल इस चेक

प्रासंगिक:

0

यदि यह अभी भी प्रासंगिक है, मैं (उम्मीद) संभावित चारों ओर झूठे सकारात्मक के लिए से मिला कोड स्निपेट:

sessionClient.createSession(
    ImmutableSession.builder() 
     .addChecks(checkId) // Ties the session to this check 
     .behavior("delete") 
     .lockDelay("15s") 
     .build() 
    )