Ở Hashnode, chúng tôi sử dụng mạnh Nodejs. Cá nhân tôi là một fan hâm mộ và đã học được nhiều điều khi chạy Hashnode. Qua tiếp xúc với nhiều lập trình viên, tôi nhận ra rằng nhiều người chưa tận dụng Nodejs đến mức tối đa và thực hiện một số điều theo cách không chuẩn. Vì vậy, bài này sẽ nói về những điều không nên làm khi chạy một ứng dụng Nodejs trong thực tế (in production applications). Bắt đầu nào!

Không Sử Dụng Nodejs Cluster

Bản chất của Nodejs là đơn luồng và giới hạn bộ nhớ 1.5GB. Vì thế nó không tự động tận dụng được nhiều lõi CPU. Tuy nhiên tin tốt là Cluster module cho phép bạn tạo (fork) nhiều tiến trình con sử dụng IPC để giao tiếp với tiến trình cha. Một bạn tiến trình boss trùm sẽ quản lý các tiến trình con, đệ của nó và các yêu cầu, tác vụ đc gửi đến sẽ qua boss trùm sau đó được phân phối theo kiểu luân chuyển vòng (round-robin).

Clustering nâng cao hiệu năng ứng dụng và cho phép bạn hạ thời gian dừng khi triển khai xuống không (zero downtime). Bên cạnh đó, số lượng tiến trình con có thể được tạo ra không bị giới hạn bởi số lõi CPU của máy.

Cá nhân tôi cảm thấy clustering là một việc phải làm cho bất kì ứng dụng Nodejs nào chạy trong thực tế và không có lí do gì để không áp dụng nó cả.

Xử Lý Các Tác Vụ Nặng Trên Web Server

Nodejs/ Express servers không phù hợp để xử lý các tác vụ nặng và yêu cầu tính toán nhiều. Ví dụ, một ứng dụng web đơn giản có thể cần gửi một loạt mails cho người dùng. Mặc dù bạn có thể thực hiện công việc này trong Nodejs server nhưng nó sẽ ảnh hưởng hiệu năng hoạt động đáng kể. Một cách làm tốt hơn là tách những tác vụ kiểu này thành những microservices (dịch vụ siêu nhỏ) phụ trách riêng tác vụ đó và triển khai chúng thành ứng dụng Node riêng biệt. Thêm vào đó, bạn có thể sử dụng những ứng dụng truyền tin như RabbitMQ để giao tiếp giữa các microservices.

Khi bạn đăng một bài trên Hashnode và gắn các từ khóa, chúng tôi đẩy bài viết vào trang tin tức (news feed) của hàng nghìn người dùng. Đây là một tác vụ nặng. Chỉ đến vài tháng trước, công việc đẩy bài viết vào trang tin tức vẫn được thực hiện bởi chính web server. Khi lưu lượng vào trang web tăng lên, chúng tôi nhận thấy nút thắt cổ chai xuất hiện và tắc nghẽn xảy ra. Hồi đó, nếu bạn đăng một bài viết và gắn từ khóa "General Programming" hay "JavaScript" thì cả trang web sẽ đơ mất vài giây. Sau khi tìm hiểu kĩ càng thì vấn đề nằm ở tác vụ đẩy bài viết vào trang tin tức của người dùng. Giải pháp chính là chuyển toàn bộ module xử lý tác vụ đó sang một máy khác và gọi tác vụ này qua tin nhắn, sử dụng message queue.

Vì vậy, điều quan trọng chúng ta nên nhớ là Nodejs phù hợp khi xử lý các sự kiện và non-blocking I/O. Bất cứ tác vụ nào nặng và tốn thời gian dài để hoàn thành nên được xử lý bởi một tiến trình riêng biệt.

Không Sử Dụng Công Cụ Quản Lý Tiến Trình

Dù rõ ràng là công cụ quản lý tiến trình mang nhiều lợi ích, nhiều lập trình viên mới lần đầu triển khai ứng dụng không sử dụng nó. Ở Hashnode, chúng tôi sử dụng pm2, một công cụ quản lý rất mạnh cho ứng dụng Node.

Thêm nữa, nếu sử dụng pm2 thì bạn có thể chạy clustering ứng dụng của mình khá dễ dàng.

pm2 start app.js -i 2

Với câu lệnh trên, i là số lượng tiến trình con mà ta muốn tạo. Điều tuyệt vời nhất chính là bạn có thể chạy lại từng tiến trình con lần lượt mà không ảnh hưởng đến nhau, vì thế, ứng dụng không phải trải qua thời gian chết khi triển khai. Cây lệnh dưới đây sẽ chạy lại ứng dụng

pm2 reload app

Nếu bạn sử dụng pm2, hãy tham khảo Keymetrics, đây là một dịch vụ giám sát ứng dụng Nodejs (dựa trên pm2).

Không Sử Dụng Reverse Proxy

Tôi đã thấy những lập trình viên chạy ứng dụng Nodejs trên cổng 80 và cung cấp tài nguyên tĩnh thẳng qua cổng này. Bạn nên nhớ kĩ rằng chạy ứng dụng Nodejs trên cổng 80 không phải một ý hay và thực tế nó nguy hiểm trong phần lớn các trường hợp. Thay vào đó bạn nên chạy trên một cổng khác, ví dụ như cổng 3000 và sử dụng nginx (hay cái gì đó như HAProxy?) như một reverse proxy đứng trước ứng dụng Nodejs của bạn.

Cấu hình kiểu trên bảo vệ ứng dụng của bạn khỏi tiếp xúc trực tiếp với các yêu cầu, việc này giúp mở rộng server và cân bằng tải yêu cầu đến dễ dàng hơn.

Thiếu Theo Dõi Giám Sát Ứng Dụng

Những thứ tệ hại như lỗi bất ngờ, không mong muốn và các trường hợp đặc biệt xảy ra thường xuyên. Nhưng điều tệ hơn nữa là gì, bạn biết không? Đó chính là còn không biết lỗi đã xảy ra trong hệ thống. Khi bạn xử dụng một công cụ quản lý tiến trình thì tiến trình sẽ được khởi động lại mỗi lần có một lỗi không được xử lý xuất hiện. Vì thế, trừ khi bạn kiểm tra logs thì sẽ không biết chuyện quái gì đã xảy ra. Giải pháp cho chuyện này chính là sử dụng dịch vụ giám sát và nó sẽ thông báo cho bạn qua email hay sms mỗi lần tiến trình của bạn bị chết và khởi động lại.

Không Xóa Câu Lệnh Console Log

Khi phát triển ứng dụng, chúng ta sử dụng console.log để kiểm tra. Tuy nhiên thỉnh thoảng chúng ta lại quên xóa những câu lệnh này đi gây tốn CPU và tài nguyên. Cách tốt nhất để tránh chuyện này là sử dụng module debug. Khi đó trừ khi bạn chạy ứng dụng trong môi trường DEBUG  các câu lệnh console log sẽ không được in ra.

Duy Trì Trạng Thái Global Trên Web Server

Thi thoảng, lập trình viên lưu giá trị session ids, socket connections, ... trong bộ nhớ (như kiểu in memory thay vì lưu dữ liệu persisten trong một CSDL nào đó). Việc này là hoàn toàn không nên và nên tránh bằng bất kì giá nào. Nếu bạn lưu session ids trong bộ nhớ, bạn sẽ thấy rằng người dùng sẽ bị đăng xuất ngay mỗi lần server khởi động lại. Việc này cũng dẫn đến khó khăn và vấn đề khi mở rộng ứng dụng và tăng thêm servers. Web servers của bạn chỉ tập trung xử lý các yêu cầu, truy cập qua lại trên web chứ không lưu trữ bất cứ thông tin nào ở bộ nhớ.

Không Dùng SSL

Với một trang web cho người dùng, không có lí do gì để không mặc định dùng SSL. Thỉnh thoảng tôi thấy lập trình viên đọc khóa SSL từ một file và sử dụng nó trong tiến trình Node. Bạn luôn nên sử dụng reverse proxy trước ứng dụng Nodejs của mình và cài đặt SSL ở reverse proxy này. 

Thêm nữa, hãy thường xuyên kiểm tra những điểm yếu mới nhất của SSL và áp dụng biện pháp xử lý nhanh nhất có thể. 

Thiếu Các Biện Pháp Bảo Mật Cơ Bản

Bảo mật luôn quan trọng và luôn lo lắng để ý đến bảo mật là một điều tốt. Bên cạnh kiểm tra bảo mật cơ bản, bạn nên sử dụng những thứ như NSP để phát hiện các điểm yếu trong dự án của mình.

Và đừng sử dụng bản quá cũ hết đát của Node và Express. Những bản không còn được bảo trì và không còn được nâng cấp về bảo mật.

Không Sử Dụng VPN

Luôn triển khai ứng dụng của bạn trên một mạng lưới tư, để chỉ có những clients đáng tin có thể giao tiếp với bạn. Nhiều người thường quên điều này khi triển khai và gặp phải nhiều vấn đề sau đó. Nghĩ đến kiến trúc và nền tảng cơ sở vật chất trước khi triển khai ứng dụng lên mạng là một cách làm tốt.

Ví dụ, nếu ứng dụng của bạn chạy trên cổng 8080 và đã cấu hình nginx làm reverskhông nên làme proxy, bạn nên đảm bảo rằng chỉ có nginx có thể giao tiếp với server tại cổng này. Cổng này nên được cô lập hoàn toàn và không được xâm phạm bởi những thứ khác trên mạng.

Tổng kết lại, tôi đã liệt kê 10 điều không nên làm khi triển khai một ứng dụng Nodejs lên trên mạng.

Bài viết bởi Sandeep Panda trên Hashnode. Đường dẫn nguồn.