Skip to content

Plasmatium/nbBridge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NoteBook Bridge

背景

  1. AWS用不起,各种GPU云都用不起
  2. Mac Book不能运行tensorflow-gpu
  3. GPU笔记本太重不想来回搬动,用起来没有Mac舒服,没有retina屏
  4. 希望在任何地方能用自己的Mac Book连到GPU笔记本上的jupyter notebook

思路

在本地的mac上开一个服务,所有的请求(包括httpwebsocket),都用hws _(higher order websocket,高阶websocket)_传输到ECS服务器,然后ECS服务器通过hws转发到公司GPU笔记本。

如何安装及使用

Mac本地运行一个nodejs服务src/remote.js,ECS运行一个nodejs转发服务remote-server.js,GPU笔记本也在本地运行一个nodejs服务src/native.js

安装

首先要有nodejs环境,直接去node官网下载安装即可。然后git clonenpm i,npm如果没速度,或许你需要cnpm

git clone https://github.com/Plasmatium/nbBridge
cnpm i

配置及使用

有两件东西需要配置,ECS的nginx.conf和传输两端的conf.json

conf.json

按照如下格式配置,密码和url根据自身情况更改:

{
  "REMOTE_HWS_URL": "ws://your/ECS/websocket/path",
  "LOCAL_HWS_URL": "ws://your/native/websocket/path",
  "INTERNEL_PORT": "YOUR_INTERNEL_PORT",
  "KEY":  "pwd_with_16_char",
  "IV":   "iv__widh_16_char",
  "AGL":  "aes-128-cbc"
}

nginx.conf

按照如下格式配置,只是部分配置,其他部分具体请参照nginx文档。其中YOUR_INTERNEL_HWS_SERVER和上述INTERNEL_PORT相关,比如INTERNEL_PORT设为8765,那么YOUR_INTERNEL_HWS_SERVER设为http://localhost:8765

# higher order websocket
location /your/ECS/websocket/path {
  proxy_pass YOUR_INTERNEL_HWS_SERVER;
  proxy_redirect off;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header Host $host;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  proxy_read_timeout 300s;

  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";

  error_log off;
  access_log off;
}

启动两地服务

注:两端和ECS都需要放好conf.json

  1. 在GPU本上首先启动服务:node src/native.js
  2. 登陆ECS,启动nginx,启动node服务:node src/remote-server.js
  3. Mac上启动node服务:node src/remote.js

转发流程

http

http请求相对websocket简单:Mac请求 -> ECS转发 -> GPU本响应 -> ECS转发回来 -> Mac浏览器收到响应并渲染页面

request

  1. 在mac上,请求http,比如http://localhost:8080
  2. 生成一个uuid,将上面请求的响应对象res存储在一个响应池中,key是uuid
  3. 将上述请求中的headersbodyoriginalUrl,以及上述uuid打包压缩加密为sendData
  4. hws发送sendData到ECS
  5. ECS转发hws的内容到GPU笔记本上
  6. GPU本解码解包,获取到headersbodyoriginalUrluuid,伪装headers成为本地请求,将originalUrl改成jupyter notebook的url,比如将http://localhost:8080改成http://localhost:8888,然后将headersbody发送到该url

response

  1. GPU本收到上面第7步的request之后,以为是本地机器请求jupyter notebook,会发送响应response,包括headersstatusbody
  2. 将上述headers, status, body, 以及上面request中的uuid一起打包压缩加密为respData,用hws发送到ECS上
  3. ECS转发respData到本地Mac电脑上
  4. Mac解包解码,获得headers, status, body, uuid
  5. request步骤1里创建的响应池中,通过uuid找到该请求的响应对象res
  6. res.statusres.send,将上述第3步解码出来的headers, status, body发送到Mac上浏览器,一个完整的请求->响应链至此结束。

websocket

websocket相对复杂些,需要将上下行链路小心翼翼串起来,具体是上家websocket的onmessage里使用对的下家websocket的send

建立websocket

  1. Mac浏览器发出创建websocket请求到Mac本地ws://localhost:8080,含有headers, originalUrl
  2. 生成uuid,连同上一步获得的headers, originalUrl一起打包压缩加密,通过hws发送到ECS
  3. 用上述uuid,以及浏览器创建在本地的ws,存入到ws池中,uuid作为索引
  4. ECS通过hws转发这个加密包到GPU本
  5. GPU本解包解码获得originalUrl, headers, uuid
  6. 通过上一步的originalUrl, headers,创建websocket,并用uuid作为索引存放在ws池里

ws通信

  1. 浏览器发出ws的message,将event.data, 发出这个信息的ws对应的uuid一起打包压缩加密,通过hws发送到ECS
  2. ECS用hws转发这个加密包到GPU本
  3. GPU本解包解码,获得event.datauuid, 通过uuid找到ws池中的ws对象,用该ws发送event.datajupyter notebook服务器
  4. jupyter notebook做出回应,会触发上述uuid对应的ws的onmessage方法。在此方法中,打包回应的event.data,连同uuid一起打包压缩加密,通过hws发往ECS
  5. ECS上用hws转发该加密包到Mac上
  6. Mac解码解包,获得event.datauuid,通过该uuid找到ws池中对应的ws,用该ws发送event.data,浏览器将会收到数据并渲染(该ws即浏览器创建在Mac上的websocket)

Flow示意图

示意图

Releases

No releases published

Packages

No packages published