NodeJS: Thực tiễn tốt nhất cho sản xuất

Đây là một nỗ lực để tranh thủ các thực tiễn quan trọng nhất để phát triển và triển khai trên NodeJs.

Tôi đã làm việc trên công nghệ này một thời gian. Tôi nhận ra tiềm năng to lớn và vị trí của nó trong quá trình phát triển. Với sự cạnh tranh gay gắt từ các ngôn ngữ như Python và Golang, NodeJS đã chứng minh tiện ích của nó trong các trường hợp sử dụng phù hợp.

Trước khi tôi đi sâu vào các thực tiễn tốt nhất, tôi muốn giới thiệu ngắn gọn về mô hình microservice là gì. Sau đó đưa cuộc trò chuyện xa hơn từ đó.

Vậy, microservice là gì?

Microservice - còn được gọi là kiến ​​trúc microservice - là một kiểu kiến ​​trúc cấu trúc một ứng dụng như một tập hợp các dịch vụ:

  • Có khả năng duy trì và kiểm tra cao
  • Ghép đôi lỏng lẻo
  • Có thể triển khai độc lập
  • Tổ chức xung quanh khả năng kinh doanh.

Kiến trúc microservice cho phép phân phối / triển khai liên tục các ứng dụng lớn, phức tạp. Nó cũng cho phép một tổ chức phát triển ngăn xếp công nghệ của mình.

Làm thế nào để quyết định nếu bạn cần microservice

Ban đầu, khi bạn mới bắt đầu làm việc với MVP của mình, bạn có thể không cần sử dụng microservice. Tỷ lệ trục Y có thể không phải là chương trình nghị sự của bạn ngay bây giờ. Nhưng khi sản phẩm bắt đầu trưởng thành và đôi khi quá sớm khi bạn phải xử lý mở rộng quy mô, việc phân tách thành các mô đun chức năng có ý nghĩa hơn khi bản thân doanh nghiệp đang phân hủy. Đây sẽ là điểm thích hợp để bắt đầu xem xét mẫu kiến ​​trúc microservice.

Một cuốn sách mà tôi đánh giá cao là của Chris Richardson tại đây: http://bit.ly/2EmJDYt.

Các dịch vụ vi mô thường được xem xét nhất trong khi thay thế một ứng dụng nguyên khối thường khá phổ biến cho đến gần đây khi các giải pháp container hóa như Docker bắt đầu thống trị thế giới DevOps. Nhưng nhiều hơn về điều này sau.

Sẽ là không công bằng nếu tôi tiếp tục mà không đề cập đến Thiết kế hướng tên miền (DDD). Đây là một chiến lược rất phổ biến để phân tách sản phẩm của bạn thành các mô đun chức năng. Do đó rất hữu ích để tạo microservice.

Vì vậy, một tên miền theo DDD là gì?

Mỗi vấn đề mà bạn đang cố gắng giải quyết là một miền.

Mỗi miền được chia thành các bối cảnh giới hạn loại trừ lẫn nhau. Những bối cảnh này không là gì ngoài những lĩnh vực riêng biệt của vấn đề cụ thể đó.

Trong một mẫu microservice, mỗi bối cảnh giới hạn tương quan với một microservice. Các mẫu DDD giúp bạn hiểu được sự phức tạp trong miền. Đối với mô hình miền cho từng Bối cảnh giới hạn, bạn xác định và xác định
các thực thể, các đối tượng giá trị và tổng hợp mô hình miền của bạn.

Tùy thuộc vào độ phức tạp của phần mềm, bạn có thể chọn các nguyên tắc DDD hoặc thực hiện một cách tiếp cận đơn giản hơn.

Mục tiêu là để đạt được một mô hình miền gắn kết cao và lỏng lẻo. Đối với điều đó theo cách tiếp cận này:

Đây là một đoạn giới thiệu ngắn gọn về DDD. Để tìm hiểu thêm về nó, tôi khuyên bạn nên đọc cuốn sách tuyệt vời của Eric Evans, http://bit.ly/2Eoy17l.

Tiến lên.

Tôi hy vọng bạn đang giữ với tôi.

Vì vậy, từ đây trở đi, tôi sẽ nói nhiều hơn về các hoạt động cụ thể đối với NodeJS. Và điều tôi muốn nói là microservice và DDD giúp bạn đánh giá tiềm năng thực sự của NodeJS. Nó hoàn thành trong chính nó. Làm sao? Chúng ta sẽ thấy.

Mẫu thiết kế nào sẽ sử dụng trong khi sử dụng NodeJs

Các mẫu thiết kế là về thiết kế phần mềm bằng cách sử dụng các tiêu chuẩn nhất định mà một số nhà phát triển đã biết.

Có nhiều mẫu thiết kế khác nhau mà chúng ta có thể sử dụng. Tôi muốn giới thiệu và / hoặc tóm tắt cho các nhà phát triển đã biết về một mẫu được gọi là Mẫu Kho lưu trữ.

Mẫu này giúp phân tách logic MVC dễ dàng hơn đồng thời giúp xử lý định nghĩa mô hình và tương tác mô hình với phần còn lại của logic dễ dàng hơn.

Nó bao gồm:

  1. Trình điều khiển: Nó chỉ xử lý yêu cầu và phản hồi và các thuộc tính liên quan. Nó sẽ không có bất kỳ logic kinh doanh hoặc định nghĩa mô hình hoặc các hiệp hội mô hình quá. (tên thư mục: bộ điều khiển)
  2. Dịch vụ: Nó chứa logic kinh doanh cho microservice của bạn. Kiểm soát chuyển từ bộ điều khiển đến một dịch vụ. Nó có mối quan hệ 1: 1 giữa bộ điều khiển và dịch vụ của nó và mối quan hệ 1: nhiều giữa dịch vụ và kho lưu trữ. (tên thư mục: dịch vụ)
  3. Kho lưu trữ: Nó tương tác với các mô hình là một phần của thư mục mô hình. Bất kỳ truy vấn đến cơ sở dữ liệu thông qua lớp mô hình sẽ được hình thành ở đây. Nó sẽ không có logic kinh doanh. (tên thư mục: kho lưu trữ)
  4. Model: Nó chứa định nghĩa mô hình, các hiệp hội, các hàm ảo (ví dụ: trong mongoose)
  5. Tiện ích: Điều này sẽ chứa các lớp / hàm trợ giúp có thể được sử dụng làm dịch vụ. Ví dụ: tiện ích Redis có tất cả các chức năng cần thiết để tương tác với Redis. (tên thư mục: tiện ích)
  6. Trường hợp thử nghiệm: Điều này sẽ bao gồm các trường hợp thử nghiệm đơn vị đối với các phương thức của bộ điều khiển để đảm bảo phạm vi mã tối đa. (tên thư mục: spec)

Để đọc thêm về điều này, bạn có thể tham khảo liên kết này: http://bit.ly/2TrSyRS

Ok, cho tôi biết về các mô-đun cụm

Một phiên bản duy nhất của Node.js chạy trong một luồng. Để tận dụng các hệ thống đa lõi, đôi khi người dùng sẽ muốn khởi chạy một cụm các quy trình Node.js để xử lý tải.

Mô-đun cụm cho phép dễ dàng tạo các tiến trình con mà tất cả các cổng máy chủ chia sẻ.

Xin lưu ý rằng nó rất lý tưởng để sử dụng một quy trình cho mỗi container trong khi sử dụng Docker container để triển khai thông qua microservice. Do đó, các mô-đun cụm không có ích khi sử dụng docker-ization.

Cách xử lý luồng điều khiển trong NodeJS

Trong khi sử dụng các cuộc gọi lại hoặc lời hứa, các thư viện sau có thể hữu ích:

  1. Không đồng bộ (https://www.npmjs.com/package/async)
  2. Vasync (với tính năng theo dõi hoạt động tốt hơn) https://www.npmjs.com/package/vasync
  3. Bluebird (xử lý các lời hứa, vd. Promise.all, v.v.) https://www.npmjs.com/package/bluebird

Và vòng lặp?

  • Chuỗi vòng: thực hiện từng bước một theo thứ tự
  • Vòng lặp bị trì hoãn: vòng lặp có thời gian chờ
  • Parallel loop: thu thập tất cả các lời hứa trong một vòng lặp và thực hiện song song

Và một số công cụ linting hữu ích là gì?

Các công cụ linting phân tích mã của bạn một cách tĩnh (không chạy nó). Họ xác định các lỗi tiềm ẩn hoặc mô hình nguy hiểm. Các mô hình như việc sử dụng các biến không được khai báo, hoặc các câu lệnh case case trong một công tắc mà không có câu lệnh break break.

Việc kích hoạt chế độ nghiêm ngặt trên cơ sở mã của bạn bằng ‘sử dụng nghiêm ngặt có thể giúp mã của bạn thất bại nhanh nếu trình phân tích cú pháp JavaScript có thể xác định một hành vi xấu toàn cầu hoặc tương tự bị rò rỉ.

Ví dụ về các linters là Javascript lint và JS lint.

Ok, làm thế nào để chúng tôi xử lý đăng nhập?

Một số gói npm thường được sử dụng là:

  • Winston (https://www.npmjs.com/package/winston)
  • Bunyan (https://www.npmjs.com/package/bunyan)

Định dạng ghi nhật ký có thể:

Đối với các hệ thống phân tán như microservice, bạn muốn khám phá theo dõi phân tán bằng ZipKin, v.v.

Lưu ý về các gói NPM: Bạn chỉ nên sử dụng một gói nếu nó giải quyết được vấn đề cho bạn mà bạn có thể tự giải quyết. Thường xuyên thực hiện kiểm toán npm để tìm các vấn đề quan trọng với các phụ thuộc npm của bạn.

Xử lý các trường hợp ngoại lệ

Theo mặc định, Node.js xử lý các trường hợp ngoại lệ như vậy bằng cách in theo dõi ngăn xếp thành stderr và thoát bằng mã 1, ghi đè bất kỳ process.exitCode nào được đặt trước đó

Lưu ý: Thêm trình xử lý cho sự kiện 'unsaughtException' sẽ ghi đè hành vi mặc định này.

Ngoài ra, thay đổi process.exitCode trong trình xử lý 'unsaughtException', điều này sẽ dẫn đến quá trình thoát với mã thoát được cung cấp. Mặt khác, với sự có mặt của một trình xử lý như vậy, quá trình sẽ thoát với 0.

process.exit (0) - chấm dứt thành công
process.exit (1) - chấm dứt không thành công

Xử lý các từ chối chưa xử lý

Các lời hứa có mặt khắp nơi trong mã Node.js và đôi khi được kết nối thành một danh sách rất dài các hàm trả về lời hứa, v.v.

Không sử dụng trình xử lý từ chối .catch (Hoài) thích hợp sẽ gây ra sự kiện UnandledRejection được phát ra. Nếu không được bắt và kiểm tra đúng cách, bạn có thể tự cướp đi cơ hội duy nhất của mình để phát hiện và có thể khắc phục vấn đề.

Mẹo thêm:

console.time () và console.timeEnd ()

Đối tượng giao diện điều khiển có các phương thức time () và timeEnd () giúp phân tích hiệu suất của các đoạn mã của bạn.

Đây không phải là một giải pháp cho sản xuất nhưng nó có thể được sử dụng khi bạn không có công cụ tốt hơn.

Cảm ơn vi đa danh thơi gian cho tôi.
Hãy đăng ký để nhận thư mới từ tôi

Các bài viết tuyệt vời khác về chủ đề tương tự:

  1. https://microservice.io
  2. https://docs.microsoft.com/en-us/dotn