zoukankan      html  css  js  c++  java
  • zookeeper实战:SingleWorker代码样例

     

       我们需要一个“单点worker”系统,此系统来确保系统中定时任务在分布式环境中,任意时刻只有一个实例处于活跃;比如,生产环境中,有6台机器支撑一个应用,但是一个应用中有30个定时任务,这些任务有些必须被在“单线程”环境中运行(例如“数据统计”任务),避免并发的原因不是在java层面,可能是在操作db数据时,或者是在消息消费时,或者是信息推送时等。某个指标的“数据统计”任务,每天只需要执行一次,即使执行多次也是妄费,因为这种类型的定时任务,需要被“单点”。同时,如果一个任务在没有报告结果的情况下异常推出,我们仍然期望集群中其他实例能够主动“接管”它。在实现不良好的架构中,可能有些开发者使用手动触发特定脚本的方式执行,有些web项目可能是通过配置特定host的方式开启任务。对于某些定时任务,可能会采用quartz-cluster中的某些实现,但是他需要数据库的额外支持。
         此时,我们将使用zookeeper来实现此功能。本实例提供了如下功能展示:
        1) 提供了单点worker功能
        2) 提供了worker均衡能力(30个worker相对均匀的分配到6台机器上)
        3) 提供了worker失效接管能力。

         但是仍有很多亟待解决的问题:
        1) 无法确保任务的接管是及时的,即一个任务执行者失效,将会在一定的过期时间后,才会被其他sid接管
        2) 在极少的情况下,仍然会有一个任务同时被2个sid执行。
        3) 在极少的情况下,会有极短的时间内,一个任务不会被任何sid接管,处于“孤立”状态
        尽管zk提供了watch机制,但是上述问题,不仅不能完全避免,还会额外增加代码的复杂度。最终我个人放弃了对在此类中使用watch的想法。。
        注意:zk中exist和create/delete等操作并非原子,可能在exist返回false的情况下,去create此节点,也有可能抛出NoExistsException;你应该能够想到“并发”环境造成此问题的时机(其他zk客户端也有类似的操作,并发)。
        注意:在zk中删除父节点,将会导致子节点一并删除;同理,如果创建一个节点,那么它的各级父节点必须已经存在,且节点的层级越深,对zk底层存储而言数据结构越冗杂。
     
        数据结构与设计思路:
        1) serverType为当前应用标识,我们期望每个应用都有各自的serverType,方便数据分类; jobType为任务类型或者任务名称;如下全节点表示某个serverType的jobType下有sid1,sid2,sid3共三个实例(例如tomcat实例,或者物理机器标识)参与了此任务。zk节点路径格式:
            /severType/jobType/register/sid1 
            ............................../sid2
            ............................../sid3
        2) 表示此jobType,被sid1运行。zk节点路径格式
            /severType/jobType/alive/sid1 挂载数据:null
        3) /serverType/jobType 挂载数据:cronExpression;将任务的“cron表达式”作为数据挂载
        4) {todu} 表示serverType下每个sid运行的任务个数,我们可以用来“均衡”任务,将新任务分配给任务较少的sid上。
            /serverType/sid1 挂载数据:任务个数.

     

     

    如下是本人的代码样例,实际生产环境中代码与样例有区别,此处仅供参考,本实例基于zookeeper + quartz 2.1,如有错误之处,请不吝赐教:

    1) TestMain.java :测试引导类

    2) PrintNumberJob.java:一个简单的任务,打印一个随即数字。

    3) PrintTimeJob.java:一个简单的任务,打印当前时间。

    4) SingleWorkerManager.java:核心类,用于处理调用者提交的任务,并确保结果符合预期。此类有2个内部工作线程组成,分别处理zk数据同步和用户任务交付等工作。

    zookeeper实战:SingleWorker代码样例

  • 相关阅读:
    如何使用 vimdiff 来 git diff /svn diff
    nginx https ssl 设置受信任证书[原创]
    Nginx配置proxy_pass转发的/路径问题
    116、Android获取Manifest中<meta-data>元素的值
    Android Studio系列教程四--Gradle基础(转载)
    Android Studio系列教程六--Gradle多渠道打包(转载)
    1、Android Studio集成极光推送(Jpush) 报错 java.lang.UnsatisfiedLinkError: cn.jpush.android.service.PushProtoco
    Java数组转成list,list转数组
    115、定时器(TimerTask+Timer+Handler)
    114、Android禁止ViewPager的左右滑动
  • 原文地址:https://www.cnblogs.com/jing1617/p/7264087.html
Copyright © 2011-2022 走看看