Lotus 代理实现文档
内部数据传输框架
- lotus 会启动 rpcServer;
- lotus-miner 会创建一个和lotus的基于websocket的jsonrpc连接,同时会通过 gorilla/mux 启动http服务;
- lotus-worker 会创建一个和miner的基于http的jsonrpc连接。
websocket vs socket
尽管它们(在一般情况下)实现了类似的事情,但是它们确实是不同的。WebSockets 通常由浏览器通过类似于在 TCP/IP 上运行的 HTTP 的协议连接到应用服务器。因此,它们主要用于需要与服务器永久连接的 Web 应用程序。另一方面,普通 Socket 是更强大和通用的。它们在 TCP/IP 上运行,但它们不限于浏览器或 HTTP 协议。它们可以用来实现任何种类的通信。
http/https 代理实现方案
- 监听端口,for循环等待连接进入,go新开一个协程进行处理
- 解析数据头,获取方法和请求路径
- 拨号进行连接,通过io.Copy的方法进行数据转发(实际这样处理不好,但确实可行)
上述是一个比较简单的方案,没有考虑超时等一些异常情况,但确实可以做到数据被代理进行转发,详情参考文档:http/https正向代理。
上述方案有一个更优秀的处理,可以参考:gist.github.com/hellojukay/proxy_server.go
http/https 反向代理实现方案
- httputil.NewSingleHostReverseProxy(url) 创建一个反向代理实例 *httputil.ReverseProxy
- 把HandleFunc第二个参数导向到 proxy,proxy本身就实现了 ServeHTTP
上述方案实现非常简单,但只实现反向代理,对于负载均衡,缓存等优秀特性没有实现,详情参考文档:Go 简单而强大的反向代理(Reverse Proxy)
websocket 反向代理实现方案
- 使用 github.com/gorilla/websocket 实现反向代理
- 自定义 WebsocketProxy,实现 ServeHTTP 方法,也就是 proxy 当作 handler 使用
- 建立客户端和后端的websocket请求后就不再断开,直到信息传递不在通畅就断开链接
以上是 websocketproxy.go 的实现。在这个实现中做到了客户端http请求升级到websocket请求,头数据传递,但仅适用于单点对单点(单个client对后台单个backend)的情况。
Lotus 代理难点
- websocket 反向代理
- jsonrpc 通信
- 认证信息(header信息)
- 保证第一次连接的backend不变,其他请求可以选择优秀的backend
解:
- jsonrpc 本质上只是不关心数据如何传递的,只要双方约定好打包/解包规则就好了,问题二应该不是问题。
- 认证信息问题也不大,原先的认证逻辑是 miner 直接给 lotus,新的逻辑是 miner 连接 proxy 不需要认证,proxy 连接多个 lotus 需要独立的认证
- 对于 miner 来说应该是无感知的,所以是透明代理,miner的配置和以往一样,把 FULLNODE_API 变成 proxy 的监听地址就好
- 对于 proxy 来说,它和 lotus 的关系类似于反向代理,proxy 可以选择数据的传输 backend,需要定期检测backend 状态,并随时可以切换 backend 连接。这里有两个策略,1是等待已有消息传递结束(不太现实,数据可能源源不断),2是同时建立多个socket连接,新消息进入时自动进入到最优秀的那个
- 按照策略2来说,上述问题第四点可以忽略,因为连接本身并不会断,除非第一次连接的那个api会主动中断(代码中是for循环等待)
实现方案是参考 websocketproxy.go,实现多路socket连接,lotus认证等。