Django 远程连接对象缓存的方案

2019-08-28 16:25:35 +08:00
 piaochen0

最近要做一个网页版 FTP 工具,用户在网页上,完成 FTP 工具的操作。
我的方案是: 1.每个登录用户连接 FTP 服务器后,会把 ftp 连接对象放到一个对象池中(实际上就是一个公共的字典中,key 为用户的 id,FTP 对象为 value )
2.用户每次操作,直接到公共字典中去找有没有已经生成的 ftp 对象,假如有,直接拿过来用。省的每次操作都要重新建立远程连接。
3.当字典中的对象超过一定数量时,清理掉最早加入的。

现在的问题是,在本地调试没有问题。但是放到 uwsgi 环境的时候,发现由于 uwsgi 会生成多实例,实际上也就生成了多个对象池。这个方案就有不行了。

麻烦询问一下大家是怎么处理这个方案的,其实最终的目的,也就是单个用户,每步操作都要重新跟服务器建立连接。只在登录页面的时候,连一下。然后其他操作公用此 ftp 对象即可。

麻烦各位赐教。

4209 次点击
所在节点    Django
13 条回复
mayorbryant
2019-08-28 16:29:49 +08:00
用 redis 来替代你文中说的公共字典
piaochen0
2019-08-28 16:35:44 +08:00
@mayorbryant radis 可以缓存 ftp 这种连接类的对象吗?印象中这种只适合可序列化的对象吧。
wuwukai007
2019-08-28 16:39:30 +08:00
redis 可以指定序列化方式,默认是 json,可以指定 pickle,但是 pickle 也有很多序列不了的对象,
这个时候用 dill 第三方序列化 pip install dill
可以序列化 函数,嵌套函数,匿名函数,main 函数等大多数 py 对象
然后 dill 序列化后是字节 ,pickle 可以识别
mayorbryant
2019-08-28 16:42:19 +08:00
@piaochen0 楼上说的也是我想表达的
piaochen0
2019-08-28 17:10:15 +08:00
提个想法,这种 FTP 连接对象,可以放到 session 中吗?会有什么问题没有?
jesnridy
2019-08-28 17:30:00 +08:00
@piaochen0 我第一个想法就是放到 session 中,链接 session 对象放在单例模型中搞,登出的时候断开 session
sujin190
2019-08-28 17:40:31 +08:00
楼上 redis 或者 session 序列化的,你们认真的么?一个进程拥有的 socket 能通过 pickle 弄到另外一个进程去?见鬼了吧
socket 底层就是文件句柄,数据能序列化,文件句柄复制到另外一个进程怎么用?
所以你这个 uwsgi 部署的 Django 是很难做出来的,估计需要用 tornado 或者 asyncio 做一个代理连接层吧,也不复杂
piaochen0
2019-08-28 17:56:07 +08:00
@jesnridy session 的方案不行,我刚试了。无法序列化
sujin190
2019-08-28 18:09:59 +08:00
或者另外一个方案是,nginx 做 upstream 负载均衡的时候,然后依据 session_id hash 方式选择 upstream,这样就可以确保单个登录用户始终由同一个进程来处理,这样你就可以用原来全局字典缓存的方式了

https://blog.csdn.net/lvshaorong/article/details/78309514
可以看看这个
wuwukai007
2019-08-28 18:22:54 +08:00
sor,socket 好像不可以序列化尴尬了
est
2019-08-28 18:55:29 +08:00
最终的目的,不管怎么做,ftp 连接池的维护,都会落到一个进程来负责。所以最直接的方式是,uwsgi 里 workers 数量改成 1 即可。

可能其他 web 请求处理量,一个 worker 不够,那也很简单,另外再跑一套 uwsgi,前面再套一个 nginx 反代或者 uwsgi router。
wangyongbo
2019-08-28 19:03:28 +08:00
我们是这样做的,1 浏览器,2 web 服务,3 ftp 连接服务。 就是把你现在整体的后端服务分成 2 和 3 两个服务。

1 和 2 之间用 http 协议,或者 websocket 协议,2 和 3 之间用消息队列通信,通信协议需要自己定义。

比如 用户要连接一个 ftp 服务器。通过 http 协议,发到 2, 然后 2 处理之后,比如验证权限,连接数量等等,然后把请求放到消息队列。3 从消息队列读取到请求之后,创建一个 ftp 连接。


可以根据实际需要扩展 2 和 3 的服务数量,互不干扰。
你觉得怎么样?
piaochen0
2019-08-29 09:33:27 +08:00
@wangyongbo 消息队列是用的 ActiveMQ 这种中间件来实现的吗?我没怎么用过这种模式,根据我的理解,这应该是异步的操作吧。web 服务把消息发给了消息队列,队列里面一个一个处理,处理完了以后,通知 web 服务。这个时候还能通过 response 通知前端页面吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/595932

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX