给Node.js加个远程调试系统

文章目录

    • 远程调试系统
      • 起因
      • 主要设计点
        • 数据结构
        • WebSocket
        • eval 即时执行远程异步代码
        • 暂停/恢复
        • 执行远程代码?需要暂停吗?
      • 效果
      • 收获
      • 下一步方向
      • Monaco Editor 遇到的障碍

远程调试系统

这个项目适用于所有的node.js程序.本文不涉及任何Puppeteer的内容.

起因

因为最近很长一段时间的工作内容都是用Puppeteer框架分析数据.
有一种经常性的需求是: 在程序工作的中间环境 试验新的代码.eg:
某个页面希望执行 自动点击键入命令,但是这个过程非常依赖前面的流程,耗时不短.
每每被打断思路,效率低下.
所以希望实现:

在Puppeteer工作时 随时插入 测试 即时 执行代码.

使用控制台来控制程序也尝试过,有两个原因让我放弃这个方案:

  • VSCode的调试器不支持IO输入窗口
    没办法键入命令(也许是我没找到)
  • 单独的CMD命令行输入窗口
    命令太单一.且和日志输出等混在一起了.

其实原因在于命令行窗口作为Log输出,一个平面无法区分更多数据.

所以对 输出数据,输入数据,命令 采取多通道的需求 就诞生了.
网页作为数据显示平面是我首先想到的。

但是这个功能说大不大,说小又没底.所以一直搁浅,直到最近客户提出 无法区分两个项目Puppeteer实例.
又恰逢两个项目的间隙,开始动手.

主要设计点

功能点:

  • node.js的日志显示到网页上
  • 网页调试
  • 执行功能
    暂停,恢复
    屏幕显示
    执行远程代码

数据结构

因为有: KD-RPC,P2PManager,Canvas远程控制系统 的设计经验,所以核心直奔数据结构设计:

因为要打日志,所以初步设计成这样:
Rep =XX=> 网页端
Rep <=cmd=网页端

interface IF_DB{
  serviceNumber:number,//这是往总控上设计,独立的服务其实不必要这个
  data:{
   name: 日志
   type:{
    main:图片文本,
    附属:屏幕等
   }
   time:Rep运行到现在的时间
   data:any
  }
  
}
interface cmd{
 name: 即时执行函数
 data: any //字符串代码
	
}

通过什么方式区分不同的返回数据呢?
当然是 通道,可以为每种特别的数据通道:
服务端发送 客户端监听的通道有三个:

  • 普通的Rep主动发送给用户的数据
    eg:日志
  • 命令的返回值,执行结果
  • 命令的错误信息

客户端发送 服务端监听的通道有:

  • 命令通道
    结构是cmd

WebSocket

之前分析某款通讯软件的Web版时,其使用的WebSocket给我留下了很深的印象.
从网上找了一些现成的代码,作为基础,使用Socket.IO库.
这里记录一下node.js是如何断开websocket的:

服务端发送一个CloseConnect事件,这个链接在执行完这一需求后,会自动断开.
客户端则是直接 socket.close()//不太记清,具体是不是这个函数自行打印对象验证.

  • Auth
    因为需要 本地向服务端通信,而又不希望可能的暴露信息,所以需要认证,即:
    服务器连接后,监听认证通道,认证密码通过才设置标注允许进一步通讯.
    注意: 每次连接建立都要清除认证标注.

eval 即时执行远程异步代码

当我们将一段代码 从网页端输入 传输回 node.js 后,怎么执行呢?

console.log('Hello')

直接let ret = await eval(cmdString)即可.
为什么有异步? 因为我们要执行异步代码:

例如远程输入:
cmdString =

async sleep(ms){
 return new Promise((reslove)=>{
  setTimeout(()=>{reslove()},ms)
 })
}
function async run(){
 console.log('1')
 await sleep(5000)
 console.log('2')
}

有了await,eval会等待整个代码(包括异步)执行完毕.

暂停/恢复

玩法也很简单,但难点其实是时机:
什么时候调用Trap?需要用户自己埋点吗?
答案是No! 直接将 将我们整个系统埋入 log中即可.这样每次log都会有一个时机.
暂停命令其实就是轮循,额额或许是因为我这边不太掌握更多node.js的事件.

执行远程代码?需要暂停吗?

不需要,因为node.js是单线程.又需要,因为我们的远程代码可能也有异步代码.
不暂停,可能会造成 远程命令和本地代码交替执行.

效果

好了,网页拿到数据拿到后怎么显示就是 前端的设计了.

效果很6.让停就停,让走就走.想执行就执行,写错代码也没关系.

收获

之前曾经尝试让后台引入 websocket 实现控制,通过这次项目,遇到类似需求,可以用node.js在服务器上做代理.

下一步方向

既然网页端搞成了 代码输入端,不加个高亮,语法分析说不过去.
Monaco Editor

Monaco Editor 遇到的障碍

直接使用了其Github范例做基础.
结果我在其它地方 appendChild 方式添加的 socket.io 不能工作了。
monaco 异常提示:
Can only have one anonymous define call per script file.
解决方案: 用一个script标签占位,直接修改其src来实现 socket.io的加载。

你可能感兴趣的:(啊哈-灵光一闪,实践,有趣-好玩)