Với sự phổ biến của bài đăng của chúng tôi về việc kết nối MongoDB SSL với Chứng chỉ tự ký trong Node.js, chúng tôi quyết định viết một hướng dẫn về cách kết nối MongoDB với Ruby. Trong blog này, chúng tôi sẽ hướng dẫn bạn cách kết nối với máy chủ MongoDB được định cấu hình với chứng chỉ tự ký cho SSL bằng cách sử dụng cả trình điều khiển Ruby MongoDB và mongoid Object-Document-Mapper (ODM).
ScaleGrid hiện đang sử dụng chứng chỉ tự ký cho SSL khi tạo các nút cho một cụm mới. Ngoài ra, chúng tôi cũng cung cấp cho bạn tùy chọn mua chứng chỉ SSL của riêng bạn và định cấu hình chúng trên máy chủ MongoDB và bạn có thể gửi email tới [email protected] để tìm hiểu thêm về ưu đãi này.
Kết nối với bộ bản sao bằng trình điều khiển Ruby MongoDB
Chúng tôi sẽ sử dụng trình điều khiển Ruby MongoDB ổn định mới nhất phiên bản 2.8 cho ví dụ này. Các phiên bản 2.5.x của trình điều khiển có một lỗi đã biết ngăn chúng hoạt động với các triển khai ScaleGrid. Phiên bản Ruby được sử dụng trong cả hai ví dụ dưới đây là 2.6.3.
Các tùy chọn kết nối có sẵn cho trình điều khiển được ghi lại ở đây và các tùy chọn chúng tôi sẽ cần là:
- :ssl
- :ssl_verify
- :ssl_ca_cert .
Trước tiên, hãy tìm và sao chép chuỗi kết nối MongoDB của bạn từ trang chi tiết cụm trên bảng điều khiển ScaleGrid:
Tệp chứng chỉ CA cũng có sẵn để tải xuống từ trang chi tiết cụm. Tải xuống và lưu trữ tệp chứng chỉ tại một vị trí có sẵn cho ứng dụng:
Đây là đoạn mã hướng dẫn cách kết nối với bộ bản sao MongoDB từ Ruby:
request '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, options) db =client.databasecollections =db.collection_namesputs "db # {db.name" {collection} "client.close
Để giữ cho ví dụ đơn giản, chúng tôi đã chỉ định chuỗi kết nối và đường dẫn tệp chứng chỉ trực tiếp trong đoạn mã - thông thường bạn sẽ đặt chúng vào tệp yaml hoặc chỉ định chúng là các biến môi trường. Ngoài ra, ví dụ này đặt cấp độ nhật ký thành DEBUG
để có thể gỡ lỗi bất kỳ sự cố kết nối nào. Nó sẽ được thay đổi thành mức ít chi tiết hơn sau khi các vấn đề kết nối đã được giải quyết.
Cách kết nối MongoDB với ứng dụng Ruby bằng SSLClick To Tweet
Kết nối bằng Mongoid
Phiên bản mongoid mà chúng tôi sẽ sử dụng trong ví dụ của mình là phiên bản ổn định mới nhất - 7.0.2. Chúng tôi sẽ sử dụng tệp yaml để cung cấp cấu hình cho mongoid và chi tiết của tệp cấu hình như vậy được ghi lại ở đây. Các tùy chọn cấu hình dành riêng cho SSL mà chúng tôi sẽ cần để kết nối với tập hợp bản sao của chúng tôi là:
- ssl
- ssl_verify
- ssl_ca_cert
Tệp yml của chúng tôi:
phát triển:# Định cấu hình các máy khách cơ sở dữ liệu có sẵn. (bắt buộc) máy khách:# Xác định máy khách mặc định. (bắt buộc) mặc định:# Một uri có thể được xác định cho một ứng dụng khách:# uri:'mongodb:// user:[email protected]:27017 / my_db' # Vui lòng xem tài liệu trình điều khiển để biết chi tiết. Ngoài ra, bạn có thể xác định như sau:# # Xác định tên của cơ sở dữ liệu mặc định mà Mongoid có thể kết nối. # (cần thiết). database:test # Cung cấp các máy chủ mà máy khách mặc định có thể kết nối. Phải là một mảng # các cặp máy chủ:cổng. (bắt buộc) máy chủ:- SG-example-17026.servers.mongodirector.com:27017 - SG-example-17027.servers.mongodirector.com:27017 - SG-example-17028.servers.mongodirector.com:47100 tùy chọn:# Tên của người dùng để xác thực. người dùng:'testuser' # Mật khẩu của người dùng để xác thực. mật khẩu:'pwd' # Vai trò cơ sở dữ liệu của người dùng. role:- 'readWrite' # Thay đổi cơ chế xác thực mặc định. Các tùy chọn hợp lệ là::scram, #:mongodb_cr,:mongodb_x509 và:trơn. (mặc định trên 3.0 là:scram, mặc định # trên 2.4 và 2.6 là:trơn) auth_mech::scram # Cơ sở dữ liệu hoặc nguồn để xác thực người dùng dựa vào. (default:admin) auth_source:test # Buộc trình điều khiển kết nối theo một cách cụ thể thay vì tự động phát hiện. Có thể là một trong số::direct,:replica_set,:sharded. Đặt thành:direct # khi kết nối với các thành viên ẩn của tập hợp bản sao. kết nối::replica_set ... ... # Tên của tập hợp bản sao cần kết nối. Máy chủ được cung cấp dưới dạng hạt giống # không thuộc tập hợp bản sao này sẽ bị bỏ qua. replica_set:RS-example-0 # Có kết nối với máy chủ qua ssl hay không. (mặc định:false) ssl:true # Có hay không thực hiện xác nhận chứng nhận ngang hàng. (mặc định:true) ssl_verify:true # Tệp chứa một tập hợp các chứng chỉ của tổ chức cung cấp dịch vụ chứng nhận được kết hợp # được sử dụng để xác nhận các chứng chỉ được chuyển từ đầu kia của kết nối. ssl_ca_cert:/path/to/ca_cert.pem # Định cấu hình các tùy chọn cụ thể của Mongoid. (tùy chọn) tùy chọn:# Đặt cấp độ nhật ký trình điều khiển Mongoid và Ruby. (default::info) log_level::debug
Ví dụ về kết nối:
gem 'mongoid', '7.0.2'require' mongoid'Mongoid.load! ("/ path / to / mongoid.yml",:development) # Không sử dụng bất kỳ tính năng ODM nào - chỉ tìm nạp mongo bên dưới máy khách và cố gắng kết nối với connectclient =Mongoid ::Clients.defaultdb =client.databasecollections =db.collection_namesputs "db # {db.name} có các bộ sưu tập # {collection}" Mongoid ::Clients.disconnect
Một lần nữa, trong ứng dụng Ruby on Rails sản xuất, đường dẫn tệp yaml sẽ được chọn từ các biến môi trường.
Kiểm tra hành vi chuyển đổi dự phòng
Giống như các trình điều khiển MongoDB khác, trình điều khiển Ruby MongoDB cũng được thiết kế để nhận biết nội bộ các thay đổi trong cấu trúc liên kết do các sự kiện như chuyển đổi dự phòng. Tuy nhiên, tốt hơn hết là bạn nên kiểm tra và xác nhận hành vi của người lái xe trong quá trình chuyển động dự phòng để tránh những bất ngờ trong quá trình sản xuất.
Giống như bài đăng trước của tôi trên MongoDB PyMongo, chúng tôi có thể viết một chương trình kiểm tra người viết vĩnh viễn để quan sát hành vi chuyển đổi dự phòng của trình điều khiển.
Cách dễ nhất để thực hiện chuyển đổi dự phòng là chạy lệnh rs.stepDown ():
RS-example-0:PRIMARY> rs.stepDown () 2019-04-18T19:44:42.257 + 0530 E QUERY [thread1] Error:error doing query:failed:lỗi mạng khi cố gắng chạy lệnh 'replSetStepDown' trên máy chủ '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] đang thử kết nối lại với SG-example -1.servers.mongodirector.com:27017 (X.X.X.X) failed2019-04-18T19:44:43.267 + 0530 I NETWORK [thread1] kết nối lại SG-example-1.servers.mongodirector.com:27017 (X.X.X.X) okRS-example- 0:SECONDARY>
Dưới đây là các phần có liên quan trong mã thử nghiệm của chúng tôi:
request '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 (" Đang cố kết nối ... ") client =Mongo ::Client.new (MONGODB_CONN_URL, options) 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 ("Đã chèn bản ghi - id:# {result.inserted_id}") i + =1 sleep (3) cứu Mongo ::Error => e logger.error ("Đã thấy lỗi Mongo:# {e.message } ") logger.error (e.backtrace) logger.i nfo ("Đang thử lại ...") end end logger.info ("Xong") cứu => err logger.error ("Đã thấy ngoại lệ:# {err.message}") logger.error (err.backtrace) đảm bảo khách hàng. đóng trừ khi client.nil? end
Thao tác này liên tục ghi các mục như thế này vào bộ sưu tập thử nghiệm trên cơ sở dữ liệu thử nghiệm:
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"} ...Hãy xem hành vi trong quá trình chuyển đổi dự phòng:
I, [2019-06-03T17:53:25.079829 # 9464] INFO -:Đang cố kết nối ... I, [2019-06-03T17:53:30.577099 # 9464] INFO -:Đã chèn bản ghi - id:5cf5113f896cd124f8f31062I, [2019-06-03T17:53:33.816528 # 9464] INFO -:Đã chèn bản ghi - id:5cf51145896cd124f8f31063I, [2019-06-03T17:53:37.047043 # 9464] Đã chèn thêm idO -:5cf51148896cd124f8f31064I, [2019-06-03T17:53:40.281537 # 9464] INFO -:Đã chèn bản ghi - id:5cf5114c896cd124f8f31065I, [2019-06-03T17:53:43.520010 # 9464] INFO -:Đã chèn bản ghi - id:5896fcd5114f8 [2019-06-03T17:53:46.747080 # 9464] INFO -:Đã chèn bản ghi - id:5cf51152896cd124f8f31067I, [2019-06-03T17:53:49.978077 # 9464] INFO -:Đã chèn bản ghi - id:5cf51155896cd124f8f31068 <<<Đã bắt đầu chuyển đổi dự phòng tại đâyE, [2019-06-03T17:53:52.980434 # 9464] LỖI -:Đã thấy lỗi Mong:EOFError:đạt đến cuối tệp (đối với x.x.x.x:27017 (sg-example-17026.servers.mongodirector.com:27017 , TLS)) E, [2019-06-03T17:53:52.980533 # 9464] LỖI -:["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/ gems / 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 -:Đang thử lại ... W, [ 2019-06-03T17:53:52.981575 # 9464] CẢNH BÁO -:Đang thử lại ismaster trên sg-example-17026.servers.mongodirector.com:27017 do:Mongo ::Error ::SocketError EOFError:đã đến cuối tệp (cho x.x.x.x:27017 (sg-example-17026.servers.mongodirector.com:27017, TLS)) I, [2019-06-03T17:54:06.293100 # 9464] INFO -:Đã chèn bản ghi - id:5cf51163896cd124f8f3106aI, [2019- 06-03T17:54:09.547716 # 9464] INFO -:Đã chèn bản ghi - id:5cf51169896cd124f8f3106bI, [2019-06-03T17:54:12.806636 # 9464] INFO -:Đã chèn bản ghi - id:5cf5116c896cd124f8f3106cRõ ràng là nếu bắt được lỗi đúng và thử đọc / ghi lại, trình điều khiển sẽ tự động phát hiện sự thay đổi cấu trúc liên kết và kết nối lại với trang chủ mới. Để ghi, tùy chọn :retry_writes đảm bảo rằng trình điều khiển sẽ tự thử lại một lần trước khi thông báo lỗi cho ứng dụng.
Ngoài ra còn có nhiều thời gian chờ trình điều khiển có thể được điều chỉnh dựa trên hành vi và độ trễ chính xác mà bạn thấy trên thiết lập của mình. Những điều này được ghi lại ở đây.
Khắc phục sự cố
Nếu bạn gặp sự cố khi kết nối với triển khai MongoDB có hỗ trợ SSL của mình, đây là một số mẹo để gỡ lỗi:
- Trước tiên, hãy xác minh rằng bạn thực sự có thể kết nối với máy chủ MongoDB từ máy chủ nơi ứng dụng của bạn đang chạy. Cách đơn giản nhất để thực hiện việc này là cài đặt mongo shell trên máy khách. Trên Linux, bạn không cần phải cài đặt toàn bộ máy chủ MongoDB - bạn có thể chọn chỉ cài đặt shell riêng. Sau khi shell khả dụng, hãy thử sử dụng 'Cú pháp dòng lệnh' mà chúng tôi cung cấp để cố gắng kết nối với máy chủ.
- Nếu bạn không thể kết nối qua mongo shell, điều đó có nghĩa là máy khách không thể truy cập cổng 27017 của máy chủ MongoDB. Xem xét cài đặt tường lửa Nhóm bảo mật, VPC và ScaleGrid của bạn để đảm bảo rằng có kết nối giữa máy khách và máy chủ.
- Nếu kết nối mạng chính xác, điều tiếp theo cần kiểm tra là bạn đang sử dụng các phiên bản Ruby, mongoid và mongo gem tương thích với phiên bản của máy chủ MongoDB của bạn.
- Nếu bạn đã xác nhận rằng phiên bản trình điều khiển là chính xác, hãy thử chạy tập lệnh Ruby mẫu, tương tự như ví dụ chúng tôi đã cung cấp ở trên, trên IRB. Quá trình thực thi từng bước có thể chỉ ra vấn đề ở đâu.
- Nếu tập lệnh thử nghiệm chạy tốt nhưng bạn vẫn không thể kết nối với mongoid, hãy thử chạy một tập lệnh thử nghiệm đơn giản, như ví dụ chúng tôi đã cung cấp ở trên .
- Nếu bạn vẫn gặp sự cố khi kết nối với phiên bản của mình, vui lòng viết thư cho chúng tôi theo địa chỉ [email protected] với kết quả chi tiết của các bước khắc phục sự cố ở trên và với phiên bản chính xác của trình điều khiển Ruby, mongoid và mongo mà bạn đang sử dụng. Gemfile.lock sẽ cung cấp cho bạn các phiên bản chính xác.
Nếu bạn chưa quen với ScaleGrid và muốn dùng thử hướng dẫn này, hãy đăng ký bản dùng thử miễn phí 30 ngày để khám phá nền tảng và thử nghiệm kết nối MongoDB với ứng dụng Ruby của bạn.