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)”.
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ó:
1 2 | $ docker run -d --name postgres -e POSTGRES_USER=admin -e POSTGRES_PASSWORD=P@ssw0rd -e POSTGRES_DB=mydb -p 5432:5432 postgres |
↑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ó.
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <span class="token comment">//. oldapp.js</span> <span class="token keyword">var</span> express <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"express"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> app <span class="token operator">=</span> <span class="token function">express</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> <span class="token constant">PG</span> <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"pg"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">//. PostgreSQL</span> <span class="token keyword">var</span> pg_hostname <span class="token operator">=</span> <span class="token string">"localhost"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg_port <span class="token operator">=</span> <span class="token number">5432</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg_database <span class="token operator">=</span> <span class="token string">"mydb"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg_username <span class="token operator">=</span> <span class="token string">"admin"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg_password <span class="token operator">=</span> <span class="token string">"P@ssw0rd"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg_clinet <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> connectionString <span class="token operator">=</span> <span class="token string">"postgres://"</span> <span class="token operator">+</span> pg_username <span class="token operator">+</span> <span class="token string">":"</span> <span class="token operator">+</span> pg_password <span class="token operator">+</span> <span class="token string">"@"</span> <span class="token operator">+</span> pg_hostname <span class="token operator">+</span> <span class="token string">":"</span> <span class="token operator">+</span> pg_port <span class="token operator">+</span> <span class="token string">"/"</span> <span class="token operator">+</span> pg_database <span class="token punctuation">;</span> <span class="token comment">//+ "?sslmode=verify-full";</span> <span class="token keyword">var</span> pg <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PG <span class="token punctuation">.</span> Pool</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> connectionString <span class="token operator">:</span> connectionString <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg <span class="token punctuation">.</span> <span class="token function">connect</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err <span class="token punctuation">,</span> client</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//. DB not running on first boot</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"no db on startup"</span> <span class="token punctuation">,</span> err <span class="token punctuation">.</span> code <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"connected."</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg_client <span class="token operator">=</span> client <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">//. top</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">"/"</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">contentType</span> <span class="token punctuation">(</span> <span class="token string">"application/json; charset=utf-8"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">//. ping</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">"/ping"</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">contentType</span> <span class="token punctuation">(</span> <span class="token string">"application/json; charset=utf-8"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> sql <span class="token operator">=</span> <span class="token string">"select 1"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> query <span class="token operator">=</span> <span class="token punctuation">{</span> text <span class="token operator">:</span> sql <span class="token punctuation">,</span> values <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> pg_client <span class="token punctuation">.</span> <span class="token function">query</span> <span class="token punctuation">(</span> query <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err <span class="token punctuation">,</span> result</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> err <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">status</span> <span class="token punctuation">(</span> <span class="token number">400</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> error <span class="token operator">:</span> err <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">//console.log( { result } );</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> result <span class="token operator">:</span> result <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> port <span class="token operator">=</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">8080</span> <span class="token punctuation">;</span> app <span class="token punctuation">.</span> <span class="token function">listen</span> <span class="token punctuation">(</span> port <span class="token punctuation">)</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"server starting on "</span> <span class="token operator">+</span> port <span class="token operator">+</span> <span class="token string">" ..."</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Để 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):
1 2 | $ npm install |
Sau đó chạy lệnh sau để bắt đầu oldapp.js:
1 2 | $ node oldapp |
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. ”
1 2 3 4 | $ node oldapp server starting on 8080 ... connected. |
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ã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ị.
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,
1 2 | $ docker stop postgres |
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ó.
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ị:
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.
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?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | <span class="token comment">//. newapp.js</span> <span class="token keyword">var</span> express <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"express"</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> app <span class="token operator">=</span> <span class="token function">express</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> <span class="token constant">PG</span> <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span> <span class="token string">"pg"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">//. PostgreSQL</span> <span class="token keyword">var</span> pg_hostname <span class="token operator">=</span> <span class="token string">"localhost"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg_port <span class="token operator">=</span> <span class="token number">5432</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg_database <span class="token operator">=</span> <span class="token string">"mydb"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg_username <span class="token operator">=</span> <span class="token string">"admin"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg_password <span class="token operator">=</span> <span class="token string">"P@ssw0rd"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> retry_ms <span class="token operator">=</span> <span class="token number">5000</span> <span class="token punctuation">;</span> <span class="token comment">//. retry every 5 sec</span> <span class="token keyword">var</span> connectionString <span class="token operator">=</span> <span class="token string">"postgres://"</span> <span class="token operator">+</span> pg_username <span class="token operator">+</span> <span class="token string">":"</span> <span class="token operator">+</span> pg_password <span class="token operator">+</span> <span class="token string">"@"</span> <span class="token operator">+</span> pg_hostname <span class="token operator">+</span> <span class="token string">":"</span> <span class="token operator">+</span> pg_port <span class="token operator">+</span> <span class="token string">"/"</span> <span class="token operator">+</span> pg_database <span class="token punctuation">;</span> <span class="token comment">//+ "?sslmode=verify-full";</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"connecting..."</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PG <span class="token punctuation">.</span> Pool</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> connectionString <span class="token operator">:</span> connectionString <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg <span class="token punctuation">.</span> <span class="token function">on</span> <span class="token punctuation">(</span> <span class="token string">"error"</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"db error on starting"</span> <span class="token punctuation">,</span> err <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">.</span> code <span class="token operator">&&</span> err <span class="token punctuation">.</span> code <span class="token punctuation">.</span> <span class="token function">startsWith</span> <span class="token punctuation">(</span> <span class="token string">"5"</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//. terminated by admin?</span> <span class="token function">try_reconnect</span> <span class="token punctuation">(</span> retry_ms <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">try_reconnect</span> <span class="token punctuation">(</span> <span class="token parameter">ts</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">setTimeout</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"reconnecting..."</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PG <span class="token punctuation">.</span> Pool</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> connectionString <span class="token operator">:</span> connectionString <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg <span class="token punctuation">.</span> <span class="token function">on</span> <span class="token punctuation">(</span> <span class="token string">"error"</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"db error on working"</span> <span class="token punctuation">,</span> err <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">.</span> code <span class="token operator">&&</span> err <span class="token punctuation">.</span> code <span class="token punctuation">.</span> <span class="token function">startsWith</span> <span class="token punctuation">(</span> <span class="token string">"5"</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//. terminated by admin?</span> <span class="token function">try_reconnect</span> <span class="token punctuation">(</span> ts <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> ts <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//. top</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">"/"</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">contentType</span> <span class="token punctuation">(</span> <span class="token string">"application/json; charset=utf-8"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">//. ping</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">"/ping"</span> <span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">contentType</span> <span class="token punctuation">(</span> <span class="token string">"application/json; charset=utf-8"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> conn <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token punctuation">;</span> <span class="token keyword">try</span> <span class="token punctuation">{</span> conn <span class="token operator">=</span> <span class="token keyword">await</span> pg <span class="token punctuation">.</span> <span class="token function">connect</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> sql <span class="token operator">=</span> <span class="token string">"select 1"</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> query <span class="token operator">=</span> <span class="token punctuation">{</span> text <span class="token operator">:</span> sql <span class="token punctuation">,</span> values <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> conn <span class="token punctuation">.</span> <span class="token function">query</span> <span class="token punctuation">(</span> query <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err <span class="token punctuation">,</span> result</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> err <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">status</span> <span class="token punctuation">(</span> <span class="token number">400</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> error <span class="token operator">:</span> err <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">//console.log( { result } );</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> result <span class="token operator">:</span> result <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span> e <span class="token punctuation">)</span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">status</span> <span class="token punctuation">(</span> <span class="token number">400</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> error <span class="token operator">:</span> e <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> conn <span class="token punctuation">)</span> <span class="token punctuation">{</span> conn <span class="token punctuation">.</span> <span class="token function">release</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> port <span class="token operator">=</span> process <span class="token punctuation">.</span> env <span class="token punctuation">.</span> <span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">8080</span> <span class="token punctuation">;</span> app <span class="token punctuation">.</span> <span class="token function">listen</span> <span class="token punctuation">(</span> port <span class="token punctuation">)</span> <span class="token punctuation">;</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"server starting on "</span> <span class="token operator">+</span> port <span class="token operator">+</span> <span class="token string">" ..."</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
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:
Chạy lệnh “$node newapp” để bắt đầu newapp.js ở trạng thái này.
1 2 3 4 | $ node newapp server starting on 8080 ... connecting... |
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ã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ã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.
Sau đó khởi động lại PostgreSQL đã dừng.
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.
Đ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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <span class="token keyword">var</span> pg_clinet <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> connectionString <span class="token operator">=</span> <span class="token string">"postgres://"</span> <span class="token operator">+</span> pg_username <span class="token operator">+</span> <span class="token string">":"</span> <span class="token operator">+</span> pg_password <span class="token operator">+</span> <span class="token string">"@"</span> <span class="token operator">+</span> pg_hostname <span class="token operator">+</span> <span class="token string">":"</span> <span class="token operator">+</span> pg_port <span class="token operator">+</span> <span class="token string">"/"</span> <span class="token operator">+</span> pg_database <span class="token punctuation">;</span> <span class="token comment">//+ "?sslmode=verify-full";</span> <span class="token keyword">var</span> pg <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PG <span class="token punctuation">.</span> Pool</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> connectionString <span class="token operator">:</span> connectionString <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg <span class="token punctuation">.</span> <span class="token function">connect</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err <span class="token punctuation">,</span> client</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//. DB not running on first boot</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'no db on startup'</span> <span class="token punctuation">,</span> err <span class="token punctuation">.</span> code <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'connected.'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg_client <span class="token operator">=</span> client <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token operator">:</span> <span class="token operator">:</span> <span class="token comment">//. ping</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">'/ping'</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">contentType</span> <span class="token punctuation">(</span> <span class="token string">'application/json; charset=utf-8'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> sql <span class="token operator">=</span> <span class="token string">'select 1'</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> query <span class="token operator">=</span> <span class="token punctuation">{</span> text <span class="token operator">:</span> sql <span class="token punctuation">,</span> values <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> pg_client <span class="token punctuation">.</span> <span class="token function">query</span> <span class="token punctuation">(</span> query <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err <span class="token punctuation">,</span> result</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> err <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">status</span> <span class="token punctuation">(</span> <span class="token number">400</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> error <span class="token operator">:</span> err <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">//console.log( { result } );</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> result <span class="token operator">:</span> result <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | <span class="token keyword">var</span> retry_ms <span class="token operator">=</span> <span class="token number">5000</span> <span class="token punctuation">;</span> <span class="token comment">//. retry every 5 sec</span> <span class="token keyword">var</span> connectionString <span class="token operator">=</span> <span class="token string">"postgres://"</span> <span class="token operator">+</span> pg_username <span class="token operator">+</span> <span class="token string">":"</span> <span class="token operator">+</span> pg_password <span class="token operator">+</span> <span class="token string">"@"</span> <span class="token operator">+</span> pg_hostname <span class="token operator">+</span> <span class="token string">":"</span> <span class="token operator">+</span> pg_port <span class="token operator">+</span> <span class="token string">"/"</span> <span class="token operator">+</span> pg_database <span class="token punctuation">;</span> <span class="token comment">//+ "?sslmode=verify-full";</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'connecting...'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> pg <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PG <span class="token punctuation">.</span> Pool</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> connectionString <span class="token operator">:</span> connectionString <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg <span class="token punctuation">.</span> <span class="token function">on</span> <span class="token punctuation">(</span> <span class="token string">'error'</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'db error on starting'</span> <span class="token punctuation">,</span> err <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">.</span> code <span class="token operator">&&</span> err <span class="token punctuation">.</span> code <span class="token punctuation">.</span> <span class="token function">startsWith</span> <span class="token punctuation">(</span> <span class="token string">'5'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//. terminated by admin?</span> <span class="token function">try_reconnect</span> <span class="token punctuation">(</span> retry_ms <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">try_reconnect</span> <span class="token punctuation">(</span> <span class="token parameter">ts</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">setTimeout</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'reconnecting...'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PG <span class="token punctuation">.</span> Pool</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> connectionString <span class="token operator">:</span> connectionString <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> pg <span class="token punctuation">.</span> <span class="token function">on</span> <span class="token punctuation">(</span> <span class="token string">'error'</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'db error on working'</span> <span class="token punctuation">,</span> err <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">.</span> code <span class="token operator">&&</span> err <span class="token punctuation">.</span> code <span class="token punctuation">.</span> <span class="token function">startsWith</span> <span class="token punctuation">(</span> <span class="token string">'5'</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//. terminated by admin?</span> <span class="token function">try_reconnect</span> <span class="token punctuation">(</span> ts <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> ts <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">:</span> <span class="token operator">:</span> <span class="token comment">//. ping</span> app <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">'/ping'</span> <span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">contentType</span> <span class="token punctuation">(</span> <span class="token string">'application/json; charset=utf-8'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> conn <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token punctuation">;</span> <span class="token keyword">try</span> <span class="token punctuation">{</span> conn <span class="token operator">=</span> <span class="token keyword">await</span> pg <span class="token punctuation">.</span> <span class="token function">connect</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> sql <span class="token operator">=</span> <span class="token string">'select 1'</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> query <span class="token operator">=</span> <span class="token punctuation">{</span> text <span class="token operator">:</span> sql <span class="token punctuation">,</span> values <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> conn <span class="token punctuation">.</span> <span class="token function">query</span> <span class="token punctuation">(</span> query <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token parameter">err <span class="token punctuation">,</span> result</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> err <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> err <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">status</span> <span class="token punctuation">(</span> <span class="token number">400</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> error <span class="token operator">:</span> err <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">//console.log( { result } );</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> result <span class="token operator">:</span> result <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span> e <span class="token punctuation">)</span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">status</span> <span class="token punctuation">(</span> <span class="token number">400</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">write</span> <span class="token punctuation">(</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> status <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> error <span class="token operator">:</span> e <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token number">2</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> res <span class="token punctuation">.</span> <span class="token function">end</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> conn <span class="token punctuation">)</span> <span class="token punctuation">{</span> conn <span class="token punctuation">.</span> <span class="token function">release</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
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:
- (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
- tải ứng dụng khách bằng pg.connect ngay trước khi thực sự thực thi SQL trong try{ .. }
- 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.