сейчасNode.js
Все больше и больше популярных, все больше и больше сценариев приложений, научитесь эффективно отлаживатьNode.js
Это сделает ежедневную разработку более эффективной. Используйте следующееinspector
отладкаnodejs
программа
Node6.3+
версия предоставляет два протокола для отладки:v8 Debugger Protocol
а такжеv8 Inspector Protocol
можно использовать сторонниеClient/IDE
Дождитесь мониторинга и вмешательства в запущенный процесс Node (v8) для отладки.
v8 Inspector Protocol
это недавно добавленный протокол отладки, который передается черезwebsocket
(обычно используется порт 9229) сClient/IDE
взаимодействие, основанное наChrome/Chromium
браузерdevtools
Предоставляет графический интерфейс отладки.
1 Включить отладку
1.1 Код сервера отладки
Если ваш скрипт строитсяhttp
илиnet
сервер, вы можете напрямую использовать--inspect
const Koa = require('koa')
const app = new Koa()
app.use(async ctx => {
let a = 0
const longCall = () => {
while (a < 10e8) {
a++
}
}
longCall()
ctx.body = `Hello ${a}`
})
app.listen(3000, () => {
console.log('程序监听了3000端口')
})
использоватьnode --inspect=9229 app.js
запустите свой скрипт,9229
указанный номер порта
# 控制台会输出如下:
/usr/local/bin/node --inspect=9229 src/inspector/demo.js
Debugger listening on ws://127.0.0.1:9229/c4f1e345-e811-47a2-b44a-65f68c0c2cc3
Debugger attached.
# 可以在浏览器里打开:http://127.0.0.1:9229/json 看到一些信息, c4f1e345-e811-47a2-b44a-65f68c0c2cc3 为uuid,不同调试面板的uuid来区分;
--inspect
Для общей программы она мигает, и выполнение завершается до отправки сигнала точки останова. Точки останова вообще не работают, вы можете--inspect-brk
;
1.2 Код скрипта отладки
Если вы завершите процесс сразу после запуска вашего скрипта, вам нужно использовать--inspect-brk
Для запуска отладчика, чтобы скрипт мог сломаться до выполнения кода, иначе весь код догоняет сразу до конца кода, завершая процесс, и отладка вообще невозможна.
node --inspect-brk=9229 app.js
2 Доступ к инструменту отладки
2.1 VS Code
Vs Code
встроенныйNode debugger
,служба поддержкиv8 Debugger Protocol
а такжеv8 Inspector Protocol
Два протокола. дляv8 Inspector Protocol
, просто добавьте строку в конфигурациюAttach
Тип конфигурации
существуетDebug
панель управления, нажмитеsettings
значок, открыть.vscode/launch.json
.
Нажмите «Node.js» для первоначальной настройки.
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/app.js"
}
]
}
2.2 Chrome DevTools
- Способ 1: открыть в браузере Chrome
chrome://inspect
нажмитеConfigure
кнопку, убедитесь, что хост и порт есть в списке.
- Способ 2: с вышеуказанного хоста и порта
/json/list
копироватьdevtoolsFrontendUrl
или–-inspect
запросите информацию и скопируйте в Chrome.
2.2.1 Console Panel
chrome
доступ к отладкеnode
После процедуры вы можетеConsole
агентNode
Весь вывод консоли в процессе обеспечивает гибкую функцию фильтрации Filter, а также может выполнять код непосредственно в контексте кода процесса Node.
2.2.2 Sources Panel
Sources
Все загруженные скрипты можно посмотреть в , включая сторонние библиотеки иNode
Основная библиотека, выбранные файлы можно редактировать,Ctrl + C
Сохранение может напрямую изменить работающий скрипт.
2.2.3 Profile Panel
Profile
Для мониторинга производительности запущенных скриптов, включая использование ЦП и памяти,CPU profile
, который может записывать время процессора, занятое выполнением функций Javascript, на временной шкале.
Существует два типа временных периодов записи профиля.
- Ручной запуск/остановка: нажмите
start
Чтобы начать запись, нажмитеstop
остановить запись - Вставьте запуск/остановку вызовов API в код
console.profile('tag')
console.profileEnd('tag')
, допустимыйSources
Отредактируйте и сохраните код прямо в панели, а затем обновите его, нажав F5.
профиль имеет три вида
- chart: широко известный как график пламени, он отображает стек вызовов функций со временем в качестве горизонтальной оси. Следующий простой пример анализа
tick
,Одинtick
должно бытьNode
Вызывается из нижнего слоя, используется в узлеprocess.nextTick(fn)
а такжеsetTimeout(fn, deloy)
Системный обратный вызов будет генерировать новыеtick
, соответствующий созданию нового стека вызовов.
Функции вызываются в порядке от нижней части стека к вершине стека. Первый стек на рисунке вышеparserOnHeadersComplete
вызывается нижним слоем,parserOnHeadersComplete
называется вparserOnIncoming
,parserOnIncoming
называется вemit
...И так далее.
Ширина стека вызовов — это время, необходимое для выполнения функции. Время выполнения функции включает в себя время выполнения ее внутренних вызовов других функций, поэтому время вызова функции, расположенной относительно близко к низу стека, должно быть больше, чем время вызова функции, близкой к вершине стека. . Исключая время выполнения внутренних вызовов других функций, это время выполнения текущей функции.
Нажмите на функцию, чтобы перейти кSources
Расположение определения функции на панели.
-
Name
: Имя функции. -
Self time
: время, необходимое для завершения текущего вызова функции, включая только объявление самой функции, а не какие-либо функции, вызываемые функцией. -
Total time
: время, необходимое для завершения текущего вызова этой функции и любых функций, которые она вызывает. -
URL
: расположение определения функции в формате file.js:100 , где file.js — это имя файла, в котором определена функция, а 100 — номер строки определения. -
Aggregated self time
: общее время всех вызовов функции в записи, исключая функции, вызываемые этой функцией. -
Aggregated total time
: общее время всех вызовов функции, за исключением функций, вызываемых этой функцией. -
Not optimized
: Если анализатор обнаружил возможную оптимизацию функции, она будет указана здесь. -
heavy(Bottom Up): Статистика снизу вверх, снизу относится к нижней части графика пламени.
- tree(Top Down): Статистика сверху вниз, сверху относится к вершине графика пламени.
Видно, что большая часть времени программы уходит наlongCall
При вызове этой функции;
2.2.4 Memory profile
Профилировщик кучи может отображать распределение памяти по объектам JavaScript страницы и связанным узлам DOM (см. также Дерево хранения объектов). С помощью анализатора можно стрелятьJS 堆快照
,分析内存图
,比较快照
так же как查找内存泄漏
.
3. Реализация прокси-сервера Node Inspector
пройти черезnode inspector
Отладка точки останова — очень распространенный метод отладки. Но было несколько проблем с предыдущей отладкой, которые сделали нашу отладку менее эффективной.
- существует
vscode
отладка, вinspector
изменение порта илиwebsocket id
Повторно подключитесь после изменения. - существует
devtools
отладка, вinspector
изменение порта илиwebsocket id
Повторно подключитесь после изменения.
Как инспектор узлов решает две вышеупомянутые проблемы?
По первому вопросу вvscode
, он будет называть себя/json
интерфейс для получения последнихwebsocket id
, затем используйте новыйwebsocket id
Соединен сnode inspector
оказание услуг. Таким образом, решение состоит в том, чтобы реализоватьtcp
Функция прокси может выполнять пересылку данных.
По второму вопросу, посколькуdevtools
не будет автоматически приобретать новыеwebsocket id
, поэтому нам нужно сделать динамическую замену, поэтому решение состоит в том, чтобы проксировать службу на/json
Получатьwebsocket id
, затем вwebsocket
при рукопожатииwebsocket id
Делайте динамические замены в заголовках запросов.
Нарисуйте блок-схему:
3.1 TCP-прокси
Во-первых, реализоватьtcp
Функция агента на самом деле очень проста, т. е. черезnode
изnet
модуль для создания прокси-портаTcp Server
, а затем, когда есть соединение, создайте соединение с целевым портом, после чего данные могут быть перенаправлены.
Простая реализация выглядит следующим образом:
const net = require('net');
const proxyPort = 9229;
const forwardPort = 5858;
net.createServer(client => {
const server = net.connect({
host: '127.0.0.1',
port: forwardPort,
}, () => {
client.pipe(server).pipe(client);
});
// 如果真要应用到业务中,还得监听一下错误/关闭事件,在连接关闭时即时销毁创建的 socket。
}).listen(proxyPort);
Вышеприведенное реализует относительно простую прокси-службу черезpipe
Метод связывает данные двух сервисов.client
Когда данные будут доступны, они будут отправлены наserver
середина,server
Когда есть данные, они также будут отправлены наclient
середина.
когда это будет сделаноTcp
После функции прокси ее уже можно реализоватьvscode
потребности в отладкеvscode
ниже среднегоlaunch.json
Указанный порт является портом прокси вconfigurations
добавить конфигурацию
{
"type": "node",
"request": "attach",
"name": "Attach",
"protocol": "inspector",
"restart": true,
"port": 9229
}
Затем, когда приложение перезапустится, или заменитеinspect
порт,vscode
может автоматически повторно передать порт проксиattach
к вашему приложению.
3.2 Получить идентификатор веб-сокета
В начале этого шага необходимо решитьdevtools
можно переустановить без изменения ссылкиattach
Проблема в том, что при запускеnode inspector server
когда,inspector
Сервис также предоставляет/json
изhttp
интерфейс для полученияwebsocket id
.
Это довольно просто, просто отправьте его напрямуюhttp
запрос к порту назначения/json
, вы можете получить данные:
[ { description: 'node.js instance',
devtoolsFrontendUrl: '...',
faviconUrl: 'https://nodejs.org/static/favicon.ico',
id: 'e7ef6313-1ce0-4b07-b690-d3cf5274d8b0',
title: '/Users/wanghx/Workspace/larva-team/vscode-log/index.js',
type: 'node',
url: 'file:///Users/wanghx/Workspace/larva-team/vscode-log/index.js',
webSocketDebuggerUrl: 'ws://127.0.0.1:5858/e7ef6313-1ce0-4b07-b690-d3cf5274d8b0' } ]
Поле id в приведенных выше данных — это то, что нам нужноwebsocket id
.
3.3 Агент-инспектор
понятноwebsocket id
После этого вы можетеtcp
делать через проксиwebsocket id
Динамическая замена , сначала нам нужна фиксированная ссылка, поэтому сначала установите прокси-ссылку, например, мой порт прокси-сервиса9229
, тогда прокси-ссылка для chrome devtools:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9229/__ws_proxy__
кроме последнегоws=127.0.0.1:9229/__ws_proxy__
Остальные зафиксированы, а последний сразу видно, что онwebsocket
ссылка на. в__ws_proxy__
Он используется для занятия пространства, используется вchrome devtools
Инициировать эту прокси-ссылкуwebsocket
Когда делается запрос на рукопожатие,__ws_proxy__
заменитьwebsocket id
затем впередnode
изinspector
оказание услуг.
к вышеизложенномуtcp
через проксиpipe
Логический код можно немного изменить.
const through = require('through2')
client
.pipe(through.obj((chunk, enc, done) => {
if (chunk[0] === 0x47 && chunk[1] === 0x45 && chunk[2] === 0x54) {
const content = chunk.toString();
if (content.includes('__ws_proxy__')) {
return done(null, Buffer.from(content.replace('__ws_proxy__', websocketId)));
}
}
done(null, chunk);
}))
.pipe(server)
.pipe(client)
пройти черезthrough2
Создаватьtransform
stream для внесения изменений в передаваемые данные.
Просто судитьchunk
Первые три байтаGET
,еслиGET
указать, что это может бытьhttp
просьба, которая может бытьwebsocket
запрос на обновление протокола. Печать заголовков запроса выглядит так:
GET /__ws_proxy__ HTTP/1.1
Host: 127.0.0.1:9229
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: chrome-devtools://devtools
Sec-WebSocket-Version: 13
затем поместите в него путь/__ws_proxy
заменить на соответствующийwebsocketId
, затем впередnode
изinspector server
на завершениеwebsocket
рукопожатие, следующийwebsocket
Коммуникация не требует обработки данных, просто пересылает их напрямую.
Далее, даже если перезапустить различные приложения или заменитьinspector
порты не требуют заменыdebug
ссылка, просто пере-inspector server
При перезапуске во всплывающем окне ниже
Один щелчок Reconnect DevTools восстановит отладку.
Ссылаться на:Реализация прокси-сервера Node Inspector