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 和一些非常流行的代理工具,但实现上难以完全保持一直(工作量大)。
- 另外,我知道 nysocks 这个名称和kneesocks接近。