Kết nối PostgreSQL với Node.js và tự động kết nối lại khi mất kết nối và khôi phục.

Tram Ho

Khi môi trường vùng chứa trở nên phổ biến hơn, bạn có thể nghe thấy rằng các ứng dụng và dịch vụ có thể hoạt động ổn định hơn. Mặc dù điều đó đúng ở một mức độ nào đó, nhưng điều quan trọng là phải có các hệ thống phụ trợ ổn định để ứng dụng hoạt động ổn định và khía cạnh này thường bị bỏ qua. Mục blog này sẽ đưa ra một ví dụ về cuộc thảo luận như vậy bằng cách giới thiệu những điểm cần được xem xét khi sử dụng cơ sở dữ liệu quan hệ (trong trường hợp này là PostgreSQL) trong một ứng dụng sử dụng Node.js.

Có thể dễ dàng triển khai mã để kết nối từ Node.js đến PostgreSQL bằng cách sử dụng gói npm có tên là “node-postgres”. Các phương pháp cụ thể cũng có thể dễ dàng tìm thấy bằng cách tìm kiếm trực tuyến.

Mặt khác, tôi nghĩ rằng các thiết kế dựa trên microservice đang trở nên phổ biến hơn, đặc biệt là trong môi trường đám mây hoặc vùng chứa. Trong những trường hợp như vậy, cần lường trước rằng “PostgreSQL có thể chuyển sang chế độ bảo trì (có thể mất kết nối).” Là một ứng dụng, nó yêu cầu triển khai hơi rắc rối hoạt động như “có khả năng kết nối cơ sở dữ liệu có thể bị ngắt kết nối và nếu bị ngắt kết nối, nó sẽ kết nối lại (và tiếp tục kết nối lại nếu không thành công)”.

hình ảnh.png

Tôi đang tìm kiếm một mã mẫu có thể hoạt động cụ thể, nhưng tôi không thể tìm thấy mã đó một cách chính xác, vì vậy tôi đã thử nhiều cách khác nhau và tự tạo mã đó. Tôi có thể xác nhận rằng ứng dụng cũng có thể kết nối lại bằng cách bắt đầu hình ảnh PostgreSQL với Docker và dừng hoặc khởi động lại vùng chứa: https://github.com/dotnsf/postgresql_reconnect

Tôi sẽ giới thiệu mã giả định kết nối và thực thi SQL dựa trên giả định rằng tổng hợp kết nối được sử dụng (thường là trường hợp trong các ứng dụng chung) với PostgreSQL.

【Kiểm tra hoạt động】

Bây giờ chúng tôi sẽ giới thiệu các bước để xác minh hoạt động của ứng dụng bằng PC có cài đặt Node.js và docker cục bộ.

Đầu tiên, lấy toàn bộ mã nguồn. Hoặc git clone từ kho lưu trữ Github ở trên hoặc tải xuống và mở rộng dự án postgresql_reconnect/ sang máy cục bộ của bạn.

Đầu tiên, hãy chạy PostgreSQL với docker. Chúng tôi sẽ tạo DB khi khởi động, nhưng không cần tạo bất kỳ bảng hoặc dữ liệu nào, chỉ cần khởi động nó:

↑Lệnh này hướng dẫn khởi động hình ảnh PostgreSQL chính thức dưới dạng vùng chứa với các tùy chọn sau:

  • Tên người dùng: quản trị viên
  • Mật khẩu: P@ssw0rd
  • Tên cơ sở dữ liệu: mydb
  • Số cổng công cộng: 5432

Giả định rằng công cụ docker được cài đặt trên máy chủ lưu trữ cục bộ. Bạn có thể thay đổi các tùy chọn đã chỉ định và chạy nó, nhưng mã nguồn mẫu được viết dựa trên giả định rằng phiên bản PostgreSQL được tạo từ đây, vì vậy nếu bạn thay đổi nó từ đây, vui lòng chỉnh sửa mã mẫu cho phù hợp và thực thi nó.

hình ảnh.png

Trước tiên, hãy thử chạy mã oldapp.js, mã này không xem xét kết nối lại khi ngắt kết nối. Nhân tiện, nội dung của oldapp.js như sau:

Để chạy chương trình với Node.js, trước tiên bạn cần cài đặt các thư viện cần thiết. Chạy lệnh sau (trong môi trường đã cài đặt Node.js):

Sau đó chạy lệnh sau để bắt đầu oldapp.js:

Khi bạn khởi động nó, nó sẽ hiển thị “máy chủ bắt đầu từ 8080…” và máy chủ sẽ đợi các yêu cầu trên cổng 8080. Trong trường hợp của oldapp.js, nó cũng sẽ cố gắng kết nối với PostgreSQL và hiển thị “đã kết nối. ”

Nội dung của oldapp.js ở trên cho thấy rõ rằng ứng dụng này xử lý hai API REST: “GET /” và “GET /ping”. Cái trước chỉ đơn giản trả về JSON của { status: true }. Cái sau thực thi một SQL “CHỌN 1″ đối với PostgreSQL được kết nối và trả về kết quả thực thi (nếu nó có thể kết nối với PostgreSQL, một số kết quả sẽ được trả về).

Hãy thử thực hiện cái trước. Truy cập ” http://localhost:8080/ ” trong trình duyệt web và đảm bảo rằng { status: true } được hiển thị.

hình ảnh.png

Hãy thử cái sau. Tương tự, truy cập ” http://localhost:8080/ping ” trong trình duyệt web và đảm bảo chuỗi “{ status: true, result: { …. } }” được hiển thị.

hình ảnh.png

Cho đến thời điểm này, nó sẽ thành công bình thường. Đây là thỏa thuận thực sự. Hãy dừng máy chủ PostgreSQL trong khi chạy ứng dụng ở trạng thái này. Nếu bạn dừng nó bằng lệnh docker,

Nếu bạn đang sử dụng Docker Desktop, hãy nhấn nút STOP trên vùng chứa đang chạy để dừng nó.

hình ảnh.png

Nếu chúng ta truy cập lại từng trang trong trình duyệt web ở trạng thái này, điều gì sẽ xảy ra? Tôi nghĩ rằng nó sẽ như thế này về hành vi dự kiến:

  • Đối với yêu cầu GET / (vì chúng tôi không sử dụng DB), nó sẽ trả về { status: true }.
  • Đối với yêu cầu GET /ping (do DB bị dừng), nó sẽ trả về “lỗi DB”.
  • Khi DB được khởi động lại, nó sẽ tự động kết nối lại và trả về kết quả thực thi SQL cho GET /ping. Tuy nhiên, trên thực tế, máy chủ đã bị sập vào thời điểm này. Trong thiết bị đầu cuối nơi $ node oldapp được thực thi, một Ngoại lệ được hiển thị và ứng dụng bị chấm dứt, đồng thời lời nhắc được hiển thị:

hình ảnh.png

Nói cách khác, máy chủ đã bị sập. Do đó, không chỉ các yêu cầu GET /ping mà cả các yêu cầu GET / cũng sẽ dẫn đến lỗi và vì nó không chạy nên không thể kết nối lại tự động.

hình ảnh.png

Tôi đang ở một điểm khó khăn ở đây. Nếu mục tiêu chỉ là một bản demo đơn giản, thì tôi nghĩ bạn có thể sử dụng nội dung của oldapp.js (vì nó sẽ hoạt động ngay bây giờ), nhưng nếu chúng ta đang nghĩ đến một tình huống mà nó cần phải ổn định và chạy liên tục, thì hơi đáng lo.

Vì vậy, làm cách nào chúng ta có thể triển khai thứ gì đó như newapp.js, trong đó ứng dụng sẽ không chết ngay cả khi DB bị dừng và sẽ tự động kết nối lại và thực thi lại SQL khi DB được khôi phục?

Trước tiên hãy kiểm tra hành vi trước khi giới thiệu sự khác biệt. Để chạy lại PostgreSQL:

hình ảnh.png

Chạy lệnh “$node newapp” để bắt đầu newapp.js ở trạng thái này.

Thông báo tương tự sẽ được hiển thị và yêu cầu sẽ ở trạng thái chờ. Đầu tiên, thực hiện GET / và GET /ping như trước (bản thân kết quả thực thi cũng giống như trước):

hình ảnh.png

hình ảnh.png

Hãy thử buộc dừng PostgreSQL tại đây. Lần trước, ứng dụng bị lỗi và dừng chờ yêu cầu, nhưng lần này, ứng dụng sẽ ở chế độ chờ mà không quay lại lời nhắc.

hình ảnh.png

Hãy thử truy cập lại GET / và GET /ping trong trạng thái này. GET / sẽ vẫn trả về { status: true } và GET /ping sẽ trả về { status: false, error: … } vì nó không thể truy cập DB, nhưng nó có thể trả về phản hồi.

hình ảnh.png

hình ảnh.png

Sau đó khởi động lại PostgreSQL đã dừng.

hình ảnh.png

Bạn đợi một chút rồi chạy lệnh GET /ping, ứng dụng sẽ tự động kết nối lại và hiển thị màn hình thông báo thực thi SQL thành công.

hình ảnh.png

Điều này cho phép hành vi thực tế tự động kết nối lại và tiếp tục hoạt động ngay cả khi bảo trì được thực hiện trên cơ sở dữ liệu.

【Mô tả mã】

Đầu tiên, cái không có kết nối lại tự động. Phần kết nối và phần thực thi SQL như sau:

Trong quá trình kết nối, chuỗi kết nối được tạo đơn giản để tạo nhóm kết nối, sau đó connect() được thực thi để truy xuất một máy khách. Máy khách này sau đó được sử dụng lại để thực thi SQL tiếp theo. Trong quá trình thực thi SQL, chuỗi SQL được xác định và máy khách được truy xuất ở trên được sử dụng để thực thi nó. Bản thân quá trình này có thể hiểu được, nhưng mặt khác, nó không xem xét các ngoại lệ (vì vậy DB có thể dừng và khiến ứng dụng bị sập).

Phần kết nối và phần thực thi SQL của phần sau, được thiết kế để có thể tự động kết nối lại sau khi ngắt kết nối có tính đến sự xuất hiện của ngoại lệ, như sau:

Lúc đầu, quá trình kết nối giống nhau cho đến khi nhóm kết nối được tạo, nhưng ở đây nó kết thúc như cũ. Quá trình thực thi connect() để truy xuất máy khách đã được thay đổi thành ngay trước khi thực sự thực thi SQL. Ngoài ra, biến pg, quản lý nhóm kết nối, được sử dụng để xử lý lỗi, để nó có thể được xử lý chính xác khi DB bị ngắt kết nối (cụ thể là đợi vài giây và tạo lại nhóm kết nối và xử lý lỗi cho nhóm mới nhóm kết nối được tạo).

Khi thực thi SQL ta làm như sau:

  1. (bao bọc toàn bộ quá trình trong try{ .. }catch{ .. }cuối cùng{ .. } để các ngoại lệ có thể được xử lý bất kể nó bị ngắt kết nối ở đâu
  2. tải ứng dụng khách bằng pg.connect ngay trước khi thực sự thực thi SQL trong try{ .. }
  3. giải phóng ứng dụng khách và đưa nó trở lại nhóm kết nối cuối cùng{ .. }.

Bằng cách thêm ba quy trình này, chúng tôi đảm bảo rằng nếu DB đột ngột chết, nó sẽ xử lý chính xác và cố gắng kết nối lại (tạo nhóm kết nối mới). Ngay cả khi mất nhiều thời gian để kết nối lại, bản thân ứng dụng sẽ không bị sập, vì vậy nó có thể đáp ứng các yêu cầu từ người dùng (mặc dù nó không thể truy cập DB).

Tóm lại, những gì tôi đang cung cấp chỉ là một ví dụ mẫu, nhưng tôi nghĩ cách tiếp cận này có thể giúp tự động kết nối lại và tiếp tục chạy ngay cả khi máy chủ PostgreSQL bị ngắt kết nối. Nó cũng có thể được áp dụng khi sử dụng RDB với các kết nối khác ngoài PostgreSQL. Tùy thuộc vào nền tảng cơ sở hạ tầng bạn sử dụng, có thể có các tính năng đặc biệt để kết nối lại trong quá trình bảo trì, vì vậy bạn không nhất thiết phải làm theo cách này, nhưng tôi nghĩ đó là cách tốt nhất.

Và cuối cùng

Như mọi khi, tôi hy vọng bạn thích bài viết này và học được điều gì đó mới. Xin cảm ơn và hẹn gặp lại các bạn trong những bài viết tiếp theo!

Nếu các bạn thích bài viết này thì hãy cho mình 1 like và subscribe để ủng hộ mình nhé. Cảm ơn.

Nguồn

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo