MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Tutorial PyMongo:Menguji Failover MongoDB di Aplikasi Python Anda

Python adalah bahasa pemrograman yang andal dan fleksibel yang digunakan oleh jutaan developer di seluruh dunia untuk membangun aplikasi mereka. Tidak mengherankan jika developer Python biasanya memanfaatkan hosting MongoDB, database NoSQL paling populer, untuk penerapan mereka karena sifatnya yang fleksibel dan kurangnya persyaratan skema.

Jadi, apa cara terbaik untuk menggunakan MongoDB dengan Python? PyMongo adalah distribusi Python yang berisi alat untuk bekerja dengan MongoDB, dan driver Python MongoDB yang direkomendasikan. Ini adalah driver yang cukup matang yang mendukung sebagian besar operasi umum dengan database.

Saat menerapkan dalam produksi, sangat disarankan untuk menyiapkan dalam konfigurasi kumpulan replika MongoDB sehingga data Anda didistribusikan secara geografis untuk ketersediaan tinggi. Juga disarankan agar koneksi SSL diaktifkan untuk mengenkripsi lalu lintas basis data klien. Kami sering melakukan pengujian karakteristik failover dari berbagai driver MongoDB agar memenuhi syarat untuk kasus penggunaan produksi, atau saat pelanggan kami meminta saran kepada kami. Dalam postingan ini, kami menunjukkan cara menyambungkan ke kumpulan replika MongoDB berkemampuan SSL yang dikonfigurasi dengan sertifikat yang ditandatangani sendiri menggunakan PyMongo, dan cara menguji perilaku failover MongoDB dalam kode Anda.

Menghubungkan ke MongoDB SSL Menggunakan Sertifikat yang Ditandatangani Sendiri

Langkah pertama adalah memastikan bahwa versi PyMongo yang benar dan dependensinya telah diinstal. Panduan ini membantu Anda memilah dependensi, dan matriks kompatibilitas driver dapat ditemukan di sini.

mongo_client.MongoClient parameter yang menarik bagi kami adalah ssl dan ss_ca_cert . Untuk terhubung ke titik akhir MongoDB berkemampuan SSL yang menggunakan sertifikat yang ditandatangani sendiri, ssl harus disetel ke Benar dan ss_ca_cert harus menunjuk ke file sertifikat CA.

Jika Anda adalah pelanggan ScaleGrid, Anda dapat mengunduh file sertifikat CA untuk klaster MongoDB Anda dari konsol ScaleGrid seperti yang ditunjukkan di sini:

Jadi, cuplikan sambungan akan terlihat seperti:

>>> import pymongo
>>> MONGO_URI = 'mongodb://rwuser:@SG-example-0.servers.mongodirector.com:27017,SG-example-1.servers.mongodirector.com:27017,SG-example-2.servers.mongodirector.com:27017/admin?replicaSet=RS-example&ssl=true'
>>> client = pymongo.MongoClient(MONGO_URI, ssl = True, ssl_ca_certs = '')
>>> print("Databases - " + str(client.list_database_names()))
Databases - ['admin', 'local', 'test']
>>> client.close()
>>>

Jika Anda menggunakan sertifikat yang ditandatangani sendiri di mana verifikasi nama host mungkin gagal, Anda juga harus menyetel ssl_match_hostname parameter ke False . Seperti yang dikatakan oleh dokumentasi driver, ini tidak disarankan karena membuat koneksi rentan terhadap serangan man-in-the-middle.

Menguji Perilaku Failover

Dengan penerapan MongoDB, failover tidak dianggap sebagai peristiwa besar seperti halnya dengan sistem manajemen basis data tradisional. Meskipun sebagian besar driver MongoDB mencoba mengabstraksi peristiwa ini, pengembang harus memahami dan mendesain aplikasi mereka untuk perilaku seperti itu, karena aplikasi seharusnya mengharapkan kesalahan jaringan sementara dan mencoba lagi sebelum kesalahan meresap.

Anda dapat menguji ketahanan aplikasi Anda dengan menginduksi failover saat beban kerja Anda berjalan. Cara termudah untuk menginduksi failover adalah dengan menjalankan perintah rs.stepDown():

RS-example-0:PRIMARY> rs.stepDown()
2019-04-18T19:44:42.257+0530 E QUERY [thread1] Error: error doing query: failed: network error while attempting to run command 'replSetStepDown' on host 'SG-example-1.servers.mongodirector.com:27017' :
DB.prototype.runCommand@src/mongo/shell/db.js:168:1
DB.prototype.adminCommand@src/mongo/shell/db.js:185:1
rs.stepDown@src/mongo/shell/utils.js:1305:12
@(shell):1:1
2019-04-18T19:44:42.261+0530 I NETWORK [thread1] trying reconnect to SG-example-1.servers.mongodirector.com:27017 (X.X.X.X) failed
2019-04-18T19:44:43.267+0530 I NETWORK [thread1] reconnect SG-example-1.servers.mongodirector.com:27017 (X.X.X.X) ok
RS-example-0:SECONDARY>

Salah satu cara saya ingin menguji perilaku driver adalah dengan menulis aplikasi penulis 'abadi' sederhana. Ini akan menjadi kode sederhana yang terus menulis ke database kecuali diinterupsi oleh pengguna, dan akan mencetak semua pengecualian yang ditemukan untuk membantu kami memahami driver dan perilaku database. Saya juga melacak data yang ditulisnya untuk memastikan bahwa tidak ada kehilangan data yang tidak dilaporkan dalam pengujian. Inilah bagian relevan dari kode pengujian yang akan kami gunakan untuk menguji perilaku failover MongoDB kami:

import logging
import traceback
...
import pymongo
...
logger = logging.getLogger("test")

MONGO_URI = 'mongodb://rwuser:@SG-example-0.servers.mongodirector.com:48273,SG-example-1.servers.mongodirector.com:27017,SG-example-2.servers.mongodirector.com:27017/admin?replicaSet=RS-example-0&ssl=true'

try:
    logger.info("Attempting to connect...")
    client = pymongo.MongoClient(MONGO_URI, ssl = True, ssl_ca_certs = 'path-to-cacert.pem')
    db = client['test']
    collection = db['test']
    i = 0
    while True:
        try:
            text = ''.join(random.choices(string.ascii_uppercase + string.digits, k = 3))
            doc = { "idx": i, "date" : datetime.utcnow(), "text" : text}
            i += 1
            id = collection.insert_one(doc).inserted_id
            logger.info("Record inserted - id: " + str(id))
            sleep(3)
        except pymongo.errors.ConnectionFailure as e:
            logger.error("ConnectionFailure seen: " + str(e))
            traceback.print_exc(file = sys.stdout)
            logger.info("Retrying...")

    logger.info("Done...")
except Exception as e:
    logger.error("Exception seen: " + str(e))
    traceback.print_exc(file = sys.stdout)
finally:
    client.close()

Jenis entri yang ditulis seperti ini:

RS-example-0:PRIMARY> db.test.find()
{ "_id" : ObjectId("5cb6d6269ece140f18d05438"), "idx" : 0, "date" : ISODate("2019-04-17T07:30:46.533Z"), "text" : "400" }
{ "_id" : ObjectId("5cb6d6299ece140f18d05439"), "idx" : 1, "date" : ISODate("2019-04-17T07:30:49.755Z"), "text" : "X63" }
{ "_id" : ObjectId("5cb6d62c9ece140f18d0543a"), "idx" : 2, "date" : ISODate("2019-04-17T07:30:52.976Z"), "text" : "5BX" }
{ "_id" : ObjectId("5cb6d6329ece140f18d0543c"), "idx" : 4, "date" : ISODate("2019-04-17T07:30:58.001Z"), "text" : "TGQ" }
{ "_id" : ObjectId("5cb6d63f9ece140f18d0543d"), "idx" : 5, "date" : ISODate("2019-04-17T07:31:11.417Z"), "text" : "ZWA" }
{ "_id" : ObjectId("5cb6d6429ece140f18d0543e"), "idx" : 6, "date" : ISODate("2019-04-17T07:31:14.654Z"), "text" : "WSR" }
..

Menangani Pengecualian ConnectionFailure

Perhatikan bahwa kami menangkap pengecualian ConnectionFailure untuk menangani semua masalah terkait jaringan yang mungkin kami temui karena failover – kami mencetak pengecualian dan terus mencoba menulis ke database. Dokumentasi driver merekomendasikan bahwa:

Jika operasi gagal karena kesalahan jaringan, ConnectionFailure dimunculkan dan klien menyambung kembali di latar belakang. Kode aplikasi harus menangani pengecualian ini (mengakui bahwa operasi gagal) dan kemudian melanjutkan eksekusi.

Mari kita jalankan ini dan lakukan failover database saat dijalankan. Inilah yang terjadi:

04/17/2019 12:49:17 PM INFO Attempting to connect...
04/17/2019 12:49:20 PM INFO Record inserted - id: 5cb6d3789ece145a2408cbc7
04/17/2019 12:49:23 PM INFO Record inserted - id: 5cb6d37b9ece145a2408cbc8
04/17/2019 12:49:27 PM INFO Record inserted - id: 5cb6d37e9ece145a2408cbc9
04/17/2019 12:49:30 PM ERROR PyMongoError seen: connection closed
Traceback (most recent call last):
    id = collection.insert_one(doc).inserted_id
  File "C:\Users\Random\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pymongo\collection.py", line 693, in insert_one
    session=session),
...
  File "C:\Users\Random\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pymongo\network.py", line 173, in receive_message
    _receive_data_on_socket(sock, 16))
  File "C:\Users\Random\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pymongo\network.py", line 238, in _receive_data_on_socket
    raise AutoReconnect("connection closed")
pymongo.errors.AutoReconnect: connection closed
04/17/2019 12:49:30 PM INFO Retrying...
04/17/2019 12:49:42 PM INFO Record inserted - id: 5cb6d3829ece145a2408cbcb
04/17/2019 12:49:45 PM INFO Record inserted - id: 5cb6d3919ece145a2408cbcc
04/17/2019 12:49:49 PM INFO Record inserted - id: 5cb6d3949ece145a2408cbcd
04/17/2019 12:49:52 PM INFO Record inserted - id: 5cb6d3989ece145a2408cbce

Perhatikan bahwa driver membutuhkan waktu sekitar 12 detik untuk memahami topologi baru, menyambung ke primer baru, dan melanjutkan menulis. Pengecualian yang diangkat adalah error . Sambungkan Ulang Otomatis yang merupakan subkelas dari ConnectionFailure .

Tutorial PyMongo:Menguji Kegagalan MongoDB di Aplikasi Python AndaKlik Untuk Tweet

Anda dapat melakukan beberapa langkah lagi untuk melihat pengecualian lain yang terlihat. Misalnya, inilah jejak pengecualian lain yang saya temui:

    id = collection.insert_one(doc).inserted_id
  File "C:\Users\Random\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pymongo\collection.py", line 693, in insert_one
    session=session),
...
  File "C:\Users\Randome\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pymongo\network.py", line 150, in command
    parse_write_concern_error=parse_write_concern_error)
  File "C:\Users\Random\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pymongo\helpers.py", line 132, in _check_command_response
    raise NotMasterError(errmsg, response)
pymongo.errors.NotMasterError: not master

Pengecualian ini juga merupakan subkelas ConnectionFailure.

Parameter ‘retryWrites’

Area lain untuk menguji perilaku failover MongoDB adalah melihat bagaimana variasi parameter lain memengaruhi hasil. Salah satu parameter yang relevan adalah ‘retryWrites ‘:

retryWrites:(boolean) Apakah operasi tulis yang didukung yang dijalankan dalam MongoClient ini akan dicoba ulang sekali setelah kesalahan jaringan pada MongoDB 3.6+. Default ke False.

Mari kita lihat bagaimana parameter ini bekerja dengan failover. Satu-satunya perubahan yang dilakukan pada kode adalah:

client = pymongo.MongoClient(MONGO_URI, ssl = True, ssl_ca_certs = 'path-to-cacert.pem', retryWrites = True)

Mari kita jalankan sekarang, lalu lakukan failover sistem database:

04/18/2019 08:49:30 PM INFO Attempting to connect...
04/18/2019 08:49:35 PM INFO Record inserted - id: 5cb895869ece146554010c77
04/18/2019 08:49:38 PM INFO Record inserted - id: 5cb8958a9ece146554010c78
04/18/2019 08:49:41 PM INFO Record inserted - id: 5cb8958d9ece146554010c79
04/18/2019 08:49:44 PM INFO Record inserted - id: 5cb895909ece146554010c7a
04/18/2019 08:49:48 PM INFO Record inserted - id: 5cb895939ece146554010c7b <<< Failover around this time
04/18/2019 08:50:04 PM INFO Record inserted - id: 5cb895979ece146554010c7c
04/18/2019 08:50:07 PM INFO Record inserted - id: 5cb895a79ece146554010c7d
04/18/2019 08:50:10 PM INFO Record inserted - id: 5cb895aa9ece146554010c7e
04/18/2019 08:50:14 PM INFO Record inserted - id: 5cb895ad9ece146554010c7f
...

Perhatikan bagaimana penyisipan setelah failover memakan waktu sekitar 12 detik, tetapi berhasil melalui retryWrites parameter memastikan penulisan yang gagal dicoba lagi. Ingatlah bahwa menyetel parameter ini tidak membebaskan Anda dari penanganan ConnectionFailure pengecualian - Anda perlu khawatir tentang pembacaan dan operasi lain yang perilakunya tidak terpengaruh oleh parameter ini. Ini juga tidak sepenuhnya menyelesaikan masalah, bahkan untuk operasi yang didukung – terkadang failover membutuhkan waktu lebih lama untuk diselesaikan dan retryWrites saja tidak akan cukup.

Mengonfigurasi Nilai Batas Waktu Jaringan

rs.stepDown() menginduksi failover yang agak cepat, karena set replika primer diinstruksikan untuk menjadi sekunder, dan sekunder mengadakan pemilihan untuk menentukan primer baru. Dalam penerapan produksi, beban jaringan, partisi, dan masalah serupa lainnya menunda deteksi ketidaktersediaan server utama, sehingga memperpanjang waktu failover Anda. Anda juga akan sering mengalami kesalahan PyMongo seperti errors.ServerSelectionTimeoutError , errors.NetworkTimeout, dll. selama masalah jaringan dan failover.

Jika ini sangat sering terjadi, Anda harus mengubah parameter batas waktu. Terkait MongoClient parameter waktu habis adalah serverSelectionTimeoutMS , connectTimeoutMS, dan socketTimeoutMS . Dari jumlah tersebut, memilih nilai yang lebih besar untuk serverSelectionTimeoutMS paling sering membantu dalam menangani kesalahan selama failover:

serverSelectionTimeoutMS:(bilangan bulat) Mengontrol berapa lama (dalam milidetik) pengemudi akan menunggu untuk menemukan server yang tersedia dan sesuai untuk menjalankan operasi basis data; sementara menunggu, beberapa operasi pemantauan server dapat dilakukan, masing-masing dikendalikan oleh connectTimeoutMS. Defaultnya adalah 30000 (30 detik).

Siap menggunakan MongoDB dalam aplikasi Python Anda? Lihat artikel Memulai Python dan MongoDB kami untuk melihat bagaimana Anda dapat memulai dan menjalankannya hanya dalam 5 langkah mudah. ScaleGrid adalah satu-satunya penyedia DBaaS MongoDB yang memberi Anda akses SSH penuh ke instance Anda sehingga Anda dapat menjalankan server Python di mesin yang sama dengan server MongoDB Anda. Otomatiskan penerapan cloud MongoDB Anda di AWS, Azure, atau DigitalOcean dengan server khusus, ketersediaan tinggi, dan pemulihan bencana sehingga Anda dapat fokus mengembangkan aplikasi Python Anda.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Bagaimana cara meminta MongoDB untuk menguji apakah suatu item ada?

  2. 10 pertanyaan untuk ditanyakan (dan dijawab) saat menghosting MongoDB di AWS

  3. Bagaimana cara menghapus dokumen menggunakan Node.js Mongoose?

  4. Pengumpulan kunci Mongodb hingga bendera disetel?

  5. Pembuatan Indeks MongoDB – Mencegah Pengguna Memicu Pembuatan Baru