मान लें कि हमारे पास दो सहकर्मी नोड हैं: पहला नोड दूसरे को कनेक्शन अनुरोध भेज सकता है, लेकिन दूसरा भी पहले वाले को कनेक्शन अनुरोध भेज सकता है। दो नोड्स के बीच दोहरे संबंध से कैसे बचें? इस समस्या को हल करने के लिए, इनबाउंड या आउटबाउंड टीसीपी कनेक्शन बनाने के लिए प्रदर्शन किए गए अनुक्रमिक बनाने के लिए पर्याप्त होगा।
इसका मतलब है कि प्रत्येक नोड को प्रत्येक नए कनेक्शन निर्माण ऑपरेशन की प्रक्रिया करनी चाहिए, दोनों आने वाले कनेक्शनों के लिए और आउटगोइंग कनेक्शनों के लिए। इस तरह, नोड से एक नया आवक कनेक्शन स्वीकार करने से पहले या नोड से कनेक्शन अनुरोध भेजने से पहले, जुड़े नोड्स की एक सूची बनाए रखना, यह जाँचने के लिए पर्याप्त होगा कि क्या यह नोड पहले से ही सूची में मौजूद है।
अनुक्रमिक बनाने के लिए कनेक्शन बनाने के संचालन के लिए, कनेक्टेड नोड्स की सूची पर एक लॉक करने के लिए पर्याप्त है : वास्तव में, प्रत्येक नए कनेक्शन के लिए, नए कनेक्टेड नोड के पहचानकर्ता को इस सूची में जोड़ा जाता है। हालांकि, मुझे आश्चर्य है कि अगर यह दृष्टिकोण वितरित गतिरोध का कारण बन सकता है :
- पहला नोड दूसरे को कनेक्शन अनुरोध भेज सकता है;
- दूसरा नोड पहले वाले को कनेक्शन अनुरोध भेज सकता है;
- यह मानते हुए कि दो कनेक्शन अनुरोध अतुल्यकालिक नहीं हैं, दोनों नोड्स आने वाले कनेक्शन अनुरोधों को लॉक करते हैं।
मैं इस समस्या को कैसे हल कर सकता हूं?
अद्यतन: हालांकि, मुझे अभी भी सूची पर हर बार एक नया (आवक या आउटगोइंग) कनेक्शन बनाया जाता है, क्योंकि अन्य धागे इस सूची तक पहुंच सकते हैं, फिर भी गतिरोध की समस्या बनी रहेगी।
अद्यतन 2: आपकी सलाह के आधार पर मैंने लॉगिन अनुरोध की पारस्परिक स्वीकृति को रोकने के लिए एक एल्गोरिथ्म लिखा। चूंकि प्रत्येक नोड एक सहकर्मी है, इसलिए नए कनेक्शन अनुरोध भेजने और आने वाले कनेक्शनों को स्वीकार करने के लिए सर्वर रूटीन के लिए ग्राहक की दिनचर्या हो सकती है ।
ClientSideLoginRoutine() {
for each (address in cache) {
lock (neighbors_table) {
if (neighbors_table.contains(address)) {
// there is already a neighbor with the same address
continue;
}
neighbors_table.add(address, status: CONNECTING);
} // end lock
// ...
// The node tries to establish a TCP connection with the remote address
// and perform the login procedure by sending its listening address (IP and port).
boolean login_result = // ...
// ...
if (login_result)
lock (neighbors_table)
neighbors_table.add(address, status: CONNECTED);
} // end for
}
ServerSideLoginRoutine(remoteListeningAddress) {
// ...
// initialization of data structures needed for communication (queues, etc)
// ...
lock(neighbors_table) {
if(neighbors_table.contains(remoteAddress) && its status is CONNECTING) {
// In this case, the client-side on the same node has already
// initiated the procedure of logging in to the remote node.
if (myListeningAddress < remoteListeningAddress) {
refusesLogin();
return;
}
}
neighbors_table.add(remoteListeningAddress, status: CONNECTED);
} // end lock
}
उदाहरण: IP: नोड A का पोर्ट A: 7001 है - IP: नोड B का पोर्ट B: 8001 है।
मान लीजिए कि नोड ए ने नोड बी: 8001 पर एक लॉगिन अनुरोध भेजा है। इस मामले में, नोड ए अपने स्वयं के सुनने के पते (ए: 7001) भेजकर लॉगिन दिनचर्या कहता है। परिणामस्वरूप, पड़ोसी A के नोड A में दूरस्थ नोड (B: 8001) का पता होता है: यह पता CONNECTING स्थिति से संबद्ध है। नोड ए, नोड बी के लिए प्रतीक्षा कर रहा है या लॉगिन अनुरोध को अस्वीकार कर सकता है।
इस बीच, नोड बी ने नोड ए (ए: 7001) के पते पर एक कनेक्शन अनुरोध भेजा है, तो नोड ए नोड बी के अनुरोध को संसाधित कर सकता है। इसलिए, नोड बी के पड़ोसियों_योग्य में रिमोट का पता शामिल है नोड (ए: 7001): यह पता कनेक्शन स्थिति के साथ जुड़ा हुआ है। नोड बी नोड ए के लिए प्रतीक्षा कर रहा है या लॉगिन अनुरोध को अस्वीकार कर सकता है।
यदि नोड ए का सर्वर पक्ष बी: 8001 से अनुरोध को अस्वीकार करता है, तो मुझे यह सुनिश्चित करना चाहिए कि नोड बी का सर्वर पक्ष ए: 7001 से अनुरोध को स्वीकार करेगा। इसी प्रकार, यदि नोड B का सर्वर पक्ष A: 7001 से अनुरोध को अस्वीकार करता है, तो मुझे यह सुनिश्चित करना चाहिए कि नोड A का सर्वर पक्ष B: 8001 से अनुरोध स्वीकार करेगा।
के अनुसार "छोटे पता" नियम , इस मामले में नोड ए, नोड बी द्वारा लॉगिन अनुरोध को अस्वीकार करते हुए नोड बी नोड ए से अनुरोध स्वीकार करेगा
तुम उसके बारे में क्या सोचते हो?