一个并发的、可用的下载服务架构设计

一个并发/异步的下载服务设计

接收任务(步骤1)

  • 提供批量任务/单个任务接口
  • 收到任务之后随即对每一个任务启动process_task线程去处理

处理任务(步骤2)

  • 根据每个任务的 {数据源}_{文件名} 作为redis的key去集群中查出该任务的值

    • 每个任务有一个状态码,status_code为3位数字, abc, a代表是否下载完成,b代表是否正在下载,c代表第n次下载

    • 若redis已有该任务status_code

      • 状态a或b为true,不予下载,线程退出

      • 状态a与b都为false,则根据c进行判断将采用哪个级别的代理(默认I、II、III级代理的速度、稳定性、IP陌生性递增)

        • 此时c值必然大于0,若c为1,则说明此次为第二次下载,第一次的代理有问题,则此次采用II级代理
        • 若c为2,则采用III级代理
        • 若c为3,说明已经下载过3次,没有更好/更陌生的代理,任务失败,退出
      • 若成功选择代理,则先将redis的status_code置为(a=false,b=true,c=c+1)

      • 下载完成后,将redis的status_code置为(a=true,b=false,c)

    • 若redis中没有该key,则说明此任务为第一次下载

    • 则本地有一个hash结构,key为目标url的域名,value为该域名下已经执行过的任务数量,暂时叫它host_count

      • 按照host_count按照一定比例(x:y:z)在I、II、III级代理之间进行轮询取代理,例如III级代理的稳定性、速度较高,则III级代理的比重设置大一点,让该host下的大多数任务都采用III级代理
    • 选择代理后执行下载,在此之前先将redis的status_code置为(a=false,b=true,c=1)

    • 下载完成后,将redis的status_code置为(a=true,b=false,c)

关键问题

  • redis并不能去重所有的重复,假设ms级别内有同一个 {数据源}_{文件名} 的多个任务发送过来,那么有可能同时启n个线程去同时取redis的value,此时这n个线程均会去执行下载任务,这样浪费了代理资源

    • 解决方案:以 {数据源}_{文件名} 为key,本地存一个hashset,采用锁进行线程间互斥读写,任务准备执行下载动作时,立即将其写入set,下载完成后,在redis-value更新之后立即从set中去除
  • 服务重启难:服务关闭时,有可能具有多个正在执行下载的任务,重启之后,这些下载任务有可能不会再被扫描列表页的程序发送过来,那么这些任务就被永久丢失了

    • 解决方案:任务准备执行下载动作时,立即创建 {数据源}_{文件名}.temp 缓冲文件,下载完成后,先将响应的二进制数组写入该temp文件,写完成后直接将该temp文件重命名为html/pdf/doc等实际文件格式
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值