TLDR; nysocks是基于kcp提供的nodejs上的SOCKS5代理工具,对丢包的网络环境有较好的效果。
Linode Tokyo 2, JP机房的测试:
tcp代理
nysocks(kcp + libuv) fast
分享一些背景和过程和思考
前几个月看到了kcp和kcptun,觉得很有意思。起初我判断如果要做一个代理工具的话,整体性能不会是最终瓶颈。于是便想用熟悉的node(纯js)一边学习kcp,一边重新写一个代理工具。但最终在性能这块,实际上还是达不到可用的程度,主要有两点:
- node中,v8环境的udp调用,光是在本地收发1MB的数据都需要超过80ms。虽然node在buffer处理上,对脚本而言已经做的很高效了,但在频繁的回调和协议解析和内容拼接上还是远远不够。
- node 8之前的版本没办法设置send/recv(虽然libuv是支持的),需要在操作系统上层面上利用sysctl增大buffer大小。
果然过于底层的应用对脚本来说还是太严苛了。于是我便考虑用c/cpp以node-addon的形式写底层的传输、加密解密部分,顶层还是用node做SOCKS和tcp部分加快开发速度。但我一开始还是担心,因为我知道对于对c/cpp,v8底层,libuv不熟悉的话,写出来的node-addon性能往往还不如用纯js写的代码高。
好在之前看到了Scott Frees的blog和这本电子书 —— C++ and Node.js Integration(需付费)。实践证明,如果你有类似的需求的话,特别是在c/cpp层面进行非阻塞进程的操作及大量buffer在c/cpp和v8之前转换的这种场景,这本书中的内容是非常有效、实用的。
最终的结果还是让我自己满意的,c/cpp部分满足了性能的需求,node部分开发得足够快,也算是让自己找到了对node-addons的定位。但整个项目比我一开始预想的大了太多,精力和经验有限,目前还有非常多可以优化、改进的点。
整个项目大量参考了kcptun和一些非常流行的代理工具,但实现上难以完全保持一直(工作量大)。希望能对有需求的同学和需要类似实现参考的同学一点微小的帮助。