Django 远程连接对象缓存的方案 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
piaochen0
V2EX    Django

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

  •  
  •   piaochen0 2019-08-28 16:25:35 +08:00 4553 次点击
    这是一个创建于 2238 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    麻烦各位赐教。

    13 条回复    2019-08-29 09:33:27 +08:00
    mayorbryant
        1
    mayorbryant  
       2019-08-28 16:29:49 +08:00
    用 redis 来替代你文中说的公共字典
    piaochen0
        2
    piaochen0  
    OP
       2019-08-28 16:35:44 +08:00
    @mayorbryant radis 可以缓存 ftp 这种连接类的对象吗?印象中这种只适合可序列化的对象吧。
    wuwukai007
        3
    wuwukai007  
       2019-08-28 16:39:30 +08:00   1
    redis 可以指定序列化方式,默认是 json,可以指定 pickle,但是 pickle 也有很多序列不了的对象,
    这个时候用 dill 第三方序列化 pip install dill
    可以序列化 函数,嵌套函数,匿名函数,main 函数等大多数 py 对象
    然后 dill 序列化后是字节 ,pickle 可以识别
    mayorbryant
        4
    mayorbryant  
       2019-08-28 16:42:19 +08:00   1
    @piaochen0 楼上说的也是我想表达的
    piaochen0
        5
    piaochen0  
    OP
       2019-08-28 17:10:15 +08:00
    提个想法,这种 FTP 连接对象,可以放到 session 中吗?会有什么问题没有?
    jesnridy
        6
    jesnridy  
       2019-08-28 17:30:00 +08:00
    @piaochen0 我第一个想法就是放到 session 中,链接 session 对象放在单例模型中搞,登出的时候断开 session
    sujin190
        7
    sujin190  
       2019-08-28 17:40:31 +08:00   2
    楼上 redis 或者 session 序列化的,你们认真的么?一个进程拥有的 socket 能通过 pickle 弄到另外一个进程去?见鬼了吧
    socket 底层就是文件句柄,数据能序列化,文件句柄复制到另外一个进程怎么用?
    所以你这个 uwsgi 部署的 Django 是很难做出来的,估计需要用 tornado 或者 asyncio 做一个代理连接层吧,也不复杂
    piaochen0
        8
    piaochen0  
    OP
       2019-08-28 17:56:07 +08:00
    @jesnridy session 的方案不行,我刚试了。无法序列化
    sujin190
        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
    可以看看这个
    wuwukai007
        10
    wuwukai007  
       2019-08-28 18:22:54 +08:00
    sor,socket 好像不可以序列化尴尬了
    est
        11
    est  
       2019-08-28 18:55:29 +08:00   1
    最终的目的,不管怎么做,ftp 连接池的维护,都会落到一个进程来负责。所以最直接的方式是,uwsgi 里 workers 数量改成 1 即可。

    可能其他 web 请求处理量,一个 worker 不够,那也很简单,另外再跑一套 uwsgi,前面再套一个 nginx 反代或者 uwsgi router。
    wangyongbo
        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 的服务数量,互不干扰。
    你觉得怎么样?
    piaochen0
        13
    piaochen0  
    OP
       2019-08-29 09:33:27 +08:00
    @wangyongbo 消息队列是用的 ActiveMQ 这种中间件来实现的吗?我没怎么用过这种模式,根据我的理解,这应该是异步的操作吧。web 服务把消息发给了消息队列,队列里面一个一个处理,处理完了以后,通知 web 服务。这个时候还能通过 response 通知前端页面吗?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5521 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 08:29 PVG 16:29 LAX 01:29 JFK 04:29
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86