欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Node Inspector 代理實(shí)現(xiàn)

 更新時(shí)間:2017年10月19日 11:13:40   作者:whxaxes  
這篇文章主要介紹了淺談Node Inspector 代理實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

背景

平時(shí)做 node 開(kāi)發(fā)的時(shí)候,通過(guò) node inspector 來(lái)進(jìn)行斷點(diǎn)調(diào)試是一個(gè)很常用的 debug 方式。但是有幾個(gè)問(wèn)題會(huì)導(dǎo)致我們的調(diào)試效率降低。

問(wèn)題一:當(dāng)使用 vscode 進(jìn)行斷點(diǎn)調(diào)試時(shí),如果應(yīng)用是通過(guò) cluster 啟動(dòng)的 inspector,那么每次當(dāng) worker 掛了重啟后,inspector 的端口都會(huì)自增。雖然在 node8.x 版本中可以指定 inspectPort 固定調(diào)試端口,但是在 node6.x 中是不支持的。這樣會(huì)導(dǎo)致每次 worker 重啟了就得在 vscode 中重新指定調(diào)試端口。

問(wèn)題二:當(dāng)使用 devtools 調(diào)試的時(shí)候,每次調(diào)試都需要拷貝 devtools 鏈接到 chrome 上調(diào)試,而上面說(shuō)的端口變更問(wèn)題則會(huì)導(dǎo)致 devtools 的鏈接變更,除此之外,每次重新啟動(dòng) inspector 也會(huì)導(dǎo)致 devtools 的鏈接變更,因?yàn)?websocket id 變了。

而把上面的兩個(gè)問(wèn)題簡(jiǎn)化一下就是:

  • 在 vscode 中調(diào)試,在 inspector 端口變更或者 websocket id 變更后能夠重連。
  • 在 devtools 中調(diào)試,在 inspector 端口變更或者 websocket id 變更后能夠重連。

解決方案

目前業(yè)界已經(jīng)有解決方案就是 chrome 插件 Node Inspector Manager(Nim) ,不過(guò)這個(gè)只能解決在同個(gè) inspector 端口下的應(yīng)用重啟后鏈接更改的問(wèn)題,卻無(wú)法解決 cluster 啟動(dòng)導(dǎo)致的端口自增問(wèn)題,除非在 Nim 中提前指定好多個(gè)端口,再者 Nim 是 chrome 上的插件,對(duì)于在 vscode 中的調(diào)試卻無(wú)能為力了。

所以最佳的解決方案自然是使用 node 來(lái)做 inspector 代理,解決方案如下:

對(duì)于第一個(gè)問(wèn)題,在 vscode 上,它是會(huì)自己去調(diào)用 /json 接口獲取最新的 websocket id,然后使用新的 websocket id 連接到 node inspector 服務(wù)上。因此解決方法就是實(shí)現(xiàn)一個(gè) tcp 代理功能做數(shù)據(jù)轉(zhuǎn)發(fā)即可。

對(duì)于第二個(gè)問(wèn)題,由于 devtools 是不會(huì)自動(dòng)去獲取新的 websocket id 的,所以我們需要做動(dòng)態(tài)替換,所以解決方案就是代理服務(wù)去 /json 獲取 websocket id,然后在 websocket 握手的時(shí)候?qū)?websocket id 進(jìn)行動(dòng)態(tài)替換到請(qǐng)求頭上。

畫(huà)了一張流程圖:

實(shí)現(xiàn)步驟

一、Tcp 代理

首先,先實(shí)現(xiàn)一個(gè) tcp 代理的功能,其實(shí)很簡(jiǎn)單,就是通過(guò) node 的 net 模塊創(chuàng)建一個(gè)代理端口的 Tcp Server,然后當(dāng)有連接過(guò)來(lái)的時(shí)候,再創(chuàng)建一個(gè)連接到目標(biāo)端口即可,然后就可以進(jìn)行數(shù)據(jù)的轉(zhuǎn)發(fā)了。

簡(jiǎn)易的實(shí)現(xiàn)如下:

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);
 });
 // 如果真要應(yīng)用到業(yè)務(wù)中,還得監(jiān)聽(tīng)一下錯(cuò)誤/關(guān)閉事件,在連接關(guān)閉時(shí)即時(shí)銷毀創(chuàng)建的 socket。
}).listen(proxyPort);

上面實(shí)現(xiàn)了比較簡(jiǎn)單的一個(gè)代理服務(wù),通過(guò) pipe 方法將兩個(gè)服務(wù)的數(shù)據(jù)連通起來(lái)。client 有數(shù)據(jù)的時(shí)候會(huì)被轉(zhuǎn)發(fā)到 server 中,server 有數(shù)據(jù)的時(shí)候也會(huì)轉(zhuǎn)發(fā)到 client 中。

當(dāng)完成這個(gè) Tcp 代理功能之后,就已經(jīng)可以實(shí)現(xiàn) vscode 的調(diào)試需求了,在 vscode 中項(xiàng)目下 launch.json 中指定端口為代理端口,在 configurations 中添加配置

{
 "type": "node",
 "request": "attach",
 "name": "Attach",
 "protocol": "inspector",
 "restart": true,
 "port": 9229
}

那么當(dāng)應(yīng)用重啟,或者更換 inspect 的端口,vscode 都能自動(dòng)重新通過(guò)代理端口 attach 到你的應(yīng)用。

二、獲取 websocketId

這一步開(kāi)始,就是為了解決 devtools 鏈接不變的情況下能夠重新 attach 的問(wèn)題了,在啟動(dòng) node inspector server 的時(shí)候,inspector 服務(wù)還提供了一個(gè) /json 的 http 接口用來(lái)獲取 websocket id。

這個(gè)就相當(dāng)簡(jiǎn)單了,直接發(fā)個(gè) http 請(qǐng)求到目標(biāo)端口的 /json,就可以獲取到數(shù)據(jù)了:

[ { 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' } ]

上面數(shù)據(jù)中的 id 字段,就是我們需要的 websocket id 了。

三、Inspector 代理

拿到了 websocket id 后,就可以在 tcp 代理中做 websocket id 的動(dòng)態(tài)替換了,首先我們需要固定鏈接,因此先定一個(gè)代理鏈接,比如我的代理服務(wù)端口是 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__ 其他都是固定的,而最后這個(gè)也一眼就可以看出來(lái)是 websocket 的鏈接。其中 __ws_proxy__則是用來(lái)占位的,用于在 chrome devtools 向這個(gè)代理鏈接發(fā)起 websocket 握手請(qǐng)求的時(shí)候,將 __ws_proxy__ 替換成 websocket id 然后轉(zhuǎn)發(fā)到 node 的 inspector 服務(wù)上。

對(duì)上面的 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);
...

通過(guò) through2 創(chuàng)建一個(gè) transform 流來(lái)對(duì)傳輸?shù)臄?shù)據(jù)進(jìn)行一下更改。

簡(jiǎn)單判斷一下 chunk 的頭三個(gè)字節(jié)是否為GET,如果是 GET 說(shuō)明這可能是個(gè) http 請(qǐng)求,也就可能是 websocket 的協(xié)議升級(jí)請(qǐng)求。把請(qǐng)求頭打印出來(lái)就是這個(gè)樣子的:

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替換成對(duì)應(yīng)的 websocketId,然后轉(zhuǎn)發(fā)到 node 的 inspector server 上,即可完成 websocket 的握手,接下來(lái)的 websocket 通信就不需要對(duì)數(shù)據(jù)做處理,直接轉(zhuǎn)發(fā)即可。

接下來(lái)就算各種重啟應(yīng)用,或者更換 inspector 的端口,都不需要更換 debug 鏈接,只需要再 inspector server 重啟的時(shí)候,在下圖的彈窗中

點(diǎn)擊一下 Reconnect DevTools 即可恢復(fù) debug。

最后

上面的詳細(xì)代碼可以在下面的 git 中找到:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Node 使用express-http-proxy 做api網(wǎng)關(guān)的實(shí)現(xiàn)

    Node 使用express-http-proxy 做api網(wǎng)關(guān)的實(shí)現(xiàn)

    這篇文章主要介紹了Node 使用express-http-proxy 做api網(wǎng)關(guān)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 利用nodejs讀取圖片并將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成base64格式

    利用nodejs讀取圖片并將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成base64格式

    這篇文章主要介紹了利用nodejs讀取圖片并將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成base64格式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 使用nvm安裝node的詳細(xì)圖文教程

    使用nvm安裝node的詳細(xì)圖文教程

    nvm是nodejs的版本管理工具,可以在一個(gè)環(huán)境中同時(shí)安裝多個(gè)nodejs 版本(和配套的 npm 版本),并隨時(shí)切換,下面這篇文章主要給大家介紹了關(guān)于使用nvm安裝node的詳細(xì)圖文教程,需要的朋友可以參考下
    2023-02-02
  • 使用Node.js實(shí)現(xiàn)一個(gè)簡(jiǎn)單的FastCGI服務(wù)器實(shí)例

    使用Node.js實(shí)現(xiàn)一個(gè)簡(jiǎn)單的FastCGI服務(wù)器實(shí)例

    這篇文章主要介紹了使用Node.js實(shí)現(xiàn)一個(gè)簡(jiǎn)單的FastCGI服務(wù)器實(shí)例,也可以作為一個(gè)比較詳細(xì)的Node.js服務(wù)器創(chuàng)建教程,需要的朋友可以參考下
    2014-06-06
  • autojs的Node.js正確退出腳本示例

    autojs的Node.js正確退出腳本示例

    這篇文章主要為大家介紹了autojs的Node.js正確退出腳本示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • nodejs npm install全局安裝和本地安裝的區(qū)別

    nodejs npm install全局安裝和本地安裝的區(qū)別

    這篇文章主要介紹了nodejs npm install 全局安裝和非全局安裝的區(qū)別,即帶參數(shù)-g和不帶參數(shù)-g安裝的區(qū)別,需要的朋友可以參考下
    2014-06-06
  • 如何將Node.js中的回調(diào)轉(zhuǎn)換為Promise

    如何將Node.js中的回調(diào)轉(zhuǎn)換為Promise

    這篇文章主要給大家介紹了關(guān)于如何將Node.js中的回調(diào)轉(zhuǎn)換為Promise的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Node.js 使用遞歸實(shí)現(xiàn)遍歷文件夾中所有文件

    Node.js 使用遞歸實(shí)現(xiàn)遍歷文件夾中所有文件

    這篇文章主要介紹了Node.js使用遞歸實(shí)現(xiàn)遍歷文件夾中所有文件,需要的朋友可以參考下
    2017-09-09
  • node.js中的http.get方法使用說(shuō)明

    node.js中的http.get方法使用說(shuō)明

    這篇文章主要介紹了node.js中的http.get方法使用說(shuō)明,本文介紹了http.get的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • 手把手教你更優(yōu)雅的修改node_modules里的代碼

    手把手教你更優(yōu)雅的修改node_modules里的代碼

    這篇文章主要給大家介紹了關(guān)于如何更優(yōu)雅的修改node_modules里的代碼的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-02-02

最新評(píng)論