Произошла ошибка при попытке прочитать файл локальных узлов

Обновлено: 30.06.2024

Node.js, кроссплатформенная среда выполнения, заслужила немало похвал и критики за то, что она предлагает разработчикам. Часто причины такой критики кроются в том, как разработчики используют/неправильно используют язык. В этой статье рассматриваются десять распространенных ошибок, которые допускают разработчики Node.js, и способы их избежать.

Махмуд – разработчик программного обеспечения с многолетним опытом работы и умением создавать эффективные, масштабируемые и стабильные решения.

С того момента, как Node.js был представлен миру, он получил немало как похвал, так и критики. Дискуссия все еще продолжается и может не закончиться в ближайшее время. Что мы часто упускаем из виду в этих дебатах, так это то, что каждый язык программирования и платформа критикуются из-за определенных проблем, которые возникают из-за того, как мы используем платформу. Независимо от того, насколько сложно Node.js усложняет написание безопасного кода и насколько легко он упрощает написание высокопараллельного кода, платформа существует уже довольно давно и использовалась для создания огромного количества надежных и сложных веб-сервисов. Эти веб-службы хорошо масштабируются и доказали свою стабильность благодаря длительному пребыванию в Интернете.

Однако, как и любая другая платформа, Node.js уязвим для проблем и проблем разработчиков. Некоторые из этих ошибок снижают производительность, в то время как другие делают Node.js непригодным для всего, чего вы пытаетесь достичь. В этой статье мы рассмотрим десять распространенных ошибок, которые часто совершают разработчики, плохо знакомые с Node.js, и то, как их можно избежать, чтобы стать профессионалом Node.js.

JavaScript в Node.js (как и в браузере) обеспечивает однопоточную среду. Это означает, что никакие две части вашего приложения не могут работать параллельно; вместо этого параллелизм достигается за счет асинхронной обработки связанных операций ввода-вывода. Например, запрос от Node.js к движку базы данных на получение какого-либо документа позволяет Node.js сосредоточиться на другой части приложения:

Однако фрагмент кода, привязанного к процессору, в экземпляре Node.js с тысячами подключенных клиентов — это все, что нужно, чтобы заблокировать цикл событий, заставив всех клиентов ждать. Коды, связанные с процессором, включают попытки сортировки большого массива, выполнение чрезвычайно длинного цикла и т. д. Например:

Вызов этой функции sortUsersByAge может быть удобен при работе с небольшим массивом пользователей, но с большим массивом это окажет ужасное влияние на общую производительность. Если это абсолютно необходимо сделать, и вы уверены, что в цикле событий больше ничего не будет ожидать (например, если это было частью инструмента командной строки, который вы создаете с помощью Node.js, и он не имело бы значения, если бы все это работало синхронно), то это может не быть проблемой. Однако в экземпляре сервера Node.js, пытающемся одновременно обслуживать тысячи пользователей, такая схема может оказаться фатальной.

Если бы этот массив пользователей извлекался из базы данных, идеальным решением было бы извлечь его уже отсортированным непосредственно из базы данных. Если цикл событий был заблокирован циклом, написанным для вычисления суммы длинной истории данных финансовых транзакций, его можно было бы отложить до настройки какой-либо внешней рабочей роли/очереди, чтобы избежать перегрузки цикла событий.

Как видите, универсального решения такой проблемы с Node.js не существует, каждый случай нужно рассматривать индивидуально. Фундаментальная идея заключается в том, чтобы не выполнять интенсивную работу ЦП в инстансах Node.js, обращенных к передней панели, к которым клиенты подключаются одновременно.

JavaScript всегда полагался на обратные вызовы. В веб-браузерах события обрабатываются путем передачи ссылок на (часто анонимные) функции, которые действуют как обратные вызовы. В Node.js обратные вызовы были единственным способом взаимодействия асинхронных элементов вашего кода друг с другом — до тех пор, пока не были введены промисы. Обратные вызовы все еще используются, и разработчики пакетов по-прежнему разрабатывают свои API на основе обратных вызовов. Одна из распространенных проблем Node.js, связанная с использованием обратных вызовов, — это вызов их более одного раза. Как правило, функция, предоставляемая пакетом для выполнения чего-либо асинхронно, предназначена для ожидания функции в качестве ее последнего аргумента, который вызывается после завершения асинхронной задачи:

Обратите внимание, что оператор return появляется каждый раз, когда вызывается "done", вплоть до самого последнего раза. Это связано с тем, что вызов обратного вызова не завершает автоматически выполнение текущей функции. Если первый «возврат» был закомментирован, передача нестрокового пароля в эту функцию все равно приведет к вызову «computeHash». В зависимости от того, как «computeHash» справляется с таким сценарием, «done» может вызываться несколько раз. Любой, кто использует эту функцию откуда-то еще, может быть застигнут врасплох, если обратный вызов, который они передают, вызывается несколько раз.

Чтобы избежать этой ошибки Node.js, достаточно быть осторожным. Какой-то узел.js разработчики имеют привычку добавлять ключевое слово return перед каждым вызовом обратного вызова:

Во многих асинхронных функциях возвращаемое значение почти не имеет значения, поэтому такой подход часто позволяет легко избежать такой проблемы.

Глубоко вложенные обратные вызовы, которые часто называют «адом обратных вызовов», сами по себе не являются проблемой Node.js. Однако это может привести к быстрому выходу кода из-под контроля:

Чем сложнее задача, тем хуже она может быть. Вкладывая обратные вызовы таким образом, мы легко получаем подверженный ошибкам, трудный для чтения и поддержки код. Один из обходных путей — объявить эти задачи как небольшие функции, а затем связать их. Хотя одним из (возможно) самых чистых решений этой проблемы является использование служебного пакета Node.js, который работает с асинхронными шаблонами JavaScript, такими как Async.js:

Подобно async.waterfall, существует ряд других функций, которые Async.js предоставляет для работы с различными асинхронными шаблонами. Для краткости мы использовали здесь более простые примеры, но реальность часто бывает хуже.

Возможно, асинхронное программирование с обратными вызовами не является чем-то уникальным для JavaScript и Node.js, но они являются причиной его популярности. В других языках программирования мы привыкли к предсказуемому порядку выполнения, когда два оператора выполняются один за другим, если нет специальной инструкции для перехода между операторами. Даже в этом случае они часто ограничиваются условными операторами, операторами циклов и вызовами функций.

Однако в JavaScript с обратными вызовами конкретная функция может работать неправильно, пока задача, которую она ожидает, не будет завершена. Выполнение текущей функции будет выполняться до конца без остановки:

Как вы заметили, вызов функции «testTimeout» сначала напечатает «Begin», затем напечатает «Waiting..», а затем сообщение «Done!» примерно через секунду.

Все, что должно произойти после срабатывания обратного вызова, должно быть вызвано внутри него.

Node.js рассматривает каждый файл как небольшой изолированный модуль. Если в вашем пакете есть два файла, возможно, «a.js» и «b.js», то для того, чтобы «b.js» мог получить доступ к функциям «a.js», «a.js» должен экспортировать его, добавив свойства в объект экспорта:

Когда это будет сделано, всем, кому требуется "a.js", будет предоставлен объект с функцией свойства "verifyPassword":

Но что, если мы хотим экспортировать эту функцию напрямую, а не как свойство какого-то объекта? Для этого мы можем перезаписать экспорт, но тогда мы не должны рассматривать его как глобальную переменную:

Обратите внимание, что мы рассматриваем «экспорт» как свойство объекта модуля. Различие между «module.exports» и «exports» здесь очень важно и часто вызывает разочарование у новых разработчиков Node.js.

В JavaScript есть понятие исключений. Подражая синтаксису почти всех традиционных языков с поддержкой обработки исключений, таких как Java и C++, JavaScript может «генерировать» и перехватывать исключения в блоках try-catch:

Однако в асинхронных ситуациях функция try-catch будет вести себя не так, как можно было бы ожидать. Например, если вы хотите защитить большой фрагмент кода с большим количеством асинхронных операций с помощью одного большого блока try-catch, это не обязательно сработает:

В Node.js ошибки обрабатываются по-другому, и поэтому необходимо следовать шаблону (ошибка, …) для всех аргументов функции обратного вызова — ожидается, что первым аргументом всех обратных вызовов будет ошибка. если это произойдет.

Числа в JavaScript представляют собой числа с плавающей запятой — целого типа данных не существует. Вы не ожидаете, что это будет проблемой, так как числа, достаточно большие, чтобы подчеркнуть пределы плавающей запятой, встречаются не часто. Именно тогда случаются ошибки, связанные с этим. Поскольку числа с плавающей запятой могут содержать целочисленные представления только до определенного значения, превышение этого значения в любом вычислении немедленно начнет его путать. Как ни странно, в Node.js следующее оценивается как true:

К сожалению, на этом особенности работы с числами в JavaScript не заканчиваются. Несмотря на то, что числа являются числами с плавающей запятой, операторы, работающие с целочисленными типами данных, работают и здесь:

Однако, в отличие от арифметических операторов, побитовые операторы и операторы сдвига работают только с последними 32 битами таких больших «целых» чисел. Например, попытка сдвинуть «Math.pow(2, 53)» на 1 всегда будет оцениваться как 0. Попытка выполнить побитовое или 1 с таким же большим числом даст 1.

Возможно, вам редко приходится иметь дело с большими числами, но если вам это нужно, существует множество библиотек больших целых чисел, которые реализуют важные математические операции с числами большой точности, такие как node-bigint.

Допустим, мы хотим создать небольшой прокси-подобный веб-сервер, который будет обслуживать ответы на запросы, получая контент с другого веб-сервера. В качестве примера мы создадим небольшой веб-сервер, обслуживающий изображения Gravatar:

В этом конкретном примере Node.js, мы извлекаем изображение из Gravatar, считываем его в буфер и затем отвечаем на запрос. Это не так уж и плохо, учитывая, что изображения Gravatar не слишком велики. Однако представьте, если бы размер содержимого, которое мы проксируем, составлял тысячи мегабайт. Гораздо лучшим подходом был бы следующий:

Здесь мы извлекаем изображение и просто передаем ответ клиенту. Нам ни в коем случае не нужно считывать весь контент в буфер перед его обслуживанием.

В Node.js «console.log» позволяет выводить на консоль почти все, что угодно. Передайте ему объект, и он напечатает его как литерал объекта JavaScript. Он принимает любое произвольное количество аргументов и выводит их все аккуратно через пробел. Есть ряд причин, по которым разработчик может испытать искушение использовать это для отладки своего кода; однако настоятельно рекомендуется избегать «console.log» в реальном коде. Вам не следует писать «console.log» по всему коду для его отладки, а затем комментировать их, когда они больше не нужны. Вместо этого используйте одну из замечательных библиотек, созданных специально для этого, например debug.

Подобные пакеты предоставляют удобные способы включения и отключения определенных строк отладки при запуске приложения. Например, с помощью отладки можно предотвратить вывод любых строк отладки на терминал, не устанавливая переменную среды DEBUG. Использовать его просто:

Чтобы включить строки отладки, просто запустите этот код, указав для переменной среды DEBUG значение «app» или «*»:

Независимо от того, работает ли ваш код Node.js в рабочей среде или в вашей локальной среде разработки, монитор программы-супервизора, который может управлять вашей программой, является чрезвычайно полезным. Одна практика, часто рекомендуемая разработчиками, разрабатывающими и внедряющими современные приложения, предполагает, что ваш код должен быстро дать сбой. Если возникает непредвиденная ошибка, не пытайтесь с ней справиться, лучше дождитесь сбоя программы и попросите супервизора перезапустить ее через несколько секунд. Преимущества супервизорных программ не ограничиваются только перезапуском аварийных программ. Эти инструменты позволяют перезапускать программу при сбое, а также перезапускать их при изменении некоторых файлов. Это делает разработку программ Node.js гораздо более приятной.

Для Node.js доступно множество управляющих программ. Например:

У всех этих инструментов есть свои плюсы и минусы. Некоторые из них хороши для работы с несколькими приложениями на одном компьютере, в то время как другие лучше подходят для управления журналами. Однако, если вы хотите начать работу с такой программой, все это будет правильным выбором.

Здравствуйте, это проблема, подробнее о разъяснении, у меня есть обычный прокси для перенаправления запросов, чтобы избежать CORS,
однако нам также нужно подключиться к клиентской VPN, и иногда у нас работает прокси, а иногда у нас есть следующий

но без прокси конечная точка TARGET всегда работает хорошо, поэтому мы решили, что это может быть проблема с проксированием некоторых, не могли бы вы пояснить это?

Может, мне нужно добавить некоторые настройки?

Текст был успешно обновлен, но возникли следующие ошибки:

djleonskennedy прокомментировал 15 июня 2017 г. •

@chimurai Спасибо за ответ, TARGET — это внутренний URL-адрес клиента, который работает при доступе к нему напрямую (без прокси-сервера)

djleonskennedy прокомментировал 19 июня 2017 г.

Проблема @chimurai с локальной средой

прокомментировал chimurai 19 июня 2017 г. •

Рад, что вы нашли ответ.
Не хотите поделиться причиной и решением?

djleonskennedy прокомментировал 19 июня 2017 г.

@chimurai Мы решили проблему с помощью nginx

AndriiDidkivsky прокомментировал 19 июня 2017 г.

Было бы здорово решить эту проблему одним прокси :)

прокомментировал chimurai 19 июня 2017 г.

Использование нескольких прокси-серверов действительно не идеально.

Можете ли вы привести отдельный пример, в котором эта проблема воспроизводима?

Я с удовольствием углублюсь в это и выясню, не связано ли это с HPM.

AndriiDidkivsky прокомментировал 19 июня 2017 г.

Вы можете прийти к нам в офис, и мы покажем вам. :)
Есть только один случай для воспроизведения. VPN-подключение к среде и прокси-сервер к некоторому API.

Можете ли вы привести отдельный пример, в котором эта проблема воспроизводима?

Знаете ли вы какие-либо сервисы, в которых мы можем использовать vpn + прокси, чтобы привести отдельный пример?
В этом случае я могу попытаться создать для вас небольшой пример.

прокомментировал chimurai 21 июня 2017 г.

Знаете ли вы какие-либо сервисы, где мы можем использовать vpn + прокси для предоставления отдельного примера?

В настоящее время ничего не известно.

Было бы неплохо, если бы вы приложили небольшие усилия для устранения проблемы.

djleonskennedy прокомментировал 29 июня 2017 г. •

@chimurai Согласно моему небольшому исследованию, это сценарий с задержкой ответа от соединения vpn.

Когда я делаю запрос, он передает прокси-сервер на nginx (в нашем текущем решении), если я не ошибаюсь, HPM получает ответ об успешном завершении от nginx, поэтому HPM не дает сбоев.

nging ожидает ответа от сервера (который находится под vpn).
Ответ может быть долгим, даже 2 минуты

В этой статье описывается, как устранить сообщения об ошибках, возникающие при попытке подключить группу кластера к сети после остановки кластера.

Применимо к: Windows Server 2012 R2
Исходный номер базы знаний: 313882

Симптомы

После того, как вы отключите кластер вручную или после отказа кластера, группа и все ее ресурсы могут переключиться при сбое, если в кластере произойдет потеря узла. Однако группа также может перейти в автономное состояние. Если вы попытаетесь подключить группу или ресурс к сети, вы можете получить следующее сообщение об ошибке:

Произошла ошибка при попытке подключить группу 'GroupName' к сети:

Узел кластера не является владельцем ресурса.

Идентификатор ошибки: 5015 (00001397). ).

Если вы попытаетесь подключить отдельный ресурс в группе к сети, вы можете получить одно из следующих сообщений об ошибке:

Произошла ошибка при попытке перевести ресурс 'ResourceName' в оперативный режим:

Ресурс кластера не может быть переведен в оперативный режим. Узел-владелец не может запустить этот ресурс.

Идентификатор ошибки: 5071 (000013df).

Для этого ресурса не указаны возможные владельцы. Это означает, что этот ресурс нельзя перевести в оперативный режим ни на одном узле кластера.

Причина

Если вы используете функцию "Переместить группу" для ручного перемещения группы с одного узла на другой или если кластер выходит из строя, список возможных владельцев создается для всей группы и для всех ресурсов в группе. Поведение, описанное в разделе «Сводка» этой статьи, может возникнуть, если один из ресурсов в группе, которая не подключается к сети, не имеет узла в сети, указанного в списке возможных владельцев.

Разрешение

Чтобы обойти эту проблему, снова подключите узел, который был переведен в автономный режим. Переместите группу обратно на узел, который вы только что подключили к сети, а затем проверьте список возможных владельцев каждого ресурса, чтобы убедиться, что в нем указан узел, на котором группа не была подключена к сети.

Если вы не можете подключить узел к сети из-за того, что узел действительно вышел из строя, добавьте нужный узел в список возможных владельцев:

В Администраторе кластера откройте Общие свойства каждого ресурса и просмотрите список возможных владельцев.

После того, как вы найдете ресурс с пустым списком возможных владельцев и неактивной кнопкой «Изменить», запишите имя этого ресурса

Откройте командную строку и введите следующую команду. имя ресурса — это имя ресурса, которое вы записали на шаге 1:

cluster res имя ресурса /listowners
Отображается список возможных владельцев ресурса. Этот список указывает, что единственный возможный владелец — это отключенный узел.

В командной строке выполните следующую команду, чтобы добавить другой узел в список возможных владельцев, где отсутствующий узел – это неработающий узел:
имя кластера res ресурса /addowner: отсутствующий узел

В Администраторе кластера снова подключите группу, которая ранее находилась в автономном режиме.

Если после подключения группы к сети у вас возникли проблемы с просмотром ресурсов в Администраторе кластера, выйдите из Администратора кластера, а затем снова подключитесь к кластеру.

Статус

Такое поведение предусмотрено дизайном.

Подробнее

Список возможных владельцев бесполезен в кластере с менее чем тремя узлами. Служба кластеров создает список возможных владельцев для группы. Расположение, в котором размещена группа, содержащая этот ресурс, зависит от изменения списка возможных владельцев для ресурса. Внутри поддерживается упорядоченный список для местоположения, в котором размещена группа. Если вы удаляете возможного владельца ресурса, вы удаляете этот узел из списка возможных владельцев.

Читайте также: