Като се има предвид популярността на публикацията ни за свързване MongoDB SSL със самоподписани сертификати в Node.js, решихме да напишем урок за свързване на MongoDB с Ruby. В този блог ще ви покажем как да се свържете със сървър на MongoDB, конфигуриран със самоподписани сертификати за SSL, като използвате както драйвера Ruby MongoDB, така и популярния монгоид на Object-Document-Mapper (ODM).
ScaleGrid понастоящем използва самоподписани сертификати за SSL, когато създава възли за нов клъстер. Освен това ви предоставяме и възможността да закупите свои собствени SSL сертификати и да ги конфигурирате на сървъра на MongoDB и можете да изпратите имейл на [email protected], за да научите повече за тази оферта.
Свързване към набор от реплики с помощта на Ruby MongoDB драйвер
Ще използваме най-новия стабилен драйвер на Ruby MongoDB версия 2.8 за този пример. Версиите 2.5.x на драйвера имат известна грешка, която им пречи да работят с внедряванията на ScaleGrid. Версията на Ruby, използвана и в двата примера по-долу, е 2.6.3.
Опциите за свързване, налични за драйвера, са документирани тук, а опциите, от които ще се нуждаем, са:
- :ssl
- :ssl_verify
- :ssl_ca_cert .
Първо намерете и копирайте своя низ за връзка с MongoDB от страницата с подробности за клъстера в конзолата ScaleGrid:
Файлът на CA сертификата също е достъпен за изтегляне от страницата с подробности за клъстера. Изтеглете и съхранявайте сертификатния файл на място, което е достъпно за приложението:
Ето фрагмент, показващ как да се свържете с комплект реплики на MongoDB от Ruby:
изисква '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=0true&ss options ={ ssl:true, ssl_verify:true, :ssl_ca_cert => MONGODB_CA_CERT }client =Mongo::Client.new(MONGODB_CONN_URL, options)db =client.databasecollections =db.collection_namesputs #.name} има колекция "db} {collections}"client.close
За да запазим примера прост, ние посочихме низа за връзка и пътя на сертификатния файл директно в кодовия фрагмент – обикновено или ще ги поставите в yaml файл, или ще ги посочите като променливи на средата. Също така, примерът задава нивото на регистрационния файл на DEBUG
така че всички проблеми със свързаността да могат да бъдат отстранени. Трябва да се промени на по-малко подробно ниво, след като проблемите със свързаността бъдат отстранени.
Как да свържете MongoDB към Ruby приложение с SSLClick To Tweet
Свързване чрез Mongoid
Монгоидната версия, която ще използваме в нашия пример, е най-новата стабилна версия – 7.0.2. Ще използваме yaml файл, за да предоставим конфигурация на mongoid, а подробностите за такъв конфигурационен файл са документирани тук. Специфичните за SSL конфигурационни опции, които ще трябва да се свържем с нашия набор от реплики, са:
- ssl
- ssl_verify
- ssl_ca_cert
Нашият yml файл:
разработка:# Конфигурирайте наличните клиенти на базата данни. (задължителни) клиенти:# Дефинирайте клиента по подразбиране. (задължително) по подразбиране:# uri може да бъде дефиниран за клиент:# uri:'mongodb://user:[email protected]:27017/my_db' # Моля, вижте документацията на драйвера за подробности. Като алтернатива можете да дефинирате следното:# # Дефинирайте името на базата данни по подразбиране, към която Mongoid може да се свързва. # (задължително). база данни:тест # Предоставяне на хостовете, към които клиентът по подразбиране може да се свърже. Трябва да е масив # от двойки хост:порт. (задължително) хостове:- SG-example-17026.servers.mongodirector.com:27017 - SG-example-17027.servers.mongodirector.com:27017 - SG-example-17028.servers.mongodirector.com:471 опции:# Името на потребителя за удостоверяване. потребител:'testuser' # Паролата на потребителя за удостоверяване. парола:'pwd' # Ролите на потребителската база данни. roles:- 'readWrite' # Променете механизма за удостоверяване по подразбиране. Валидни опции са::scram, # :mongodb_cr, :mongodb_x509 и :plain. (по подразбиране за 3.0 е :scram, # по подразбиране за 2.4 и 2.6 е :plain) auth_mech::scram # Базата данни или източникът, срещу който се удостоверява потребителят. (по подразбиране:администратор) auth_source:тест # Принуди драйвера да се свърже по специфичен начин вместо автоматично # откриване. Може да бъде един от::direct, :replica_set, :sharded. Задайте на :direct #, когато се свързвате със скрити членове на набор от реплика. connect::replica_set ... ... # Името на набора реплика, към който да се свържете. Сървърите, предоставени като семена, които # не принадлежат към този набор от реплики, ще бъдат игнорирани. набор_реплика:RS-пример-0 # Дали да се свържете със сървърите чрез ssl. (по подразбиране:false) ssl:true # Дали да се направи или не валидиране на партньорски сертификати. (по подразбиране:вярно) ssl_verify:вярно # Файлът, съдържащ набор от конкатенирани сертификати от # сертифициращ орган, използвани за валидиране на сертификати, предадени от другия край на връзката. ssl_ca_cert:/път/до/ca_cert.pem # Конфигурирайте специфични за Mongoid опции. (по избор) опции:# Задайте нивата на регистрационния файл на драйвера Mongoid и Ruby. (по подразбиране::info) log_level::debug
Пример за връзка:
gem 'mongoid', '7.0.2'require 'mongoid'Mongoid.load!("/path/to/mongoid.yml", :development)# Не се използва нито една от функциите на ODM - просто извлечете основното mongo клиент и се опитайте да се свържетеclient =Mongoid::Clients.defaultdb =client.databasecollections =db.collection_namesputs "db #{db.name} има колекции #{collections}"Mongoid::Clients.disconnect
Отново, в производствените Ruby on Rails приложения, пътят на yaml файла ще бъде извлечен от променливите на средата.
Тестване на поведение при отказ
Подобно на други драйвери на MongoDB, драйверът на Ruby MongoDB също е проектиран да разпознава вътрешно промените в топологията, дължащи се на събития като отказване. Въпреки това е добре да се тества и потвърди поведението на драйвера по време на отказ, за да се избегнат изненади в производството.
Както предишната ми публикация в MongoDB PyMongo, ние можем да напишем вечна програма за тестване на писател, за да наблюдаваме поведението на драйвера при отказ при отказ.
Най-лесният начин да предизвикате отказ е да изпълните командата rs.stepDown():
RS-example-0:PRIMARY> rs.stepDown()2019-04-18T19:44:42.257+0530 E QUERY [thread1] Грешка:грешка при извършване на заявка:неуспешна:грешка в мрежата при опит за изпълнение на командата 'replSetStepDown' на хост „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] опитвам се да се свържа отново към SG-example -1.servers.mongodirector.com:27017 (X.X.X.X) неуспешно2019-04-18T19:44:43.267+0530 I NETWORK [thread1] reconnect SG-example-1.servers.mongodirector.com:27017 (X.X.ex.) 0:ВТОРИЧНО>
Ето съответните части от нашия тестов код:
изисква '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("Опит за свързване...") client =Mongo::Client.new(MONGODB_CONN_URL, опции) i =0 цикъл do db =client.database collection =db[:test] begin doc ={"idx":i, "date":DateTime.now, "text":SecureRandom.base64(3) } резултат =collection.insert_one( doc) logger.info("Записът е вмъкнат - id:#{result.inserted_id}") i +=1 sleep(3) rescue Mongo::Error => e logger.error("Mong Грешка е видяна:#{e.message }") logger.error(e.backtrace) logger.i nfo("Retrying...") end end logger.info("Done")rescue => err logger.error("Виждано изключение:#{err.message}") logger.error(err.backtrace)enure client. затворете, освен ако client.nil?end
Това непрекъснато записва записи като тези в тестовата колекция в тестовата база данни:
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, "дата" :ISODate("2019-06-03T12:17:58" ), "text" :"/e5Z" }{ "_id" :ObjectId("5cf50ff9896cd172a4f7c6f0"), "idx" :2, "date" :ISODate("2019-06-03T12:18:01.940Z"), " text" :"quuw" }{ "_id" :ObjectId("5cf50ffd896cd172a4f7c6f1"), "idx" :3, "дата" :ISODate("2019-06-03T12:18:05.194Z:"), "text gTyY" }{ "_id" :ObjectId("5cf51000896cd172a4f7c6f2"), "idx" :4, "дата" :ISODate("2019-06-03T12:18:08.442Z"), "DXX" :" "_id" :ObjectId("5cf51003896cd172a4f7c6f3"), "idx" :5, "дата" :ISODate("2019-06-03T12:18:11.691Z"), "текст":"UY87" предварително>Нека видим поведението по време на отказ:
I, [2019-06-03T17:53:25.079829 #9464] ИНФОРМАЦИЯ -- :Опит за свързване...I, [2019-06-03T17:53:30.577099 #9464] ИНФО -- :Записът е вмъкнат - id:5cf5113f896cd124f8f31062I, [2019-06-03T17:53:33.816528 #9464] ИНФОРМАЦИЯ -- :Записът е вмъкнат - id:5cf51145896cd124f31062I:Записът е вмъкнат:5cf51145896cd124f31062I:Записът е вмъкнат:5cf51145896cd124f3106:04 INFO:04 INFO 04 -04 -04 -04 -04 -071 -04 -04 -04 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] ИНФОРМАЦИЯ -- :Записът е вмъкнат - идентификатор:5cf51152896cd124f8f31067I, [2019-06-03T17:53:49.976] Вмъкнат запис - 17:53:49.987 <Очевидно е, че ако бъдат уловени правилни грешки и се опита отново да чете/записва, драйверът автоматично ще открие промяната на топологията и ще се свърже отново с новия главен файл. За записи опцията :retry_writes уверете се, че драйверът ще опита отново веднъж сам, преди да уведоми приложението за грешка.
Има също множество изчаквания на драйвери, които могат да бъдат настроени въз основа на точното поведение и латентност, които виждате при настройката си. Те са документирани тук.
Отстраняване на неизправности
Ако имате проблеми с свързването с внедряването на MongoDB с активиран SSL, ето няколко съвета за отстраняване на грешки:
- Първо, проверете дали наистина можете да се свържете със сървъра на MongoDB от сървъра, на който се изпълнява вашето приложение. Най-простият начин да направите това е да инсталирате mongo shell на клиентската машина. В Linux няма да е необходимо да инсталирате целия сървър MongoDB – можете да изберете просто да инсталирате обвивката отделно. След като обвивката е налична, опитайте да използвате „Синтаксис на командния ред“, който предоставяме, за да опитате да се свържете със сървъра.
- Ако не можете да се свържете чрез mongo shell, това означава, че клиентската машина не може да достигне до порт 27017 на сървърите на MongoDB. Вижте настройките на вашата група за сигурност, VPC и защитна стена ScaleGrid, за да се уверите, че има свързаност между клиентските и сървърните машини.
- Ако мрежовата свързаност е правилна, следващото нещо, което трябва да проверите, е дали използвате версии на Ruby, mongoid и mongo gem, които са съвместими с версията на вашия MongoDB сървър.
- Ако сте потвърдили, че версиите на драйвера са правилни, опитайте да изпълните примерен Ruby скрипт, подобен на примера, който предоставихме по-горе, на IRB. Изпълнението стъпка по стъпка може да посочи къде е проблемът.
- Ако тестовият скрипт работи добре, но все още не можете да се свържете с mongoid, опитайте се да изпълните прост тестов скрипт, като примера, който предоставихме по-горе .
- Ако все още имате проблеми със свързването с вашия екземпляр, моля, пишете ни на [email protected] с подробни резултати от горните стъпки за отстраняване на неизправности и с точните версии на Ruby, mongoid и mongo драйвер, който използвате. Gemfile.lock ще ви предостави точните версии.
Ако сте нов в ScaleGrid и искате да опитате този урок, регистрирайте се за безплатен 30-дневен пробен период, за да разгледате платформата и да тествате свързване на MongoDB с вашето Ruby приложение.