Data la popolarità del nostro post sulla connessione di MongoDB SSL con certificati autofirmati in Node.js, abbiamo deciso di scrivere un tutorial sulla connessione di MongoDB con Ruby. In questo blog, ti mostreremo come connetterti a un server MongoDB configurato con certificati autofirmati per SSL utilizzando sia il driver Ruby MongoDB che il popolare mongoide Object-Document-Mapper (ODM).
ScaleGrid attualmente utilizza certificati autofirmati per SSL durante la creazione di nodi per un nuovo cluster. Inoltre, ti offriamo anche la possibilità di acquistare i tuoi certificati SSL e di configurarli sul server MongoDB, e puoi inviare un'e-mail a [email protected] per saperne di più su questa offerta.
Connessione a un set di repliche utilizzando il driver Ruby MongoDB
Utilizzeremo l'ultimo driver stabile Ruby MongoDB versione 2.8 per questo esempio. Le versioni 2.5.x del driver hanno un bug noto che impedisce loro di lavorare con le distribuzioni ScaleGrid. La versione di Ruby utilizzata in entrambi gli esempi seguenti è la 2.6.3.
Le opzioni di connessione disponibili per il conducente sono documentate qui e le opzioni di cui avremo bisogno sono:
- :ssl
- :ssl_verify
- :ssl_ca_cert .
In primo luogo, trova e copia la stringa di connessione MongoDB dalla pagina dei dettagli del cluster sulla console ScaleGrid:
Il file del certificato CA è anche disponibile per il download dalla pagina dei dettagli del cluster. Scarica e archivia il file del certificato in una posizione disponibile per l'applicazione:
Ecco uno snippet che mostra come connettersi a un set di repliche MongoDB da Ruby:
require 'mongo'Mongo::Logger.logger.level =::Logger::DEBUGMONGODB_CA_CERT ="/path/to/ca_cert.pem"MONGODB_CONN_URL ="mongodb://testuser:@SG-example- 17026.servers.mongodirector.com:27017,SG-example-17027.servers.mongodirector.com:27017,SG-example-17028.servers.mongodirector.com:27017/test?replicaSet=RS-example-0&ssl=true" options ={ ssl:true, ssl_verify:true, :ssl_ca_cert => MONGODB_CA_CERT }client =Mongo::Client.new(MONGODB_CONN_URL, opzioni)db =client.databasecollections =db.collection_namesputs "db #{db.name} ha raccolte # {collezioni}"client.close
Per mantenere l'esempio semplice, abbiamo specificato la stringa di connessione e il percorso del file cert direttamente nello snippet di codice – generalmente li inserirai in un file yaml o li specificheresti come variabili ambientali. Inoltre, l'esempio imposta il livello di registro su DEBUG
in modo da poter eseguire il debug di eventuali problemi di connettività. Dovrebbe essere modificato a un livello meno dettagliato una volta risolti i problemi di connettività.
Come collegare MongoDB a un'applicazione Ruby con SSLClick To Tweet
Connessione tramite Mongoid
La versione mongoide che useremo nel nostro esempio è l'ultima versione stabile:7.0.2. Useremo un file yaml per fornire la configurazione a mongoid e i dettagli di tale file di configurazione sono documentati qui. Le opzioni di configurazione specifiche per SSL di cui avremo bisogno per connetterci al nostro set di repliche sono:
- ssl
- ssl_verify
- ssl_ca_cert
Il nostro file yml:
sviluppo:# Configura i client di database disponibili. client (obbligatorio):# Definire il client predefinito. (obbligatorio) default:# È possibile definire un uri per un client:# uri:'mongodb://user:[email protected]:27017/my_db' # Consultare la documentazione del driver per i dettagli. In alternativa, puoi definire quanto segue:# # Definire il nome del database predefinito a cui Mongoid può connettersi. # (necessario). database:test # Fornisce gli host a cui il client predefinito può connettersi. Deve essere un array # di coppie host:port. (richiesto) host:- SG-example-17026.servers.mongodirector.com:27017 - SG-example-17027.servers.mongodirector.com:27017 - SG-example-17028.servers.mongodirector.com:47100 opzioni:# Il nome dell'utente per l'autenticazione. utente:'testuser' # La password dell'utente per l'autenticazione. password:'pwd' # I ruoli del database dell'utente. ruoli:- 'readWrite' # Modifica il meccanismo di autenticazione predefinito. Le opzioni valide sono::scram, # :mongodb_cr, :mongodb_x509 e :plain. (l'impostazione predefinita su 3.0 è :scram, l'impostazione predefinita # su 2.4 e 2.6 è :plain) auth_mech::scram # Il database o l'origine su cui autenticare l'utente. (predefinito:admin) origine_auth:test # Forza il driver a connettersi in un modo specifico invece di # individuazione automatica. Può essere uno di::direct, :replica_set, :sharded. Impostare su :direct # quando ci si connette a membri nascosti di un set di repliche. connect::replica_set ... ... # Il nome del set di repliche a cui connettersi. I server forniti come seed che # non appartengono a questo set di repliche verranno ignorati. set_replica:RS-example-0 # Se connettersi ai server tramite ssl. (predefinito:falso) ssl:vero # Se eseguire o meno la convalida della certificazione peer. (predefinito:vero) ssl_verify:vero # Il file contenente una serie di certificazioni concatenate dell'autorità di certificazione # utilizzato per convalidare i certificati passati dall'altra estremità della connessione. ssl_ca_cert:/percorso/a/ca_cert.pem # Configura le opzioni specifiche di Mongoid. (opzionale) opzioni:# Imposta i livelli di registro dei driver Mongoid e Ruby. (predefinito::info) log_level::debug
Esempio di connessione:
gem 'mongoid', '7.0.2'require 'mongoid'Mongoid.load!("/path/to/mongoid.yml", :development)# Non si utilizza nessuna delle funzionalità ODM:basta recuperare il mongo sottostante client e tenta di connettersiclient =Mongoid::Clients.defaultdb =client.databasecollections =db.collection_namesputs "db #{db.name} ha raccolte #{collezioni}"Mongoid::Clients.disconnect
Di nuovo, nelle applicazioni Ruby on Rails di produzione, il percorso del file yaml verrebbe prelevato dalle variabili di ambiente.
Test del comportamento di failover
Come altri driver MongoDB, anche il driver Ruby MongoDB è progettato per riconoscere internamente i cambiamenti nella topologia dovuti a eventi come il failover. Tuttavia, è bene testare e convalidare il comportamento del driver durante i failover per evitare sorprese in produzione.
Come il mio precedente post su MongoDB PyMongo, possiamo scrivere un programma di test di scrittura perpetuo per osservare il comportamento di failover del driver.
Il modo più semplice per indurre il failover è eseguire il comando rs.stepDown():
RS-example-0:PRIMARY> rs.stepDown()2019-04-18T19:44:42.257+0530 E QUERY [thread1] Errore:errore durante l'esecuzione della query:non riuscita:errore di rete durante il tentativo di eseguire il comando 'replSetStepDown' sull'host 'SG-example-1.servers.mongodirector.com:27017' :DB.prototype.runCommand@src/mongo/shell/db.js:168:1DB.prototype.adminCommand@src/mongo/shell/db. js:185:1rs.stepDown@src/mongo/shell/utils.js:1305:12@(shell):1:12019-04-18T19:44:42.261+0530 I NETWORK [thread1] provando a riconnettersi a SG-example -1.servers.mongodirector.com:27017 (X.X.X.X) non riuscito2019-04-18T19:44:43.267+0530 I RETE [thread1] ricollega SG-example-1.servers.mongodirector.com:27017 (X.X.X.X) okRS-example- 0:SECONDARIO>
Ecco le parti rilevanti del nostro codice di test:
richiedi 'mongo'...logger =Logger.new(STDOUT)logger.level =Logger::INFOMONGODB_CA_CERT ="/path/to/ca_cert.pem"MONGODB_CONN_URL ="mongodb://testuser:@ SG-example-17026.servers.mongodirector.com:27017,SG-example-17027.servers.mongodirector.com:27017,SG-example-17028.servers.mongodirector.com:27017/test?replicaSet=RS-example- 0&ssl=true"options ={ ssl:true, ssl_verify:true, :ssl_ca_cert => MONGODB_CA_CERT }begin logger.info("Tentativo di connessione...") client =Mongo::Client.new(MONGODB_CONN_URL, opzioni) i =0 loop do db =client.database collection =db[:test] begin doc ={"idx":i, "date":DateTime.now, "text":SecureRandom.base64(3) } result =collection.insert_one( doc) logger.info("Record inserito - id:#{result.inserted_id}") i +=1 sleep(3) rescue Mongo::Error => e logger.error("Errore Mong visto:#{e.message }") logger.error(e.backtrace) logger.i nfo("Riprova in corso...") end end logger.info("Fatto")rescue => err logger.error("Eccezione vista:#{err.message}") logger.error(err.backtrace)assicura client. chiudere a meno che client.nil?end
Questo scrive continuamente voci come queste nella raccolta di test sul database di test:
RS-test-0:PRIMARY> db.test.find(){ "_id" :ObjectId("5cf50ff1896cd172a4f7c6ee"), "idx" :0, "date" :ISODate("2019-06-03T12:17 :53.008Z"), "text" :"HTvd" }{ "_id":ObjectId("5cf50ff6896cd172a4f7c6ef"), "idx" :1, "date" :ISODate("2019-06-03T12:17:58.697Z" ), "text" :"/e5Z" }{ "_id" :ObjectId("5cf50ff9896cd172a4f7c6f0"), "idx" :2, "date" :ISODate("2019-06-03T12:18:01.940Z"), " text" :"quuw" }{ "_id" :ObjectId("5cf50ffd896cd172a4f7c6f1"), "idx" :3, "date" :ISODate("2019-06-03T12:18:05.194Z"), "text" :" gTyY" }{ "_id" :ObjectId("5cf51000896cd172a4f7c6f2"), "idx" :4, "date" :ISODate("2019-06-03T12:18:08.442Z"), "text" :"VDXX" }{ "_id" :ObjectId("5cf51003896cd172a4f7c6f3"), "idx" :5, "date" :ISODate("2019-06-03T12:18:11.691Z"), "text" :"UY87"}...
Vediamo il comportamento durante un failover:
I, [2019-06-03T17:53:25.079829 #9464] INFO -- :Tentativo di connessione...I, [2019-06-03T17:53:30.577099 #9464] INFO -- :Record inserito - id:5cf5113f896cd124f8f31062I, [2019-06-03T17:53:33.816528 #9464] INFO -- :Record inserito - id:5cf51145896cd124f8f31063I, [2019-06-03T17:53:33 Record inserito - 96704] 5cf51148896cd124f8f31064I, [2019-06-03T17:53:40.281537 #9464] INFO -- :Record inserted - id:5cf5114c896cd124f8f31065I, [2019-06-03T17:53:43.520010 #9464] INFO -- :Record inserted - id:5cf5114f896cd124f8f31066I, [2019-06-03T17:53:46.747080 #9464] INFO -- :Record inserito - id:5cf51152896cd124f8f31067I, [2019-06-03T17:53:49.978077 #9464] INFO -- :Record inserito - id:5cf511124<896c Failover avviato quiE, [2019-06-03T17:53:52.980434 #9464] ERRORE -- :Errore Mong:EOFError:fine del file raggiunto (per x.x.x.x:27017 (sg-example-17026.servers.mongodirector.com:27017 , TLS))E, [2019-06-03T17:53:52.980533 #9464] ERRORE -- :["C:/Ruby 26-x64/lib/ruby/gems/2.6.0/gems/mongo-2.8.0/lib/mongo/socket.rb:300:in `rescue in handle_errors'", "C:/Ruby26-x64/lib/ ruby/gems/2.6.0/gems/mongo-2.8.0/lib/mongo/socket.rb:294:in `handle_errors'", "C:/Ruby26-x64/lib/ruby/gems/2.6.0/ gemme/mongo-2.8.0/lib/mongo/socket.rb:126:in `read'", "C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/mongo-2.8.0/ lib/mongo/protocol/message.rb:139:in `deserialize'",......I, [2019-06-03T17:53:52.980688 #9464] INFO -- :Nuovo tentativo...W, [ 2019-06-03T17:53:52.981575 #9464] WARN -- :Nuovo tentativo di ismaster su sg-example-17026.servers.mongodirector.com:27017 a causa di:Mongo::Error::SocketError EOFError:fine del file raggiunto (per x.x.x.x:27017 (sg-example-17026.servers.mongodirector.com:27017, TLS))I, [2019-06-03T17:54:06.293100 #9464] INFO -- :Record inserito - id:5cf51163896cd124f8f3106aI, [2019- 06-03T17:54:09.547716 #9464] INFO -- :Record inserito - id:5cf51169896cd124f8f3106bI, [2019-06-03T17:54:12.806636 #9464] INFO -- :Record inserito - id:5cf5116c896fd3106c896cd124f8 ri>È evidente che se vengono rilevati gli errori corretti e si esegue un nuovo tentativo di lettura/scrittura, il driver rileverà automaticamente la modifica della topologia e si ricollegherà al nuovo master. Per le scritture, l'opzione :retry_writes assicurarsi che il driver riprovi una volta da solo prima di notificare un errore all'applicazione.
Ci sono anche più timeout del driver che possono essere modificati in base al comportamento esatto e alla latenza che vedi sulla tua configurazione. Questi sono documentati qui.
Risoluzione dei problemi
Se hai problemi a connetterti alla tua distribuzione MongoDB abilitata per SSL, ecco alcuni suggerimenti per il debug:
- In primo luogo, verifica di poterti effettivamente connettere al server MongoDB dal server in cui è in esecuzione l'applicazione. Il modo più semplice per farlo è installare mongo shell sul computer client. Su Linux, non avresti bisogno di installare l'intero server MongoDB:puoi scegliere di installare semplicemente la shell separatamente. Una volta che la shell è disponibile, prova a utilizzare la "Sintassi della riga di comando" fornita per tentare di connetterti al server.
- Se non riesci a connetterti tramite la shell mongo, significa che la macchina client non è in grado di raggiungere la porta 27017 dei server MongoDB. Esamina le impostazioni del tuo gruppo di sicurezza, VPC e firewall ScaleGrid per assicurarti che ci sia connettività tra le macchine client e server.
- Se la connettività di rete è corretta, la prossima cosa da controllare è che stai usando versioni di Ruby, mongoid e mongo gem compatibili con la versione del tuo server MongoDB.
- Se hai confermato che le versioni del driver sono corrette, prova a eseguire uno script Ruby di esempio, simile all'esempio fornito sopra, sull'IRB. Un'esecuzione passo passo potrebbe indicare dove si trova il problema.
- Se lo script di test funziona correttamente, ma non riesci ancora a connetterti con mongoid, prova a eseguire un semplice script di test, come l'esempio fornito sopra .
- Se hai ancora problemi di connessione alla tua istanza, scrivici a [email protected] con i risultati dettagliati della procedura di risoluzione dei problemi sopra e con le versioni esatte dei driver Ruby, mongoid e mongo che stai utilizzando. Gemfile.lock ti fornirà le versioni esatte.
Se non conosci ScaleGrid e vuoi provare questo tutorial, registrati per una prova gratuita di 30 giorni per esplorare la piattaforma e provare connettendo MongoDB alla tua applicazione Ruby.