shadowsocksrr/shadowsocksr

关于整体服务端监听模式的改进建议

YanzheL opened this issue · 9 comments

关于整体服务端监听模式的改进建议

SSR服务端的多用户版本的实现方式是每个端口对应于一个密码,在多用户使用的时候只需给单独的用户分配单独的端口,再分配对应的密码即可。

这种方式简单有效,但是十分不便于规模化部署。

  1. 先不考虑服务器总端口数有限的问题(总共也就65535个端口,去掉系统保留端口之类,就更少了,而且有些端口还会与服务器上其他服务的端口冲突)
  2. 当SSR用于docker swarm集群时,配置多个端口从集群内暴露到集群外是一件非常麻烦的事情,而且很难动态调整
  3. 当使用服务器层面的负载均衡器时,配置多端口的监听以及转发也是很困难的事情。
    例如,在云服务商下拥有ABC三台服务器作为一个集群G,每个服务器都开放20000-30000的端口号(也就是接受一万个用户),然后当我使用云服务商提供的负载均衡服务时,需要配置负载均衡器X的转发规则。
    那么我需要配置10000个端口号的TCP转发,才能把指向X各端口的流量均衡到集群G中的各端口上,这是非常不现实的。
  4. 一个服务监听太多端口也是不符合程序设计模式的。

以下是我建议的一种模式

参考多个知名开源项目的服务监听方式,例如Strongswan、MongoDB、MySQL、Nginx等

SSR整个服务应该只监听服务器上的少数几个指定的端口,例如只监听10000端口

这个端口负责处理所有用户的连接,不同用户携带不同的账号信息发往10000端口,那么服务器只需要在10000端口上统一处理所有用户的请求即可。再根据用户发来的凭证信息去后端数据库查找比对来判断拒绝还是接受连接。

单端口模式(或者少数几个端口)的优势

  1. 添加新用户时便不需要再在服务器层面增加新的端口监听了,而只需要在数据库中添加一条用户信息即可。
  2. 方便部署在集群中。例如部署在Docker Swarm集群中(或者kubernates),只需要配置对外开放10000这一个端口,对于指向任意节点的10000端口的连接,都会被Docker Swarm内部实现的负载均衡功能分发到所有的节点中处理,当增加新的节点时也会更加灵活
  3. 假如使用云服务商提供的服务器负载均衡服务,那么负载均衡器只需要负责监听指向总入口的10000端口的连接并转发到后端集群中即可,配置起来也简单,而且节省成本(一个负载均衡器最多配置50条转发规则,多了就要另外开一个均衡器,意味着双倍的成本)

观察到近期作者主要是专注于开发csharp客户端,服务端这边也很久没有重大的更新了。希望作者能够重视起服务端的开发,毕竟很多时候性能瓶颈还是在服务端

建议macOS和安卓客户端支持指定服务器UDP端口,像CSharp客户端那样。因为有时候服务器上的TCP监听和UDP监听是分端口的

当然我提出的这个方案如果实施起来需要变化的地方太多,基本上算是整体重构了一遍,工作量非常大。但考虑到此方案的发展前景,我认为还是值得一试的。

我此前也一直在研究SSR的服务端python代码,同时开发过基于MongoDB数据库作为后端的用户管理(想发PR的,但没整理好)。服务端部署了一段时间,感觉服务端的并发性能不是很好,当用户流量大时内存占用严重(100~300M,正常的时候是30M左右)。好像SSR多线程部分并没有实现的很好,建议作者参考Python Cookbook上的一些经典设计模式。

  1. ShadowsocksR 支持「单端口多用户」模式,可以实现 issue 中提到的只监听某几个特定端口实现多用户。文档链接
  2. Issue 中提到的使用 MongoDB 来作为用户数据库,我觉得这个可以在 「单端口多用户」模式的基础上进行扩展即可,改动应该不是特别大。

另外
SSR的PY实现并没有多线程,PY做不到真正的多线程,想上多线程也许需要等其他实现了吧,比如Erlang或者C++什么的

如果出现内存占用非常大的情况,请查看是不是使用的最新版的SSRR,SSRR修复了几个密码学组件中的内存泄露问题

PY服务器端这边最近上了稳定版的F协议,但是libev那边还是个泥潭,如果喜欢的话,你可以切到akkariiin/dev分支上来试试


另外有关开发速度这个问题,项目人手不够是最重要的原因

BalaBala

为什么大家都怪维护者不更新而不想想为什么没有人原意像维护者这样来无偿为项目贡献代码呢?难道是因为无偿开发不赚钱吗?既然大家都没有为这个项目出过一分钱,为什么还要自我感觉像出了钱或是交了税的大爷一样来要求这个要求那个呢?
这个项目,赚钱的都是机场老板和云服务商,开发者不赚一分钱,那些有需求的用着机场的用户是不是应该找机场老板发issue呢?机场老板是不是应该找云服务商发issue呢?自架服务器的是不是应该自己写代码呢?为什么机场厂长要来问大规模使用下的性能问题?为什么不加钱上超算?

大家都是普通人,难道项目贡献者就吃了税金所以就需要像日本公务员那样来处理这样那样的诸如“改颜色!”、“这个我不喜欢那个我不喜欢改改改”这样的鸡毛蒜皮找猫找狗的需求呢?难道不怕真有哪个吃了国家资助的提交者给项目里加一点什么吗?

总有些人贪得无讨,还来人肉开发者,人肉来人肉去的,既然这样大家都别用好了,写代码不如跳舞,就让它停更算了,我们大家都来跳社会主义的交谊舞。 哼o(一︿一+)o


另外,不要观察来观察去的,给人一种**准备要人肉开发者的感觉。没更新肯定是有原因的,事情既然存在和发生就有它存在和发生的原因和合理性。
我还要上课还要做实验,不是SSRR的全职开发,也没有一个叫SSRR基金会的能提供给谁一个全职开发岗位,SSRR的不少代码还需要其他贡献者来写,既然现在除了我就没有人来维护libev和Android就不要怪Android一直不支持F协议,我也没办法,最近做实验很忙。

恩………之前心情不好,请原谅,现在我再仔细回答一下这个issue吧

关于普通的监听模式不适合大规模部署的问题
可以使用上面所说的单端口多用户模式来解决
唯一的缺点就是这个模式只有部分协议支持

有关更新速度的问题,因为现在只有寥寥几个贡献者,而这个项目又是又好几种不同的语言组成的,所以就导致现在这样部分项目更新快,部分项目更新慢的问题
人的精力有限,这个问题除非有更多贡献者加入,否则是无解的

TCP和UDP分离监听的模式的确很好,只是需求恐怕不是很多,可以研究一下如何在客户端实现

流量大时使用更多内存这是正常现象,因为作为一个中转服务器就必然会缓存发送和接收的数据以便中转
这个是原理决定的,除非使用硬件实现或者0拷贝的技术,否则不可能有多大的降低

当然,如果内存占用居高不下,就有可能是PY又内存侧漏了【笑
如果出现这样的情况,请先更新到最新版,最新版已经解决了不少内存泄漏问题,但是现有的的垃圾回收机制,要想完全不出现无用的内存消耗,我觉得再造一个完全基于C++的RAII来进行内存管理的轮子可能更有可能达到这个目的【笑

py想要实现多线程我觉得是个奢望…这个问题我觉得上boost.asio可能可以解决。


就是这样,既然你也能够写py,为什么不来贡献点代码呢?【笑

突然意识到我用的是实名账号来发的issue....感觉更容易被人肉的是我>_<!!

嗯我知道因为GIL的原因,python的多线程实际上都是单线程,但是对于IO密集型的应用,python的伪多线程效果还是挺好的。其实如果想绕过GIL,试试multiprocessing模块实现进程池也可,不过这样的话就需要考虑到进程间通信的开销了

我使用的是3.2.0的SSR,那我试试3.2.1版本吧

试试最好的语言PHP

支持 , @YanzheL 3.2.1 以前的版本内存泄露严重,512M一下KVM VPS 开着没一会儿就宕机

8iack commented

数据库多用户版本的时候分配的端口总量是65535
不管是不是单端口多用户还是直接多用户都会有一个问题
如果说超过这么多的用户的时候 就没端口可分配了