Misalkan kita memiliki dua node peer: node pertama dapat mengirim permintaan koneksi ke yang kedua, tetapi juga yang kedua dapat mengirim permintaan koneksi ke yang pertama. Bagaimana cara menghindari koneksi ganda antara kedua node? Untuk mengatasi masalah ini, cukup berurutan untuk operasi yang dilakukan untuk membuat koneksi TCP masuk atau keluar.
Ini berarti bahwa setiap node harus memproses secara berurutan setiap operasi pembuatan koneksi baru, baik untuk koneksi masuk maupun untuk koneksi keluar. Dengan cara ini, mempertahankan daftar node yang terhubung, sebelum menerima koneksi masuk baru dari suatu node atau sebelum mengirim permintaan koneksi ke sebuah node, itu akan cukup untuk memeriksa apakah node ini sudah ada dalam daftar.
Untuk membuat sekuensial operasi pembuatan koneksi, cukup dengan melakukan kunci pada daftar node yang terhubung: pada kenyataannya, untuk setiap koneksi baru, pengidentifikasi dari node yang terhubung baru ditambahkan ke daftar ini. Namun, saya bertanya-tanya apakah pendekatan ini dapat menyebabkan kebuntuan terdistribusi :
- simpul pertama dapat mengirim permintaan koneksi ke simpul kedua;
- simpul kedua bisa mengirim permintaan koneksi ke yang pertama;
- dengan asumsi bahwa dua permintaan koneksi tidak sinkron, kedua node mengunci setiap permintaan koneksi yang masuk.
Bagaimana saya bisa menyelesaikan masalah ini?
UPDATE: Namun, saya masih harus mengunci daftar setiap kali koneksi baru (masuk atau keluar) dibuat, karena utas lain dapat mengakses daftar ini, maka masalah kebuntuan masih akan tetap ada.
UPDATE 2: Berdasarkan saran Anda, saya menulis sebuah algoritma untuk mencegah saling menerima permintaan login. Karena setiap node adalah peer, itu bisa memiliki rutin klien untuk mengirim permintaan koneksi baru dan rutin server untuk menerima koneksi masuk.
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
}
Contoh: IP: port node A adalah A: 7001 - IP: port node B adalah B: 8001.
Misalkan node A telah mengirim permintaan login ke node B: 8001. Dalam hal ini, simpul A memanggil rutin masuk dengan mengirim dengan mengirimkan alamat pendengarannya sendiri (A: 7001). Sebagai konsekuensinya, neighbor_table dari node A berisi alamat dari remote node (B: 8001): alamat ini dikaitkan dengan keadaan CONNECTING. Node A sedang menunggu node B menerima atau menolak permintaan login.
Sementara itu, simpul B juga mungkin telah mengirim permintaan koneksi ke alamat simpul A (A: 7001), kemudian simpul A dapat memproses permintaan dari simpul B. Jadi, neighbor_table dari simpul B berisi alamat dari jarak jauh simpul (A: 7001): alamat ini dikaitkan dengan keadaan CONNECTING. Node B sedang menunggu simpul A menerima atau menolak permintaan masuk.
Jika sisi server dari simpul A menolak permintaan dari B: 8001, maka saya harus yakin bahwa sisi server dari simpul B akan menerima permintaan dari A: 7001. Demikian pula, jika sisi server dari simpul B menolak permintaan dari A: 7001, maka saya harus yakin bahwa sisi server dari simpul A akan menerima permintaan dari B: 8001.
Menurut aturan "alamat kecil" , dalam hal ini simpul A akan menolak permintaan masuk oleh simpul B, sedangkan simpul B akan menerima permintaan dari simpul A.
Apa pendapatmu tentang itu?