在《[Whistle 实现原理 —— 从 0 开始实现一个抓包工具] 》一文中给大家详细介绍了如何实现一个抓包调试工具 Whsitle。事实上 Whistle 不仅可以供开发人员本地开发调试,也可以部署到公共服务器给产品运营、测试等非开发人员用来访问测试环境、远程抓包调试。但 Whistle 是单进程服务,无法满足多人多项目同时使用,所以基于 Whistle 开发了多进程多用户的远程代理服务 -- Nohost,其主要功能:
Github 仓库: https://github.com/Tencent/nohost 有关 Whistle 的实现原理参见:[Whistle 实现原理 —— 从 0 开始实现一个抓包工具] 。
更详细的场景和功能描述请参考:《[Nohost 开源啦!] 》。
有点类似 Node 的 Cluster 模块,其核心思想是:将多进程多问题转成单进程 Whistle 的问题,即给每个团队成员或业务模块分配一个 Whistle 进程,并通过一个 Master 进程来管理各个 Whistle 进程以及分发请求。
1 . 访问接入 Nohost 的页面,Nohost 会在页面左下角注入一个小圆点(环境切换按钮)(具体原理后面讲)。
如何接入 Nohost 参见: https://nohost.pro/docs/quickstart
2 . 点击小圆点弹出环境选择框,点击选择环境后,页面会先将选择的 账号/环境
发送到 Nohost 的 Master 进程。
3 . Master 进程会先获取 clientId
(如何获取参见后面的 Master 进程实现原理),将获取的 clientId
与选择的 账号/环境
存到 Master 进程的内存 LRU Cache 里面。
4 . 页面等待设置环境的接口响应或超时后自动刷新页面,这时页面所有请求也会经过 Master 进程,Master 进程通过 3 的方式获取每个请求的 clientId
,并根据 clientId
获取之前选择的 账号/环境
,再将请求转到账号对应的 Whistle 进程及执行对应环境的规则(具体实现参见后面的 Master 进程实现原理)。
这样每个人或业务只需关注自己的 Whistle 进程,功能上也就跟本地的 Whistle 差不多,也可以直接使用所有 Whistle 插件。
最后看下 Master 进程的实现,Master 进程可以主要有三个功能:
启动(关闭)指定 Whistle 进程并将请求转发到该进程及执行对应环境规则
小圆点的注入不是简单的往页面追加脚本,还涉及到:
const startWhistle = require('whistle')
其中:
whistle.nohost
实现的,分三部分内容:rules.txt
动态获取白名单,并配置规则将上述白名单请求转发到插件。_rules.txt
配置的私有规则,对请求到插件的 html 页面注入小圆点。这里引入了一个插件 whistle.nohost
,该插件除了上述注入小圆点功能以外,还有如下的功能。
点击选择环境,页面会发送请求 /.whistle-path.5b6af7b9884e1165/whistle.nohost/cgi-bin/select?name=imweb&envId=test&time=1637026271911
,其中:
/.whistle-path.5b6af7b9884e1165
是一个特殊路径,Whistle 自动拦截该路径并作为内部请求。name
:账号(分组)名称。envId
:环境名称的编码,encodeURIComponent(envName)
。该请求会转到 Nohost 的内置的 whistle.nohost
插件进程的 uiServer
,该插件会通过以下方式获取 clientId
:
x-whistle-client-id
获取 clientId
。x-whistle-client-id
,则分别通过请求头 x-forwarded-for
或 req.socket.remoteAddress
获取 clientIp
作为 clientId
。将获取的 clientId
和 name/env
存到插件进程的 LRU Cache:lru.set(clientId, name/env)
。
对 Worker 里面的 Whistle 进程的管理也是通过 whistle.nohost
插件实现的:
rulesServer
和 tunnelRulesServer
设置转发规则。clientId
并根据 clientId
获取用户选择的账号和环境。* internal-proxy://127.0.0.1:xxxxx
让 Master 的 Whistle 进程将请求转到该端口。internal-proxy 是 Whistle 代理直接转发协议,它可以通过用 http 的方式转发 https 请求
Nohost 插件会自动根据请求需求拉起对应进程,且如果该进程有超过 6 分钟没有请求,则会自动关闭。可以通过 Whistle 提供的方法检测进程是否有请求详见: https://github.com/Tencent/nohost/blob/master/lib/plugins/whistle.nohost/lib/whistle.js#L126 。
插件的完整实现代码参见: https://github.com/Tencent/nohost/blob/master/lib/plugins/whistle.nohost/lib/rulesServer.js
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8