Node.js là gì? [đóng cửa]


506

Tôi không nhận được đầy đủ những gì Node.js là gì. Có lẽ bởi vì tôi chủ yếu là một nhà phát triển ứng dụng kinh doanh dựa trên web. Nó là gì và công dụng của nó là gì?

Sự hiểu biết của tôi cho đến nay là:

  1. Các mô hình lập trình là sự kiện điều khiển, đặc biệt là cách nó xử lý I / O .
  2. Nó sử dụng JavaScript và trình phân tích cú pháp là V8 .
  3. Nó có thể dễ dàng được sử dụng để tạo các ứng dụng máy chủ đồng thời.

Những hiểu biết của tôi có đúng không? Nếu có, thì lợi ích của I / O có sự kiện là gì, nó chỉ hơn đối với các công cụ tương tranh? Ngoài ra, hướng của Node.js có trở thành một khung như mô hình lập trình dựa trên JavaScript (dựa trên V8) không?

Câu trả lời:


213

Tôi nghĩ những lợi thế là:

  1. Phát triển web bằng ngôn ngữ động (JavaScript) trên máy ảo cực nhanh (V8). Nó nhanh hơn nhiều so với Ruby, Python hoặc Perl.

  2. Khả năng xử lý hàng ngàn kết nối đồng thời với chi phí tối thiểu trên một quy trình.

  3. JavaScript là hoàn hảo cho các vòng lặp sự kiện với các đối tượng và đóng hàm chức năng hạng nhất. Mọi người đã biết cách sử dụng nó theo cách này đã sử dụng nó trong trình duyệt để đáp ứng với các sự kiện do người dùng khởi tạo.

  4. Rất nhiều người đã biết JavaScript, ngay cả những người không tự nhận là lập trình viên. Nó được cho là ngôn ngữ lập trình phổ biến nhất.

  5. Sử dụng JavaScript trên máy chủ web cũng như trình duyệt giúp giảm sự không khớp trở kháng giữa hai môi trường lập trình có thể giao tiếp cấu trúc dữ liệu thông qua JSON hoạt động giống nhau trên cả hai mặt của phương trình. Mã xác thực mẫu trùng lặp có thể được chia sẻ giữa máy chủ và máy khách, v.v.


1
@postfuturist: Nó thực sự hoạt động tốt trước rất nhiều lựa chọn thay thế. Nó cũng đánh bại Java 6 khá nhiều trong nhiều trường hợp. Khéo léo!
Adam Crossland

1
@postfuturist Tôi nghĩ bạn đã so sánh với java 6 -Xint. Hãy thử so sánh với máy chủ java 6
fedesilva

@iJK yammer.com là một ứng dụng hoạt động của node.js
Gerard Banasig

1
Thật buồn cười, tôi đã viết JScript bằng ASP 10 năm trước để tôi có thể (a) tránh sự khủng khiếp của VBScript, (b) sử dụng cùng một ngôn ngữ trên máy khách và máy chủ và (c) sử dụng lại thư viện JS của riêng tôi và của người khác để xử lý chuỗi ... vv.
Antony Quinn

4
@ Tại sao bạn chỉ chỉnh sửa bài đăng này cho "Legacy bullshit"? Tôi không nghĩ rằng 212 người sẽ bỏ phiếu cho bài đăng này nếu bạn đã viết bài này ngay từ đầu.
Julien Fouilhé

619

Tôi sử dụng Node.js tại nơi làm việc và thấy nó rất mạnh mẽ. Buộc phải chọn một từ để mô tả Node.js, tôi sẽ nói "thú vị" (đây không phải là tính từ hoàn toàn tích cực). Cộng đồng sôi động và phát triển. JavaScript, mặc dù sự kỳ quặc của nó có thể là một ngôn ngữ tuyệt vời để mã hóa. Và hàng ngày bạn sẽ suy nghĩ lại về sự hiểu biết của riêng bạn về "thực tiễn tốt nhất" và các mẫu mã có cấu trúc tốt. Có một nguồn năng lượng khổng lồ của các ý tưởng chảy vào Node.js ngay bây giờ và làm việc trong đó cho bạn thấy tất cả những suy nghĩ này - cử tạ tinh thần tuyệt vời.

Node.js trong sản xuất chắc chắn là có thể, nhưng khác xa với việc triển khai "chìa khóa trao tay" dường như được tài liệu hứa hẹn. Với Node.js v0.6.x, "cụm" đã được tích hợp vào nền tảng, cung cấp một trong các khối xây dựng thiết yếu, nhưng tập lệnh "sản xuất" của tôi vẫn là ~ 150 dòng logic để xử lý các công việc như tạo nhật ký thư mục, tái chế công nhân đã chết, v.v. Đối với một dịch vụ sản xuất "nghiêm túc", bạn cũng cần chuẩn bị để điều tiết các kết nối đến và làm tất cả những thứ mà Apache làm cho PHP . Công bằng mà nói, Ruby on Rails có vấn đề chính xác này. Nó được giải quyết thông qua hai cơ chế bổ sung: 1) Đưa Ruby vào Rails / Node.Apache sẽ quản lý các quy trình worker, tái chế chúng theo định kỳ, v.v. Tôi vẫn chưa tìm thấy một khung phục vụ Node.js có vẻ như hoàn toàn được nướng; nó có thể tồn tại, nhưng tôi chưa tìm thấy nó và vẫn sử dụng ~ 150 dòng trong "sản xuất" được cuộn bằng tay.Lighttd ). Máy chủ web có thể phục vụ hiệu quả nội dung tĩnh, truy cập ghi nhật ký, viết lại URL, chấm dứt SSL , thực thi các quy tắc truy cập và quản lý nhiều dịch vụ phụ. Đối với các yêu cầu đánh vào dịch vụ nút thực tế, máy chủ web ủy quyền yêu cầu thông qua. 2) Sử dụng khung như Unicorn

Các khung đọc như Express làm cho có vẻ như thông lệ tiêu chuẩn là chỉ phục vụ mọi thứ thông qua một dịch vụ Node.js độc quyền ... "app.use (express.static (__ dirname + '/ public'))" . Đối với các dịch vụ tải thấp và phát triển, điều đó có thể tốt. Nhưng ngay khi bạn cố gắng tải thời gian lớn cho dịch vụ của mình và chạy 24/7, bạn sẽ nhanh chóng khám phá những động lực thúc đẩy các trang web lớn có mã C được làm tốt, cứng như Nginx trước trang web của họ và xử lý tất cả trong số các yêu cầu nội dung tĩnh (... cho đến khi bạn thiết lập CDN , như Amazon CloudFront )). Đối với một chút hài hước và tiêu cực không thể phủ nhận về điều này, xem anh chàng này .

Node.js cũng đang tìm kiếm ngày càng nhiều việc sử dụng phi dịch vụ. Ngay cả khi bạn đang sử dụng một thứ khác để phục vụ nội dung web, bạn vẫn có thể sử dụng Node.js làm công cụ xây dựng, sử dụng các mô-đun npm để tổ chức mã của bạn, Browserify để ghép nó vào một tài sản duy nhất và uglify-js để thu nhỏ nó để triển khai . Để đối phó với web, JavaScript là một kết hợp trở kháng hoàn hảo và thường xuyên làm cho nó trở thành con đường tấn công dễ dàng nhất. Ví dụ: nếu bạn muốn tìm hiểu về một loạt các tải trọng phản hồi JSON , bạn nên sử dụng dấu gạch dưới của tôi -CLI mô-đun , vành đai tiện ích của dữ liệu có cấu trúc.

Ưu / nhược điểm:

  • Pro: Đối với một anh chàng máy chủ, viết JavaScript trên phụ trợ đã là một "liều thuốc" để học các mẫu UI hiện đại. Tôi không còn sợ viết mã khách hàng.
  • Pro: Có xu hướng khuyến khích kiểm tra lỗi thích hợp (err được trả về bởi hầu như tất cả các cuộc gọi lại, cằn nhằn lập trình viên để xử lý nó, đồng thời, async.js và các thư viện khác xử lý "thất bại nếu bất kỳ nhiệm vụ nào trong số này không thành công" )
  • Pro: Một số tác vụ thú vị và thông thường khó trở nên tầm thường - như nhận trạng thái trên các tác vụ trong chuyến bay, liên lạc giữa các nhân viên hoặc chia sẻ trạng thái bộ nhớ cache
  • Pro: Cộng đồng khổng lồ và hàng tấn thư viện tuyệt vời dựa trên trình quản lý gói vững chắc (npm)
  • Con: JavaScript không có thư viện chuẩn. Bạn đã quen với việc nhập chức năng đến mức cảm thấy kỳ lạ khi bạn sử dụng JSON.parse hoặc một số phương thức xây dựng khác không yêu cầu thêm mô-đun npm. Điều này có nghĩa là có năm phiên bản của tất cả mọi thứ. Ngay cả các mô-đun có trong "lõi" của Node.js cũng có thêm năm biến thể nếu bạn không hài lòng với việc triển khai mặc định. Điều này dẫn đến sự tiến hóa nhanh chóng, nhưng cũng có một số mức độ nhầm lẫn.

So với mô hình một quy trình một yêu cầu đơn giản ( LAMP ):

  • Pro: Có thể mở rộng đến hàng ngàn kết nối hoạt động. Rất nhanh và rất hiệu quả. Đối với một nhóm web, điều này có thể có nghĩa là giảm 10 lần số lượng hộp cần thiết so với PHP hoặc Ruby
  • Pro: Viết các mẫu song song rất dễ dàng. Hãy tưởng tượng rằng bạn cần tìm nạp ba (hoặc N) đốm từ Memcached . Làm điều này trong PHP ... bạn vừa viết mã tìm nạp blob đầu tiên, sau đó thứ hai, sau đó thứ ba? Wow, thật chậm. Có một PECL đặc biệt mô-đun để khắc phục sự cố cụ thể đó cho Memcached, nhưng nếu bạn muốn lấy một số dữ liệu Memcached song song với truy vấn cơ sở dữ liệu của bạn thì sao? Trong Node.js, vì mô hình không đồng bộ, nên việc yêu cầu web thực hiện nhiều việc song song là điều rất tự nhiên.
  • Con: Mã không đồng bộ về cơ bản phức tạp hơn mã đồng bộ và đường cong học tập phía trước có thể gây khó khăn cho các nhà phát triển nếu không có sự hiểu biết vững chắc về việc thực thi đồng thời thực sự có nghĩa là gì. Tuy nhiên, nó khó hơn rất nhiều so với việc viết bất kỳ loại mã đa luồng nào có khóa.
  • Con: Nếu một yêu cầu chuyên sâu tính toán chạy, ví dụ 100 ms, nó sẽ trì hoãn việc xử lý các yêu cầu khác đang được xử lý trong cùng quy trình Node.js ... AKA, đa nhiệm hợp tác . Điều này có thể được giảm thiểu bằng mẫu Công nhân web (loại bỏ một quy trình con để xử lý công việc đắt tiền). Ngoài ra, bạn có thể sử dụng một số lượng lớn nhân viên Node.js và chỉ cho phép mỗi người xử lý một yêu cầu đồng thời (vẫn khá hiệu quả vì không có quy trình tái chế).
  • Con: Vận hành một hệ thống sản xuất phức tạp hơn nhiều so với mô hình CGI như Apache + PHP, Perl , Ruby , v.v. Các ngoại lệ không được xử lý sẽ làm giảm toàn bộ quy trình, đòi hỏi phải logic để khởi động lại các công nhân thất bại (xem cụm ). Các mô-đun với mã gốc lỗi có thể làm hỏng quá trình. Bất cứ khi nào một công nhân chết, mọi yêu cầu mà nó đang xử lý đều bị loại bỏ, do đó, một API lỗi có thể dễ dàng làm giảm dịch vụ cho các API được lưu trữ khác.

Versus viết một dịch vụ "thực" trong Java / C # / C (C? Thật sao?)

  • Pro: Thực hiện không đồng bộ trong Node.js dễ dàng hơn so với thực hiện an toàn luồng ở bất kỳ nơi nào khác và được cho là mang lại lợi ích lớn hơn. Node.js cho đến nay là mô hình không đồng bộ ít đau đớn nhất mà tôi từng làm việc. Với các thư viện tốt, nó chỉ khó hơn một chút so với viết mã đồng bộ.
  • Pro: Không có lỗi đa luồng / khóa. Đúng, bạn đầu tư trước để viết thêm mã dài dòng thể hiện một quy trình làm việc không đồng bộ thích hợp mà không có hoạt động chặn. Và bạn cần phải viết một số bài kiểm tra và làm cho nó hoạt động (đó là một ngôn ngữ kịch bản và các tên biến ngón tay mập chỉ được bắt gặp tại thời điểm kiểm tra đơn vị). NHƯNG, một khi bạn làm cho nó hoạt động, diện tích bề mặt cho heisenbugs - những vấn đề kỳ lạ chỉ xuất hiện một lần trong một triệu lần chạy - diện tích bề mặt đó chỉ thấp hơn nhiều. Các loại thuế viết mã Node.js được tải trước vào giai đoạn mã hóa. Sau đó, bạn có xu hướng kết thúc với mã ổn định.
  • Pro: JavaScript nhẹ hơn nhiều để thể hiện chức năng. Thật khó để chứng minh điều này bằng các từ, nhưng JSON , gõ động, ký hiệu lambda, kế thừa nguyên mẫu, mô-đun nhẹ, bất cứ điều gì ... nó chỉ có xu hướng mất ít mã hơn để diễn đạt cùng một ý tưởng.
  • Con: Có lẽ bạn thực sự, thực sự thích các dịch vụ mã hóa trong Java?

Để có góc nhìn khác về JavaScript và Node.js, hãy xem Từ Java đến Node.js , một bài đăng trên blog về ấn tượng và kinh nghiệm của nhà phát triển Java khi học Node.js.


Modules Khi xem xét nút, hãy ghi nhớ rằng sự lựa chọn của bạn của các thư viện JavaScript sẽ DEFINE kinh nghiệm của bạn. Hầu hết mọi người sử dụng ít nhất hai, một trình trợ giúp mẫu không đồng bộ (Bước, Tương lai, Không đồng bộ) và mô-đun đường JavaScript ( Underscore.js ).

Trình trợ giúp / Đường JavaScript:

  • Underscore.js - sử dụng cái này. Cứ làm đi. Nó làm cho mã của bạn đẹp và dễ đọc với những thứ như _.isString () và _.isArray (). Tôi không thực sự chắc chắn làm thế nào bạn có thể viết mã an toàn khác. Ngoài ra, để tăng cường dòng lệnh-fu, hãy kiểm tra riêng của tôi Underscore-CLI .

Mô-đun mẫu không đồng bộ:

  • Bước - một cách rất thanh lịch để thể hiện sự kết hợp của các hành động nối tiếp và song song. Giới thiệu cá nhân của tôi. Xem bài viết của tôi về mã Bước trông như thế nào.
  • Tương lai - cách linh hoạt hơn nhiều (đó có thực sự là một điều tốt?) Để thể hiện trật tự thông qua các yêu cầu. Có thể diễn tả những điều như "bắt đầu a, b, c song song. Khi A và B kết thúc, bắt đầu AB. Khi A và C kết thúc, bắt đầu AC." Tính linh hoạt như vậy đòi hỏi nhiều sự cẩn thận hơn để tránh các lỗi trong quy trình làm việc của bạn (như không bao giờ gọi lại hoặc gọi nó nhiều lần). Xem bài đăng của Raynos về việc sử dụng hợp đồng tương lai (đây là bài đăng khiến tôi "có được" tương lai).
  • Async - thư viện truyền thống hơn với một phương thức cho mỗi mẫu. Tôi đã bắt đầu với điều này trước khi chuyển đổi tôn giáo sang bước và nhận ra rằng tất cả các mẫu trong Async có thể được thể hiện trong Bước với một mô hình dễ đọc hơn.
  • TameJS - Được viết bởi OKCool, đó là một trình biên dịch trước có thêm một nguyên tắc ngôn ngữ mới "chờ đợi" để viết các quy trình công việc nối tiếp và song song một cách tao nhã. Các mô hình trông tuyệt vời, nhưng nó đòi hỏi phải biên dịch trước. Tôi vẫn đang quyết định về điều này.
  • StreamlineJS - đối thủ của TameJS. Tôi đang nghiêng về Tame, nhưng bạn có thể tự quyết định.

Hoặc để đọc tất cả về các thư viện không đồng bộ, hãy xem bảng phỏng vấn này với các tác giả.

Khung web:

  • Express Great Ruby on Rails-esk framework để tổ chức các trang web. Nó sử dụng JADE làm công cụ tạo khuôn mẫu XML / HTML, giúp xây dựng HTML ít đau đớn hơn, thậm chí gần như thanh lịch.
  • jQuery Mặc dù về mặt kỹ thuật không phải là một mô-đun nút, jQuery nhanh chóng trở thành một tiêu chuẩn thực tế cho giao diện người dùng phía máy khách. jQuery cung cấp các bộ chọn giống như CSS để 'truy vấn' cho các bộ phần tử DOM có thể được vận hành trên đó (đặt bộ xử lý, thuộc tính, kiểu, v.v.). Cùng quan điểm, khung CSS Bootstrap của Twitter , Backbone.js cho mẫu MVCBrowserify.js để ghép tất cả các tệp JavaScript của bạn vào một tệp. Các mô-đun này đều đang trở thành tiêu chuẩn thực tế, vì vậy ít nhất bạn nên kiểm tra chúng nếu bạn chưa nghe về chúng.

Kiểm tra:

  • JSHint - Phải sử dụng; Tôi đã không sử dụng điều này lúc đầu mà bây giờ dường như không thể hiểu được. JSLint bổ sung lại một loạt các xác minh cơ bản bạn có được với một ngôn ngữ được biên dịch như Java. Dấu ngoặc không khớp, biến không được khai báo, kiểu chữ có nhiều hình dạng và kích cỡ. Bạn cũng có thể bật các dạng khác nhau của cái mà tôi gọi là "chế độ hậu môn" trong đó bạn xác minh kiểu khoảng trắng và không có gì, sẽ ổn nếu đó là tách trà của bạn - nhưng giá trị thực sự đến từ việc nhận phản hồi tức thì về số dòng chính xác trong đó bạn đã quên đóng ")" ... mà không phải chạy mã của mình và nhấn vào dòng vi phạm. "JSHint" là một biến thể có cấu hình cao hơn của JSLint của Douglas Crockford .
  • Mocha là đối thủ của Nguyện mà tôi bắt đầu thích. Cả hai khung xử lý đủ cơ bản, nhưng các mẫu phức tạp có xu hướng dễ thể hiện hơn trong Mocha.
  • Vows Vows thực sự khá thanh lịch. Và nó in ra một báo cáo đáng yêu (--spec) cho bạn thấy những trường hợp thử nghiệm đã vượt qua / thất bại. Dành 30 phút để học nó và bạn có thể tạo các bài kiểm tra cơ bản cho các mô-đun của mình với nỗ lực tối thiểu.
  • Zombie - Thử nghiệm không đầu cho HTML và JavaScript bằng JSDom làm "trình duyệt" ảo. Công cụ rất mạnh mẽ. Kết hợp nó với Phát lại để có được các bài kiểm tra xác định nhanh về mã trong trình duyệt.
  • Một nhận xét về cách "nghĩ về" thử nghiệm:
    • Kiểm tra là không tùy chọn. Với một ngôn ngữ động như JavaScript, có rất ít kiểm tra tĩnh. Ví dụ: truyền hai tham số cho một phương thức dự kiến ​​4 sẽ không bị hỏng cho đến khi mã được thực thi. Thanh khá thấp để tạo lỗi trong JavaScript. Các bài kiểm tra cơ bản là rất cần thiết để tạo khoảng cách xác minh với các ngôn ngữ được biên dịch.
    • Quên xác nhận, chỉ cần làm cho mã của bạn thực thi. Đối với mọi phương pháp, trường hợp xác nhận đầu tiên của tôi là "không có gì phá vỡ" và đó là trường hợp xảy ra thường xuyên nhất. Chứng minh rằng mã của bạn chạy mà không ném bắt được 80% lỗi và sẽ làm rất nhiều để cải thiện sự tự tin của mã mà bạn sẽ thấy mình quay lại và thêm các trường hợp xác thực sắc thái mà bạn bỏ qua.
    • Bắt đầu nhỏ và phá vỡ rào cản quán tính. Tất cả chúng ta đều lười biếng và bị ép thời gian, và thật dễ dàng để xem thử nghiệm là "công việc làm thêm". Vì vậy, bắt đầu nhỏ. Viết trường hợp kiểm tra 0 - tải mô-đun của bạn và báo cáo thành công. Nếu bạn buộc bản thân phải làm điều này nhiều, thì rào cản quán tính để kiểm tra đã bị phá vỡ. Đó là <30 phút để làm điều đó lần đầu tiên của bạn, bao gồm cả việc đọc tài liệu. Bây giờ hãy viết test case 1 - gọi một trong các phương thức của bạn và xác minh "không có gì phá vỡ", nghĩa là bạn không nhận được lỗi. Trường hợp thử nghiệm 1 sẽ đưa bạn ít hơn một phút. Khi quán tính biến mất, việc tăng dần phạm vi kiểm tra của bạn trở nên dễ dàng.
    • Bây giờ phát triển các bài kiểm tra của bạn với mã của bạn. Đừng bị đe dọa bởi thử nghiệm đầu cuối "chính xác" sẽ như thế nào với các máy chủ giả và tất cả những thứ đó. Mã bắt đầu đơn giản và phát triển để xử lý các trường hợp mới; xét nghiệm cũng vậy. Khi bạn thêm các trường hợp mới và độ phức tạp mới vào mã của bạn, hãy thêm các trường hợp thử nghiệm để thực hiện mã mới. Khi bạn tìm thấy lỗi, hãy thêm xác minh và / hoặc trường hợp mới để bao gồm mã bị lỗi. Khi bạn đang gỡ lỗi và mất niềm tin vào một đoạn mã, hãy quay lại và thêm các bài kiểm tra để chứng minh rằng nó đang làm những gì bạn nghĩ. Nắm bắt các chuỗi dữ liệu mẫu (từ các dịch vụ khác mà bạn gọi, các trang web bạn cạo, bất cứ thứ gì) và đưa chúng vào mã phân tích của bạn. Một vài trường hợp ở đây, cải thiện xác nhận ở đó, và bạn sẽ kết thúc với mã có độ tin cậy cao.

Ngoài ra, hãy xem danh sách chính thức của các mô-đun Node.js được đề xuất. Tuy nhiên, Node Modules Wiki của GitHub hoàn thiện hơn nhiều và là một tài nguyên tốt.


Để hiểu Node, thật hữu ích khi xem xét một vài lựa chọn thiết kế chính:

Node.js là sự kiện dựakhông đồng bộ / non-blocking. Các sự kiện, như kết nối HTTP đến sẽ kích hoạt chức năng JavaScript thực hiện một chút công việc và khởi động các tác vụ không đồng bộ khác như kết nối với cơ sở dữ liệu hoặc lấy nội dung từ máy chủ khác. Khi các tác vụ này được khởi động, chức năng sự kiện kết thúc và Node.js trở lại trạng thái ngủ. Ngay khi có điều gì đó khác xảy ra, như kết nối cơ sở dữ liệu được thiết lập hoặc máy chủ bên ngoài phản hồi với nội dung, các hàm gọi lại sẽ thực thi và nhiều mã JavaScript thực thi hơn, có khả năng khởi động các tác vụ không đồng bộ hơn (như truy vấn cơ sở dữ liệu). Theo cách này, Node.js sẽ vui vẻ xen kẽ các hoạt động cho nhiều quy trình công việc song song, chạy bất kỳ hoạt động nào được bỏ chặn tại bất kỳ thời điểm nào. Đây là lý do tại sao Node.js thực hiện một công việc tuyệt vời như vậy để quản lý hàng ngàn kết nối đồng thời.

Tại sao không chỉ sử dụng một tiến trình / luồng trên mỗi kết nối như mọi người khác?Trong Node.js, một kết nối mới chỉ là một phân bổ heap rất nhỏ. Quay lên một quy trình mới cần nhiều bộ nhớ hơn, một megabyte trên một số nền tảng. Nhưng chi phí thực sự là chi phí liên quan đến chuyển đổi ngữ cảnh. Khi bạn có 10 ^ 6 kernel kernel, kernel phải thực hiện rất nhiều công việc để tìm ra ai sẽ thực thi tiếp theo. Một nhóm công việc đã đi vào việc xây dựng một bộ lập lịch O (1) cho Linux, nhưng cuối cùng, cách hiệu quả hơn là có một quy trình hướng sự kiện duy nhất hơn 10 ^ 6 quy trình cạnh tranh về thời gian của CPU. Ngoài ra, trong điều kiện quá tải, mô hình đa quy trình hoạt động rất kém, bỏ đói các dịch vụ quản lý và quản lý quan trọng, đặc biệt là SSHD (có nghĩa là bạn thậm chí không thể đăng nhập vào hộp để tìm hiểu xem nó thực sự bị hỏng như thế nào).

Node.js SINGLE THREADEDKHÓA MIỄN PHÍ . Node.js, như một lựa chọn thiết kế rất có chủ ý chỉ có một luồng duy nhất cho mỗi quy trình. Do đó, về cơ bản, nhiều luồng không thể truy cập dữ liệu cùng lúc. Vì vậy, không cần khóa. Chủ đề là khó khăn. Thực sự rất khó. Nếu bạn không tin điều đó, bạn đã không thực hiện đủ chương trình luồng. Bắt khóa đúng là khó và dẫn đến các lỗi thực sự khó theo dõi. Loại bỏ các khóa và đa luồng làm cho một trong những lớp lỗi khó chịu nhất biến mất. Đây có thể là lợi thế lớn nhất của nút.

Nhưng làm thế nào để tôi tận dụng hộp 16 lõi của mình?

Hai lối:

  1. Đối với các tác vụ tính toán lớn như mã hóa hình ảnh, Node.js có thể kích hoạt các tiến trình con hoặc gửi tin nhắn đến các tiến trình công nhân bổ sung. Trong thiết kế này, bạn sẽ có một luồng quản lý luồng sự kiện và N tiến trình thực hiện các tác vụ tính toán nặng và nhai 15 CPU khác.
  2. Để mở rộng thông lượng trên dịch vụ web, bạn nên chạy nhiều máy chủ Node.js trên một hộp, mỗi lõi, sử dụng cụm (Với Node.js v0.6.x, mô-đun "cụm" chính thức được liên kết ở đây thay thế phiên bản learnboost có một API khác nhau). Các máy chủ Node.js cục bộ này sau đó có thể cạnh tranh trên một ổ cắm để chấp nhận các kết nối mới, cân bằng tải trên chúng. Khi một kết nối được chấp nhận, nó sẽ bị ràng buộc chặt chẽ với một trong những quy trình được chia sẻ này. Về lý thuyết, điều này nghe có vẻ tệ, nhưng trong thực tế, nó hoạt động khá tốt và cho phép bạn tránh đau đầu khi viết mã an toàn cho chuỗi. Ngoài ra, điều này có nghĩa là Node.js có được mối quan hệ bộ đệm CPU tuyệt vời, sử dụng băng thông bộ nhớ hiệu quả hơn.

Node.js cho phép bạn thực hiện một số điều thực sự mạnh mẽ mà không bị đổ mồ hôi. Giả sử bạn có một chương trình Node.js thực hiện nhiều nhiệm vụ khác nhau, lắng nghe trêncổng TCP để nhận lệnh, mã hóa một số hình ảnh, bất cứ điều gì. Với năm dòng mã, bạn có thể thêm vào một cổng quản lý web dựa trên HTTP để hiển thị trạng thái hiện tại của các tác vụ đang hoạt động. Điều này rất dễ làm:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(myJavascriptObject.getSomeStatusInfo());
}).listen(1337, "127.0.0.1");

Bây giờ bạn có thể nhấn một URL và kiểm tra trạng thái của quá trình đang chạy của bạn. Thêm một vài nút và bạn có một "cổng thông tin quản lý". Nếu bạn có tập lệnh Perl / Python / Ruby đang chạy, chỉ cần "ném vào cổng quản lý" là không chính xác.

Nhưng không phải JavaScript chậm / xấu / xấu / sinh sản của quỷ sao? JavaScript có một số điểm kỳ lạ, nhưng với "những phần hay" thì có một ngôn ngữ rất mạnh ở đó và trong mọi trường hợp, JavaScript là ngôn ngữ trên máy khách (trình duyệt). JavaScript ở đây để ở lại; các ngôn ngữ khác đang nhắm mục tiêu nó như một IL và tài năng đẳng cấp thế giới đang cạnh tranh để tạo ra các công cụ JavaScript tiên tiến nhất. Do vai trò của JavaScript trong trình duyệt, một lượng lớn nỗ lực kỹ thuật đang bị ném vào khiến JavaScript phát sáng nhanh. V8là công cụ javascript mới nhất và lớn nhất, ít nhất là trong tháng này. Nó thổi bay các ngôn ngữ kịch bản khác về cả tính hiệu quả và tính ổn định (nhìn vào bạn, Ruby). Và nó sẽ chỉ trở nên tốt hơn với các nhóm khổng lồ giải quyết vấn đề tại Microsoft, Google và Mozilla, cạnh tranh để xây dựng công cụ JavaScript tốt nhất (Nó không còn là "trình thông dịch" JavaScript vì tất cả các công cụ hiện đại tạo ra hàng tấn JITbiên dịch dưới mui xe với giải thích chỉ là một dự phòng cho mã thực thi một lần). Vâng, tất cả chúng ta đều ước mình có thể sửa một vài lựa chọn ngôn ngữ JavaScript kỳ quặc, nhưng nó thực sự không tệ đến thế. Và ngôn ngữ rất linh hoạt đến nỗi bạn thực sự không mã hóa JavaScript, bạn đang mã hóa Bước hoặc jQuery - hơn bất kỳ ngôn ngữ nào khác, trong JavaScript, các thư viện xác định trải nghiệm. Để xây dựng các ứng dụng web, dù sao bạn cũng phải biết nhiều về JavaScript, do đó, mã hóa với nó trên máy chủ có một loại sức mạnh tổng hợp được thiết lập kỹ năng. Nó đã làm cho tôi không sợ viết mã khách hàng.

Ngoài ra, nếu bạn THỰC SỰ ghét JavaScript, bạn có thể sử dụng đường cú pháp như CoffeeScript . Hoặc bất cứ điều gì khác tạo mã JavaScript, như Google Web Toolkit (GWT).

Nói về JavaScript, "đóng cửa" là gì? - Khá nhiều cách để nói rằng bạn giữ các biến có phạm vi từ vựng trong các chuỗi cuộc gọi. ;) Như thế này:

var myData = "foo";
database.connect( 'user:pass', function myCallback( result ) {
    database.query("SELECT * from Foo where id = " + myData);
} );
// Note that doSomethingElse() executes _BEFORE_ "database.query" which is inside a callback
doSomethingElse();

Xem làm thế nào bạn có thể chỉ sử dụng "myData" mà không làm điều gì khó xử như đâm nó vào một đối tượng? Và không giống như trong Java, biến "myData" không phải chỉ đọc. Tính năng ngôn ngữ mạnh mẽ này giúp lập trình không đồng bộ ít dài dòng hơn và ít đau đớn hơn.

Viết mã không đồng bộ luôn phức tạp hơn so với viết một tập lệnh đơn luồng đơn giản, nhưng với Node.js, nó không khó hơn nhiều và bạn nhận được rất nhiều lợi ích ngoài hiệu quả và khả năng mở rộng cho hàng ngàn kết nối đồng thời. ..


"Biến 'myData' không nhất thiết phải chỉ đọc" - có vẻ như bạn muốn giữ nó bất biến hầu hết thời gian để ngăn chặn các vấn đề tương tranh, phải không?
Nick

1
@Nick - đó là sai. "Các vấn đề tương tranh" được giảm thiểu bởi thực tế là nút là luồng đơn. Khóa trong nút đơn giản là không tồn tại; nó không cần thiết trong một mô hình đơn luồng.
Dave Dopson


1
ps, lưu ý phụ - Tôi thực sự đã chỉnh sửa nó đủ lần để bài đăng trở thành "wiki cộng đồng" (ngưỡng là 10 lần chỉnh sửa). Tôi đã lầm tưởng đây là một loại danh dự, khi thực sự nó chỉ ngăn chặn việc đạt được danh tiếng từ những người ủng hộ. Cuối cùng, một trong những cử tri trước CW đã nhấp vào "unvote" (hy vọng, do vô tình :) và tôi bị mất danh tiếng ... tôi đã nhầm lẫn đã nộp meta.stackexchange.com/questions/129941/ và được học trong "Cộng đồng Wiki "thực sự có nghĩa là. Mod đã đủ tốt để loại bỏ trạng thái CW. :)
Dave Dopson

1
@ John - bình luận gỡ lỗi của tôi hoàn toàn áp dụng cho vanilla asnyc. Để ngắt gỡ lỗi, tất cả những gì tôi cần làm là bọc một số lệnh gọi hàm trong "process.nextTick (...)". Sau đó, khi nó ném, theo dõi ngăn xếp của tôi sẽ bắt đầu với process.nextTick; không hữu ích lắm Điều tôi thực sự muốn biết là: "ngăn xếp nào được lên lịch process.nextTick?" Tôi gọi dữ liệu đó là "chuỗi nhân quả" và nó nhắc tôi về 'gây raBy' trong xử lý ngoại lệ Java ... ném mã mức thấp, mã trung cấp bắt ngoại lệ LL và ném FrameworkMethodFailedException - không có 'gây raBy', ngăn xếp từ LL mã sẽ bị mất.
Dave Dopson

85

V8 là một triển khai của JavaScript. Nó cho phép bạn chạy các ứng dụng JavaScript độc lập (trong số những thứ khác).

Node.js đơn giản là một thư viện được viết cho V8, có sự kiện I / O. Khái niệm này khó giải thích hơn một chút và tôi chắc chắn ai đó sẽ trả lời với lời giải thích tốt hơn tôi ... Ý chính là thay vì thực hiện một số đầu vào hoặc đầu ra và chờ đợi nó xảy ra, bạn đừng chờ đợi cho nó kết thúc Vì vậy, ví dụ, yêu cầu thời gian chỉnh sửa cuối cùng của tệp:

// Pseudo code
stat( 'somefile' )

Điều đó có thể mất vài mili giây hoặc có thể mất vài giây. Với I / O được sự kiện, bạn chỉ cần thực hiện yêu cầu và thay vì chờ đợi xung quanh bạn đính kèm một cuộc gọi lại được chạy khi yêu cầu kết thúc:

// Pseudo code
stat( 'somefile', function( result ) {
  // Use the result here
} );
// ...more code here

Điều này làm cho nó rất giống mã JavaScript trong trình duyệt (ví dụ: với chức năng kiểu Ajax ).

Để biết thêm thông tin, bạn nên xem bài viết Node.js thực sự thú vị , đó là phần giới thiệu của tôi về thư viện / nền tảng ... Tôi thấy nó khá hay.


4
IO được tổ chức như thế nào mà không sử dụng khóa, sử dụng luồng, xử lý, đóng? Và tôi có cảm giác rằng các khái niệm này khá giống với lập trình chức năng và Erlang.
Jeff

1
Nó được thực hiện như một vòng lặp sự kiện đơn giản, theo như tôi biết. v8 đã có chức năng gọi lại / etc, giống như bất kỳ triển khai javascript nào.
rfunduk

2
Vòng lặp sự kiện IO của node.js có nghĩa là tại bất kỳ thời điểm nào, nhiều nhất chỉ có một việc đang được thực hiện. Tôi thấy hai mức tăng đáng kể: Không có chi phí chuyển đổi luồng, do đó, node.js rất nhanh và thứ hai là nhiều lỗi đồng thời điển hình mà Java nổi tiếng là không thể.
nalply

1
"IO được tổ chức như thế nào mà không sử dụng ... đóng cửa?" JavaScript hỗ trợ các bao đóng và chúng được sử dụng mọi lúc trong node.js (các hàm ẩn danh ans trong ví dụ ở đây).
panzi

@panzi: Không nhận thấy Jeffrey bao gồm các bao đóng trong danh sách những thứ mà node.js được triển khai 'không có'. Rõ ràng mọi chức năng trong javascript đều đóng cửa trong phạm vi của nó :)
rfunduk

35

Node.js là một công cụ dòng lệnh mã nguồn mở được xây dựng cho mã JavaScript phía máy chủ. Bạn có thể tải xuống một tarball , biên dịch và cài đặt nguồn. Nó cho phép bạn chạy các chương trình JavaScript.

JavaScript được thực thi bởi V8 , một công cụ JavaScript được phát triển bởi Google, được sử dụng trong trình duyệt Chrome . Nó sử dụng API JavaScript để truy cập mạng và hệ thống tệp.

Nó là phổ biến cho hiệu suất của nó và khả năng thực hiện các hoạt động song song.

Hiểu về node.js là cách giải thích tốt nhất về node.js mà tôi đã tìm thấy cho đến nay.

Sau đây là một số bài viết tốt về chủ đề này.


13

Việc đóng cửa là một cách để thực thi mã trong bối cảnh nó được tạo ra.

Điều này có nghĩa gì cho sự đồng nhất là bạn có thể xác định các biến, sau đó khởi tạo hàm I / O không chặn và gửi cho nó một hàm ẩn danh cho cuộc gọi lại của nó.

Khi tác vụ hoàn thành, hàm gọi lại sẽ thực thi trong ngữ cảnh với các biến, đây là bao đóng.

Lý do đóng cửa rất tốt cho việc viết các ứng dụng với I / O không chặn là vì nó rất dễ quản lý bối cảnh của các hàm thực thi không đồng bộ.


8

Hai ví dụ điển hình liên quan đến cách bạn quản lý các mẫu và sử dụng các cải tiến lũy tiến với nó. Bạn chỉ cần một vài đoạn mã JavaScript nhẹ để làm cho nó hoạt động hoàn hảo.

Tôi thực sự khuyên bạn nên xem và đọc những bài viết này:

Chọn bất kỳ ngôn ngữ nào và cố gắng nhớ cách bạn sẽ quản lý các mẫu tệp HTML của mình và những gì bạn phải làm để cập nhật một ngôn ngữ tên lớp CSS trong cấu trúc DOM của bạn (ví dụ: người dùng đã nhấp vào một mục menu và bạn muốn đánh dấu là "Đã chọn" và cập nhật nội dung của trang).

Với Node.js, nó đơn giản như thực hiện nó trong mã JavaScript phía máy khách. Nhận nút DOM của bạn và áp dụng lớp CSS của bạn cho điều đó. Nhận nút DOM của bạn và bên trongHTML nội dung của bạn (bạn sẽ cần một số mã JavaScript bổ sung để thực hiện việc này. Đọc bài viết để biết thêm).

Một ví dụ điển hình khác là bạn có thể làm cho trang web của mình tương thích cả với JavaScript được bật hoặc tắt với cùng một đoạn mã. Hãy tưởng tượng bạn có một lựa chọn ngày được thực hiện bằng JavaScript cho phép người dùng của bạn chọn bất kỳ ngày nào bằng lịch. Bạn có thể viết (hoặc sử dụng) cùng một đoạn mã JavaScript để làm cho nó hoạt động với mã JavaScript của bạn được BẬT hoặc TẮT.


7

Có một sự tương tự nơi thức ăn nhanh rất tốt giải thích tốt nhất mô hình hướng sự kiện của Node.js, xem toàn bộ bài viết, Node.js, Văn phòng bác sĩ và Nhà hàng thức ăn nhanh - Hiểu về lập trình hướng sự kiện

Đây là một bản tóm tắt:

Nếu doanh nghiệp đồ ăn nhanh tuân theo mô hình dựa trên chủ đề truyền thống, bạn sẽ đặt hàng thực phẩm của mình và xếp hàng chờ đợi cho đến khi bạn nhận được. Người đứng sau bạn sẽ không thể đặt hàng cho đến khi đơn hàng của bạn được thực hiện. Trong một mô hình hướng sự kiện, bạn đặt món ăn của bạn và sau đó ra khỏi hàng để chờ đợi. Mọi người khác sau đó được miễn phí để đặt hàng.

Node.js được điều khiển theo sự kiện, nhưng hầu hết các máy chủ web đều dựa trên luồng .York giải thích cách Node.js hoạt động:

  • Bạn sử dụng trình duyệt web của mình để thực hiện yêu cầu "/about.html" trên máy chủ web Node.js.

  • Máy chủ Node.js chấp nhận yêu cầu của bạn và gọi một hàm để lấy tệp đó từ đĩa.

  • Trong khi máy chủ Node.js đang chờ lấy tệp, nó sẽ phục vụ yêu cầu web tiếp theo.

  • Khi tệp được truy xuất, có một hàm gọi lại được chèn vào hàng đợi máy chủ Node.js.

  • Máy chủ Node.js thực thi chức năng đó trong trường hợp này sẽ hiển thị trang "/about.html" và gửi lại cho trình duyệt web của bạn. "


6

Ồ, tôi hiểu điều đó

  • Mục tiêu của Node là cung cấp một cách dễ dàng để xây dựng các chương trình mạng có thể mở rộng.
  • Node có thiết kế tương tự và bị ảnh hưởng bởi các hệ thống như Máy sự kiện của Ruby hoặc Twisted của Python.
  • Sự kiện I / O cho javascript V8.

Đối với tôi điều đó có nghĩa là bạn đã đúng trong cả ba giả định. Thư viện chắc chắn có triển vọng!


1
Rất nhiều lần tôi tìm thấy về trang khá mơ hồ.
Jeff

6

Ngoài ra, đừng quên đề cập rằng V8 của Google RẤT nhanh. Nó thực sự chuyển đổi mã JavaScript thành mã máy với hiệu năng khớp nhị phân được biên dịch. Vì vậy, cùng với tất cả những điều tuyệt vời khác, nó KHÔNG BAO GIỜ nhanh chóng.


3

Q: Các mô hình lập trình được sự kiện điều khiển, đặc biệt là cách nó xử lý I / O .

Chính xác. Nó sử dụng các cuộc gọi lại, vì vậy mọi yêu cầu truy cập hệ thống tệp sẽ khiến yêu cầu được gửi đến hệ thống tệp và sau đó Node.js sẽ bắt đầu xử lý yêu cầu tiếp theo của nó. Nó chỉ lo lắng về yêu cầu I / O khi nó nhận được phản hồi từ hệ thống tệp, tại thời điểm đó nó sẽ chạy mã gọi lại. Tuy nhiên, có thể thực hiện các yêu cầu I / O đồng bộ (nghĩa là chặn các yêu cầu). Nhà phát triển phải lựa chọn giữa không đồng bộ (gọi lại) hoặc đồng bộ (chờ).

H: Nó sử dụng JavaScript và trình phân tích cú pháp là V8.

Đúng

Q: Nó có thể dễ dàng được sử dụng để tạo các ứng dụng máy chủ đồng thời.

Có, mặc dù bạn cần mã hóa khá nhiều JavaScript. Có thể tốt hơn để xem xét một khung, chẳng hạn như http://www.easynodejs.com/ - đi kèm với tài liệu trực tuyến đầy đủ và một ứng dụng mẫu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.