今天给大家介绍一款新武器。我自研的一个java组件easyTask-L。这个是做啥的呢?我之前研发了一款单机版本的easyTask,这次是要介绍另外一款easyTask-L。区别就是后者支持分布式环境,任务数据支持多个备份,具备了真正意义上的高可用。同时它又是轻量级的分布式应用,原因是因为它还不是一个独立的中间件,它需要一个宿主程序才能使用。做成独立的中间件是我后面要继续做的一个版本。

  组件开源地址:https://github.com/liuche51/easyTask-L

  废话不多说,先来介绍下easyTask-L组件的特性。

  高可用:因为我们是分布式leader-follow集群,每个任务多有多个备份数据,所以可靠性非常高

  秒级触发:我们是采用时钟秒级分片的数据结构,支持秒级触发任务。不早也不迟

  分布式:组件支持分布式

  高并发:支持多线程同时提交任务,支持多线程同时执行任务

  数据一致性:使用TCC事务机制,保障数据在集群中的强一致性

  海量任务:节点可以存储非常多的任务,只要内存和磁盘足够。触发效率也是极高。需要配置好分派任务线程池和执行任务线程池大小即可

  开源:组件完全在GitHub上开源。任何人都可以随意使用,在不侵犯著作权情况下

  易使用:无需独立部署集群,嵌入式开发。不过多的依赖于第三方中间件,除了zookeeper。

  easyTask-L组件的整体架构如下:

  整体采用分布式设计,leader-follow风格。集群中每一个节点都是leader,同时也可能是其他某个节点的follow。每个leader都有若干个follow。leader上提交的新任务都会强制同步到follow中,删除任务同时也会强制删除follow中的备份任务。集群中所有节点都会在zookeeper中注册并维持心跳。

  easyTask-L组件的核心“环形队列”的设计架构如下:

  环形队列在之前单机版的easyTask中也讲过,原理都是类似的。客户端提交任务,服务端先将任务进行持久化,再添加上环形队列这个数据结构中去,等待时间片轮询的到来。不同的是这里的持久化机制,改成了分布式存储了。不仅leader自己存储起来,还要同步存储到其follow中去。删除一个任务也是类似的过程。

  任务添加时会计算其触发所属的时间分片槽,等环形队列的始终秒针到达时会判断任务是否可以被执行了。如果可以执行了,则分派任务线程池将其丢入执行任务线程池等待执行。只要执行任务线程池线程数足够,任务将立即得到执行。

  大概的原理清晰了,接下来就是写个HelloWorld程序了!

  easyTask-L不是一个中间件,所以需要一个宿主程式。建议在微服务框架如:dubbo、spring-cloud中使用此组件,并建立一个独立的专门用于处理延时任务的服务模块。这样可以使服务尽可能少的频繁更新重启。保持集群的稳定性。下面我将以一个springboot应用为例来给大家演示如何使用easyTask-L组件

  第一步:引入jar包

  如果你是Maven项目,可以使用如下方式配置引入jar包。这可以让项目自动引入easyTask-L中依赖的其他第三方jar包。最新版本请在maven中央仓库中查询。请在pom.xml中加入以下引用

 <dependency>
<groupId>com.github.liuche51</groupId>
<artifactId>easyTask-L</artifactId>
<version>1.0.1</version>
</dependency>

  第二步:配置启动环形队列

  这里以springboot应用为例,在application.yml中做如下配置

server:
port: 8081
spring:
application:
name: easyTask-L
easyTaskL:
zkAddress: 127.0.0.1:2181
taskStorePath: C:/db/node1
serverPort: 2021
sQLlitePoolSize: 5
backupCount: 2
dispatchPool:
corePoolSize: 5
maximumPoolSize: 50
workPool:
corePoolSize: 5
maximumPoolSize: 50

  新建一个启动配置类EasyTaskLConf.java

 package com.github.liuche51.easyTaskL.config;

 import com.github.liuche51.easyTask.core.AnnularQueue;
import com.github.liuche51.easyTask.core.EasyTaskConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor; @Configuration
public class EasyTaskLConf {
private static Logger log = LoggerFactory.getLogger(EasyTaskLConf.class);
@Value("${easyTaskL.zkAddress}")
private String zkAddress;
@Value("${easyTaskL.taskStorePath}")
private String taskStorePath;
@Value("${easyTaskL.serverPort}")
private int serverPort;
@Value("${easyTaskL.sQLlitePoolSize}")
private int sQLlitePoolSize;
@Value("${easyTaskL.backupCount}")
private int backupCount;
@Value("${easyTaskL.dispatchPool.corePoolSize}")
private int dispatchCorePoolSize;
@Value("${easyTaskL.dispatchPool.maximumPoolSize}")
private int dispatchMaximumPoolSize;
@Value("${easyTaskL.workPool.corePoolSize}")
private int workPoolCorePoolSize;
@Value("${easyTaskL.workPool.maximumPoolSize}")
private int workPoolMaximumPoolSize;
@Bean
public AnnularQueue initAnnularQueue(){
try {
EasyTaskConfig config =new EasyTaskConfig();
config.setTaskStorePath(taskStorePath);
config.setServerPort(serverPort);
config.setSQLlitePoolSize(sQLlitePoolSize);
//config.setBackupCount(backupCount);
config.setZkAddress(zkAddress);
AnnularQueue annularQueue = AnnularQueue.getInstance();
config.setDispatchs(new ThreadPoolExecutor(dispatchCorePoolSize, dispatchMaximumPoolSize, 1000, java.util.concurrent.TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
config.setWorkers(new ThreadPoolExecutor(workPoolCorePoolSize, workPoolMaximumPoolSize, 1000, java.util.concurrent.TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
annularQueue.start(config);
return annularQueue;
}catch (Exception e){
log.error("",e);
return null;
}
} }

EasyTaskLConf.java

  第三步:建立延时任务处理类

package com.github.liuche51.easyTaskL.task;
import com.github.liuche51.easyTask.dto.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue; public class CusTask1 extends Task implements Runnable {
private static Logger log = LoggerFactory.getLogger(CusTask1.class);
@Override
public void run() {
Map<String, String> param = getParam();
if (param != null && param.size() > 0) {
log.info("任务1已执行!姓名:{} 生日:{} 年龄:{} 线程ID:{}", param.get("name"), param.get("birthday"), param.get("age"), param.get("threadid"));
}
}
}

  第四步:向环形队列中添加任务

  新建一个Controller,增加以下Action方法。

@RequestMapping("/once")
@ResponseBody
public String once(@RequestParam("name") String name, @RequestParam("time") int time) {
CusTask1 task1 = new CusTask1();
task1.setEndTimestamp(ZonedDateTime.now().plusSeconds(time).toInstant().toEpochMilli());
Map<String, String> param = new HashMap<String, String>() {
{
put("name", name);
put("birthday", "1996-1-1");
put("age", "28");
put("threadid", String.valueOf(Thread.currentThread().getId()));
}
};
task1.setParam(param);
return AnnularQueue.getInstance().submitAllowWait(task1);
}

  完整的demo可以使用Git克隆我的一个开源项目:https://gitee.com/liuche/DubboServer.git  找到子项目easyTask-L-demo即可

轻量级分布式延时任务处理组件easyTask-L-入门篇的更多相关文章

  1. 新一代分布式实时流处理引擎Flink入门实战之先导理论篇-上

    @ 目录 概述 定义 为什么使用Flink 应用行业和场景 应用行业 应用场景 实时数仓演变 Flink VS Spark 架构 系统架构 术语 无界和有界数据 流式分析基础 分层API 运行模式 作 ...

  2. .NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一)

    在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下FluentValidation验证组件.那里只是概述了一下,并没有对其使用和强大功能做深入研究 ...

  3. 轻量级分布式 RPC 框架

    @import url(/css/cuteeditor.css); 源码地址:http://git.oschina.net/huangyong/rpc RPC,即 Remote Procedure C ...

  4. 【转】轻量级分布式 RPC 框架

    第一步:编写服务接口 第二步:编写服务接口的实现类 第三步:配置服务端 第四步:启动服务器并发布服务 第五步:实现服务注册 第六步:实现 RPC 服务器 第七步:配置客户端 第八步:实现服务发现 第九 ...

  5. .NET轻量级DBHelpers数据访问组件

    一.摘要 一说到ADO.NET大家可能立刻想到的就是增.删.改.查(CRUD)操作,然后再接就想到项目中的SQLHelper.没错本课分享课阿笨给大家带来的是来源于github上开源的DAO数据库访问 ...

  6. NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(转载)

    原文地址:http://www.cnblogs.com/asxinyu/p/dotnet_Opensource_project_FluentValidation_1.html 阅读目录 1.基本介绍 ...

  7. 轻量级分布式 RPC 框架(转)

    RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. RPC 可基于 HTTP 或 TCP 协议,Web Servi ...

  8. ZeroMQ——一个轻量级的消息通信组件

    ZeroMQ是一个轻量级的消息通信组件,尽管名字中包含了"MQ",严格上来讲ZeroMQ并不是"消息队列/消息中间件".ZeroMQ是一个传输层API库, 更关 ...

  9. ZeroMQ——一个轻量级的消息通信组件 C#

    ZeroMQ——一个轻量级的消息通信组件 ZeroMQ是一个轻量级的消息通信组件,尽管名字中包含了"MQ",严格上来讲ZeroMQ并不是"消息队列/消息中间件" ...

随机推荐

  1. 2、尚硅谷_SSM高级整合_创建Maven项目.avi

    第一步我们新建立一个web工程 这里首先要勾选上enable的第一个复选框 这里要勾选上add maven support 我们在pom.xml中添加sevlet的依赖 创建java web项目之后, ...

  2. mysql 出现You can't specify target table for update in FROM clause错误的解决方法

    mysql出现You can’t specify target table for update in FROM clause 这个错误的意思是不能在同一个sql语句中,先select同一个表的某些值 ...

  3. ubuntu无法安装vim、tree等解决办法

    rm /etc/apt/sources.list.d/* 删除该目录下所有文件

  4. (私人收藏)[开发必备]最全Java离线快速查找手册(可查询可学习,带实例)

    (私人收藏)[开发必备]最全Java离线快速查找手册(可查询可学习,带实例) https://pan.baidu.com/s/1L54VuFwCdKVnQGVc8vD1TQnwmj java手册 Ja ...

  5. TensorFlow中的显存管理器——BFC Allocator

    背景 作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 使用GPU训练时,一次训练任务无论是模型参数还是中间结果都需要占用大量显存.为了 ...

  6. HTML5(五)Geolocation

    HTML5 Geolocation 定位用户的位置 HTML5 Geolocation API 用于获得用户的地理位置. 鉴于该特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的. 注意 ...

  7. 一文说清 KubeSphere 容器平台的价值

    KubeSphere 作为云原生家族 后起之秀,开源近两年的时间以来收获了诸多用户与开发者的认可.本文通过大白话从零诠释 KubeSphere 的定位与价值,以及不同团队为什么会选择 KubeSphe ...

  8. Traffic Real Time Query System,题解

    题目链接 题意: 问从一条边到另一条边的必经点. 分析: 首先,问必经点,当然是要点双缩点(圆方树)啦,关键是把边映射到哪一点上,其实直接放在某联通分量的方点上就行,但是这个点并不好找,所以我们考虑一 ...

  9. 14.刚体组件Rigidbody

    刚体组件是物理类组件,添加有刚体组件的物体,会像现实生活中的物体一样有重力.会下落.能碰撞. 给物体添加刚体: 选中游戏物体->菜单Component->Physics->Rigid ...

  10. 12个Visual Studio调试效率技巧

    在这篇文章中,我们假定读者了解VS基本的调试知识,如: F5 开始使用调试器运行程序 F9 在当前行设置断点 F10 运行到下一个断点处 F5 从被调试的已停止程序恢复执行 F11 步进到函数内(如果 ...