最近要做一个网页版 FTP 工具,用户在网页上,完成 FTP 工具的操作。
我的方案是:
1.每个登录用户连接 FTP 服务器后,会把 ftp 连接对象放到一个对象池中(实际上就是一个公共的字典中,key 为用户的 id,FTP 对象为 value )
2.用户每次操作,直接到公共字典中去找有没有已经生成的 ftp 对象,假如有,直接拿过来用。省的每次操作都要重新建立远程连接。
3.当字典中的对象超过一定数量时,清理掉最早加入的。
现在的问题是,在本地调试没有问题。但是放到 uwsgi 环境的时候,发现由于 uwsgi 会生成多实例,实际上也就生成了多个对象池。这个方案就有不行了。
麻烦询问一下大家是怎么处理这个方案的,其实最终的目的,也就是单个用户,每步操作都要重新跟服务器建立连接。只在登录页面的时候,连一下。然后其他操作公用此 ftp 对象即可。
麻烦各位赐教。
1
mayorbryant 2019-08-28 16:29:49 +08:00
用 redis 来替代你文中说的公共字典
|
2
piaochen0 OP @mayorbryant radis 可以缓存 ftp 这种连接类的对象吗?印象中这种只适合可序列化的对象吧。
|
3
wuwukai007 2019-08-28 16:39:30 +08:00 1
redis 可以指定序列化方式,默认是 json,可以指定 pickle,但是 pickle 也有很多序列不了的对象,
这个时候用 dill 第三方序列化 pip install dill 可以序列化 函数,嵌套函数,匿名函数,main 函数等大多数 py 对象 然后 dill 序列化后是字节 ,pickle 可以识别 |
4
mayorbryant 2019-08-28 16:42:19 +08:00 1
@piaochen0 楼上说的也是我想表达的
|
5
piaochen0 OP 提个想法,这种 FTP 连接对象,可以放到 session 中吗?会有什么问题没有?
|
6
jesnridy 2019-08-28 17:30:00 +08:00
@piaochen0 我第一个想法就是放到 session 中,链接 session 对象放在单例模型中搞,登出的时候断开 session
|
7
sujin190 2019-08-28 17:40:31 +08:00 2
楼上 redis 或者 session 序列化的,你们认真的么?一个进程拥有的 socket 能通过 pickle 弄到另外一个进程去?见鬼了吧
socket 底层就是文件句柄,数据能序列化,文件句柄复制到另外一个进程怎么用? 所以你这个 uwsgi 部署的 Django 是很难做出来的,估计需要用 tornado 或者 asyncio 做一个代理连接层吧,也不复杂 |
9
sujin190 2019-08-28 18:09:59 +08:00 1
或者另外一个方案是,nginx 做 upstream 负载均衡的时候,然后依据 session_id hash 方式选择 upstream,这样就可以确保单个登录用户始终由同一个进程来处理,这样你就可以用原来全局字典缓存的方式了
https://blog.csdn.net/lvshaorong/article/details/78309514 可以看看这个 |
10
wuwukai007 2019-08-28 18:22:54 +08:00
sor,socket 好像不可以序列化尴尬了
|
11
est 2019-08-28 18:55:29 +08:00 1
最终的目的,不管怎么做,ftp 连接池的维护,都会落到一个进程来负责。所以最直接的方式是,uwsgi 里 workers 数量改成 1 即可。
可能其他 web 请求处理量,一个 worker 不够,那也很简单,另外再跑一套 uwsgi,前面再套一个 nginx 反代或者 uwsgi router。 |
12
wangyongbo 2019-08-28 19:03:28 +08:00 2
我们是这样做的,1 浏览器,2 web 服务,3 ftp 连接服务。 就是把你现在整体的后端服务分成 2 和 3 两个服务。
1 和 2 之间用 http 协议,或者 websocket 协议,2 和 3 之间用消息队列通信,通信协议需要自己定义。 比如 用户要连接一个 ftp 服务器。通过 http 协议,发到 2, 然后 2 处理之后,比如验证权限,连接数量等等,然后把请求放到消息队列。3 从消息队列读取到请求之后,创建一个 ftp 连接。 可以根据实际需要扩展 2 和 3 的服务数量,互不干扰。 你觉得怎么样? |
13
piaochen0 OP @wangyongbo 消息队列是用的 ActiveMQ 这种中间件来实现的吗?我没怎么用过这种模式,根据我的理解,这应该是异步的操作吧。web 服务把消息发给了消息队列,队列里面一个一个处理,处理完了以后,通知 web 服务。这个时候还能通过 response 通知前端页面吗?
|