1 от имени
Появляется все больше и больше технических отчетов о Node.js, и существуют различные способы написания Node.js. Некоторые из них написаны на NodeJS, а некоторые — на Nodejs. Какой из способов написания является наиболее стандартным, мы могли бы также следовать официальное заявление. в Node.jsОфициальный сайтначальство,一直将其项目称之为”Node“或者”Node.js“
, других слов я не нашел, "узел" используется чаще всего, учитывая, что значение и использование слова "узел" слишком широкое, разработчикам легко его неправильно понять,我们采用了第二种称呼——”Node.js“,js的后缀点出了Node项目的本意
, Остальные названия разные, точного источника нет, не рекомендуем их использовать.
2 Какую проблему призван решить Node
Заявленная цель Node состоит в том, чтобы“旨在提供一种简单的构建可伸缩网络程序的方法”
. Что не так с текущей серверной программой? Давайте решим математическую задачу. В таких языках, как Java™ и PHP, каждое соединение порождает новый поток, и для каждого нового потока может потребоваться 2 МБ сопутствующей памяти. В системе с 8 ГБ ОЗУ теоретическое максимальное количество одновременных подключений составляет 4000 пользователей. По мере роста вашей клиентской базы вы должны добавлять больше серверов, если хотите, чтобы ваше веб-приложение поддерживало больше пользователей. Конечно, это увеличивает затраты, такие как стоимость сервера, стоимость трафика и затраты на оплату труда. В дополнение к этим растущим затратам существует потенциальная техническая проблема, заключающаяся в том, что пользователи могут использовать разные серверы для каждого запроса, поэтому любые общие ресурсы должны быть разделены между всеми серверами.鉴于上述所有原因,整个 Web 应用程序架构(包括流量、处理器速度和内存速度)中的瓶颈是:服务器能够处理的并发连接的最大数量
.
Решение Node для этой проблемы:更改连接到服务器的方式
. Вместо того, чтобы создавать новый поток ОС (и выделять ему некоторую сопутствующую память) для каждого соединения, каждое соединение создает событие, которое выполняется в процессе движка Node.Node 声称它绝不会死锁,因为它根本不允许使用锁,它不会直接阻塞 I/O 调用
. Node также утверждает, что серверы, на которых он работает, могут поддерживать десятки тысяч одновременных подключений.
3 Node.js — это не JS-приложение, а рабочая платформа JS.
Увидев название Node.js, новички могут принять его за приложение Javascript,事实上,Node.js采用C++语言编写而成,是一个Javascript的运行环境
. Зачем использовать язык C++?По словам Райана Даля, основателя Node.js, он сначала надеялся использовать Ruby для написания Node.js, но позже обнаружил, что производительность виртуальной машины Ruby не соответствует его требованиям, и тогда он пытался采用V8引擎,所以选择了C++语言
. Поскольку это не приложение Javascript, почему оно называется .js?因为 Node.js是一个Javascript的运行环境
. Когда речь заходит о Javascript, первое, что приходит на ум, это повседневный браузер.Современные браузеры включают в себя различные компоненты, в том числе механизмы рендеринга, механизмы Javascript и т. д. Механизм Javascript отвечает за интерпретацию и выполнение кода Javascript на веб-странице. Являясь одним из самых важных языков во внешнем интерфейсе в Интернете, Javascript всегда был патентом разработчиков внешнего интерфейса. но,Node.js是一个后端的Javascript运行环境(支持的系统包括Linux、Windows)
, значит можно编写系统级或者服务器端的Javascript代码,交给Node.js来解释执行
, простая команда, например:
#node helloworld.js
Node.js использует движок V8 браузера Google Chrome, и его производительность очень высока.同时还提供了很多系统级的API
, такие как операции с файлами, сетевое программирование и т. д.浏览器端的Javascript代码在运行时会受到各种安全性的限制,对客户系统的操作有限
. В отличие,Node.js则是一个全面的后台运行时,为Javascript提供了其他语言能够实现的许多功能
.
4 Node.js использует управляемое событиями асинхронное программирование, предназначенное для сетевых служб.
Термин "управляемый событиями" не является чем-то новым. В сетевом программировании на некоторых традиционных языках мы будем использовать функции обратного вызова. Например, когда ресурс сокета достигает определенного состояния, будет выполняться зарегистрированная функция обратного вызова.Node.js的设计思想中以事件驱动为核心,它提供的绝大多数API都是基于事件的、异步的风格
. Если взять модуль Net в качестве примера, объект net.Socket имеет следующие события: подключение, данные, завершение, тайм-аут, слив, ошибка, закрытие и т. д. Разработчикам, использующим Node.js, необходимо зарегистрировать соответствующие функции обратного вызова в соответствии со своей бизнес-логикой. .这些回调函数都是异步执行的
, что означает, что хотя в структуре кода эти функции выглядят последовательно,它们并不依赖于自身出现的顺序,而是等待相应的事件触发
.事件驱动、异步编程的设计,重要的优势在于,充分利用了系统资源,执行代码无须阻塞等待某种操作完成,有限的资源可以用于其他的任务
. Такие конструкции идеально подходят для后端的网络服务编程,Node.js的目标也在于此
.При разработке серверов параллельная обработка запросов представляет собой большую проблему, а блокировка функций может привести к напрасной трате ресурсов и временным задержкам. Благодаря регистрации событий и асинхронным функциям разработчики могут улучшить использование ресурсов и повысить производительность.
Из модулей поддержки, предоставляемых Node.js, мы можем看到包括文件操作在内的许多函数都是异步执行的
, Это отличается от традиционных языков, и для облегчения разработки серверов Node.js имеет множество сетевых модулей, включая HTTP, DNS, NET, UDP, HTTPS, TLS и т. д., на этой основе разработчики могут быстро создавать веб-серверы. В качестве примера возьмем простой helloworld.js:
// 全局方法require()是用来导入模块的,一般直接把require()方法的返回值赋值给一个变量,在JavaScript代码中直接使用此变量即可。require("http")就是加载系统预置的http模块。
var http = require('http');
// http.createServer是模块的方法,目的就是创建并返回一个新的web server对象,并且给服务绑定一个回调,用以处理请求。
http.createServer(function (req, res) {
// 使用response.writeHead()函数发送一个HTTP状态200和HTTP头的内容类型(content-type)
// 使用response.write()函数在HTTP相应主体中发送文本“Hello World"
res.writeHead(200, {'Content-Type': 'text/plain'});
// 完成响应
res.end('Hello World\n');
// 通过http.listen()方法就可以让该HTTP服务器在特定端口监听。
}).listen(80, "127.0.0.1");
// console.log就不用多说了,了解firebug的都应该知道,Node实现了这个方法。
console.log('Server running at http://127.0.0.1:80/');
Приведенный выше код настраивает простой http-сервер (запустите образец развертывания по адресуhttp://127.0.0.1можно получить доступ), слушать локально на порту 80, и для любого HTTP-запроса сервер возвращает текстовый ответ «Hello World» с кодом состояния заголовка 200 и значением Content-Type «text/plain». Из этого небольшого примера мы можем увидеть несколько моментов:
- Сетевое программирование Node.js удобнее, предоставленный модуль (здесь http) открывает простой в использовании интерфейс API, а сервер можно построить всего за несколько строк кода.
- Воплощает управляемое событиями асинхронное программирование, Функция обратного вызова (реализованная анонимной функцией Javascript) указана в параметрах функции createServer.При отправке HTTP-запроса Node.js вызывает функцию обратного вызова для обработки запроса и ответа. Конечно, этот пример относительно прост без особой регистрации событий, и читатели увидят больше практических примеров в следующих статьях.
Когда мы используем метод http.createServer, мы, конечно, не просто хотим, чтобы сервер прослушивал определенный порт, мы также хотим, чтобы он что-то делал, когда сервер получает HTTP-запрос. Проблема в том, что это асинхронно:请求任何时候都可能到达,但是我们的服务器却跑在一个单进程中
. Мы создали сервер и передали функцию методу, который его создал.无论何时我们的服务器收到一个请求,这个函数就会被调用
.
Почему это событие идеально подходит для Node?JavaScript 是一种很棒的事件驱动编程语言
, потому что он позволяет использовать анонимные функции и замыкания, и, что более важно, синтаксис знаком каждому, кто писал код.Функция обратного вызова, вызываемая при возникновении события, может быть записана там, где происходит захват события.. Это упрощает написание и сопровождение кода, отсутствие сложных объектно-ориентированных фреймворков, интерфейсов и возможности чрезмерного проектирования. Просто слушайте события, пишите callback-функцию, а все остальное сделает система!
5 особенностей Node.js
Поговорим о характеристиках Node.js. Характеристики управляемого событиями и асинхронного программирования были подробно описаны только что и не будут здесь повторяться.
Node.js的性能不错
. По словам основателя Райана Даля, производительность является важным фактором для Node.js.选择C++和V8而不是Ruby或者其他的虚拟机也是基于性能的目的
. Node.js также имеет довольно смелый дизайн.它以单进程、单线程模式运行(很吃惊,对吧?这和Javascript的运行方式一致),事件驱动机制是Node.js通过内部单线程高效率地维护事件循环队列来实现的,没有多线程的资源占用和上下文切换,这意味着面对大规模的http请求,Node.js凭借事件驱动搞定一切
, разработчики веб-сервисов, привыкшие к традиционным языкам, могут быть хорошо знакомы с многопоточным параллелизмом и совместной работой, но перед лицом Node.js нам необходимо принять и понять его характеристики. Исходя из этого, можем ли мы сделать вывод, что такая конструкция будет导致负载的压力集中在CPU(事件循环处理?)而不是内存(还记得Java虚拟机抛出OutOfMemory异常的日子吗?)
, Лучше увидеть, давайте взглянем на тест производительности Node.js, проведенный командой Taobao Shared Data Platform:
- Конфигурация физической машины: RHEL 5.2, процессор 2,2 ГГц, память 4 ГБ
- Сценарий приложения Node.js: прокси-сервер MemCache, каждый раз извлекающий 100 байт данных
- Размер пула соединений: 50
- Количество одновременных пользователей: 100
- Результаты тестов (режим сокета): память (30M), QPS (16700), CPU (95%)
Из приведенных выше результатов видно, что в таком тестовом сценарии количество запросов в секунду может достигать 16700 раз, память занимает всего 30 МБ (из которых куча V8 занимает 22 МБ), а ЦП достигает 95%, что может стать узким местом. Кроме того, есть много практиков, которые проводили анализ производительности Node.js, В целом его производительность убедительна и является важной причиной его популярности.既然Node.js采用单进程、单线程模式,那么在如今多核硬件流行的环境中,单核性能出色的Node.js如何利用多核CPU呢?创始人Ryan Dahl建议,运行多个Node.js进程,利用某些通信机制来协调各项任务
. В настоящее время выпущено много сторонних модулей поддержки многопроцессорности Node.js.В последующих статьях будет подробно описано программирование Node.js для многоядерных процессоров.
Еще одна особенность Node.js заключается в том, что он поддерживает язык программирования Javascript.. Сравнение преимуществ и недостатков динамических языков и статических языков здесь обсуждаться не будет. Всего три момента:
- Являясь основным языком интерфейсных инженеров, Javascript пользуется большой популярностью в техническом сообществе.. Более того, с непрерывным развитием веб-технологий, особенно с возрастающей важностью клиентской части, многие фронтенд-инженеры начали проверять возможности «внутренних приложений». Во многих компаниях, использующих Node.js, инженеры говорят, что поскольку они привыкли к Javascript, они выбрали Node.js.
- Анонимные функции и замыкания Javascript идеально подходят для асинхронного программирования, управляемого событиями., Из примера helloworld видно, что callback-функция реализована в виде анонимной функции, что очень удобно. Замыкания еще более полезны, см. следующий пример кода:
var hostRequest = http.request(requestOptions,function(response) {
var responseHTML ='';
response.on('data', function (chunk) {
responseHTML = responseHTML + chunk;
});
response.on('end',function(){
console.log(responseHTML);
// do something useful
});
});
В приведенном выше коде нам нужно обработать переменную responseHTML в конечном событии,由于Javascript的闭包特性,我们可以在两个回调函数之外定义responseHTML变量
, а затем непрерывно изменять его значение в функции обратного вызова, соответствующей событию данных, и, наконец, обращаться к нему и обрабатывать его в конечном событии.
-
Javascript лучше работает на динамических языках, Некоторые разработчики проанализировали производительность динамических языков, таких как Javascript, Python и Ruby, и обнаружили, что производительность Javascript лучше, чем у других языков.Кроме того, двигатель V8 также является лучшим в своем классе., поэтому производительность Node.js также выигрывает от этого. Есть много причин для выбора Node.js, например, интерес и развитие сообщества,
同时也希望可以提高并发能力,榨干CPU
.