zoukankan      html  css  js  c++  java
  • 用python做分布式定时器

    分布式任务系统 (Python)

    github地址 https://github.com/thomashuang/Lilac/blob/master/README.rst

    这里将介绍Liac的设计架构,首先分布式任务系统的定义是在多台服务器执行定时任务。

    实现技术

    1. 分布式定时调度,可以同时在不同服务执行。
    2. 使用Leader/Follower Pattern 多线程模式。
    3. 只是周期定时,crontab定时,定点任务。
    4. 重试失败任务。
    5. 线程安全db api,支持读写分离模式
    6. 使用data-mapper模式
    7. web ui化管理工具(使用MVC,基于 mako gevent cherrypy)

    定时任务的类型

    一次性定时任务

    在将来某个时间点需要执行一次

    周期性任务

    对于周期性任务最为简单的就是间隔性执行任务,比如每五分钟需要执行一次。

    如何做到分布式任务

    从分布式的理解来看,需要一种机制保证正常给各个任务执行服务准确及时的分派任务,并却要减少各个服务之间竞争。于是最简单的任务执行者向任务管理服务所要当前可以执行服务。回分派相关任务,当执行任务完需要汇报给任务调度管理服务,并筹划任务下一步的状态。但这里设计原理并非如此,对于任务管理器而言,只是作任务的的长久序列化,对于怎么提取,任务的执行状态(完成,失败,重试等),都由任务执行者决定。

    分派流程

    1. 定时服务生成唯一task标识符,依据下次执行时间在db标记任务。
    2. 依据task标识符获取可执行任务。
    3. 执行任务,保存刷新最新状态。

    使用MYSQL如何做到任务的分派

    使用关联数据数据,而非内存数据库比如heaq做任务调度,可能有些开始让人难以理解。现在有很多任务执行服务,在领取任务时,首先生成一个一个具有唯一性标识的(uuid)的对mysql的cron表做更新 UPDATE cron set task_id=$identify WHERE task_id IS NULL AND next_run<now() LIMIT $take_size; 这样标识了当前服务的可执行的任务。然后使用SELECT × FROM cron WHERE task_id=$identify, 于是就能拉当前服务可以执行任务。然后对于任务的是什么,该怎么执行。

    任务线程池的设计与优化

    对于scheduler任务的执行,因为一次认领多个任务,最初是想使用生产消费者模式,如果master线程与工人线程共享队列,会造成任务竞争激烈。于是优化成每个工人线程拥有自己的任务队列,master线程轮询分派任务,但这样,减少了线程对资源的竞争,但在空闲时,如果没有特殊处理可能造成cpu的占用。最后使用的是一种leader follower的变种。master线程仅负责分派任务。 follower将在挂起与任务执行(processing)状态转换。另外这样可能任务众多,如果线程池没有空闲线程怎么办,办法是将这些任务放入一个闲置队列,加入一个心跳(定时器)线程负责闲置任务的再次分配。对于python而言,真正的优化在于减少任务空闲时对cpu的抢占。

    数据层

    最初设计时,考虑到对多数据库的支持。首先使用记录(activerecord)模式,这种模式把模型与数据落地放置与同一个类,随着业务的复杂后,模式优势越来越小,造成数据落地层行为与模型行为的混淆。为了维护性与后期的拓展性。最终采用了data-mapper模式,这样在拓展多数据库支持时,仅仅考虑数据落地层的接口重写,同样也为后期的数据库接口优化提供了空间。

    值得一提的是,在使用mysql作为数据库,因为使用mysqldb所以需要简单的封装一个连接池,并简化接口的使用。db模块有三个重要的接口setup 将帮助设置数据库, query将用于select的查询,execute是用来做增删改的语句,因为这样更方便数据库的读写分离。

    setup

    setup将用来注册数据库,如果指定slave为true,这个数据库将会注册到读数据库
    key用来标示数据库,默认注册到default。
    需要注意的是你必须先注册一个master数据库才能注册从数据库。

    query

    用于select的查询语句,指定many时将会使用mydqldb的fetchmany接口,key用来标示数据库,默认为default。

    execute

    对于insert语句将会返回lastwordid
    而update与delete将会是rowcount。

    web 管理平台

    web管理平台使用的cherrypy与routes mako实现,考虑到cherrypy也许有些慢。于是给cherypy打上猴子补丁,而使用gevent的wsgiserver。 功能基本实现了简单的用户角色和任务管理功能。

  • 相关阅读:
    20155313 杨瀚 《网络对抗技术》实验九 Web安全基础
    20155313 杨瀚 《网络对抗技术》实验八 Web基础
    20155313 杨瀚 《网络对抗技术》实验七 网络欺诈防范
    20155313 杨瀚 《网络对抗技术》实验六 信息搜集与漏洞扫描
    20155313 杨瀚 《网络对抗技术》实验五 MSF基础应用
    20155313 杨瀚 《网络对抗技术》实验四 恶意代码分析
    20155313 杨瀚 《网络对抗技术》实验三 免杀原理与实践
    20155313 杨瀚 《网络对抗技术》实验二 后门原理与实践
    20155313 杨瀚 《网络对抗技术》实验一 PC平台逆向破解(5)M
    20155313 2017-2018-1 《信息安全系统设计基础》课程总结
  • 原文地址:https://www.cnblogs.com/nagi/p/4191432.html
Copyright © 2011-2022 走看看