今天给大家介绍一款新武器。我自研的一个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. JavaWeb网上图书商城完整项目--day02-20.修改密码各层实现

    1.我们来看看后台操作的业务流程 每一层都按照上面的步骤来进行实现: 这里我们要使用commUtils.toBean把表单提交的参数封装成User对象,必须保证User对象中的字段和表单提交的字段的名 ...

  2. Python3-pymysql模块-数据库操作之MySQL

    博客转载 http://www.cnblogs.com/alex3714/articles/5950372.html 代码示例 import pymysql conn = None cursor = ...

  3. Android Studio 插件 ADBWifi 无线调试真机

    长话短说,步骤如下 Android Studio 安装插件 ADB Wifi.这一步可以选择AS->Settings->Plugins->Market搜索:或者可以选择去插件官网下载 ...

  4. vue基础入门(2.2)

    2.2.基础指令 2.2.1.什么是指令 指令 (Directives) 是带有 v- 前缀的特殊特性,指令特性的值预期是单个 JavaScript 表达式,指令的职责是,当表达式的值改变时,将其产生 ...

  5. Java中时间加减的比较

    public class TestDate{ public static void main(String[] args){try{ Date date=new Date(); DateFormat  ...

  6. 第一步:安装centos_8

    关于centos的安装其实大部分时候都是在虚拟机环境下安装. 好处无疑有这几个:方便,快速,主要就是整出事情了我可以直接删了重装 我这边是在vmware下进行一个安装 vmware我这边给出下载链接: ...

  7. django 类视图的使用

    使用django框架也有挺长时间了,但是一直都没有用过django的类视图,因为之前跟着网上教程学习时,觉得类视图是进阶的知识,可能目前还达不到吧 但今天在做项目的时候用到了,感觉真的太方便了吧,而且 ...

  8. idea2020.1.2破解,亲测可行,激活至2089年!

    一.下载最新版IDEA2020安装包 官网:https://www.jetbrains.com/idea/download/ 旧版:https://www.jetbrains.com/idea/dow ...

  9. 控制shell终端提示符格式和颜色

    字体颜色值 (ASCII) 背景颜色值 (ASCII) 显示颜色 30 40 黑色 31 41 红色 32 42 绿色 33 43 黄色 34 44 蓝色 35 45 紫红色 36 46 青蓝色 37 ...

  10. 腾讯T8纯手写66个微服务架构设计模式,全部学会真的“变强”了

    微服务的概念虽然直观易懂,但“细节是魔鬼”,微服务在实操落地的环节中存在诸多挑战.我们在为企业提供PaaS.人工智能.云原生平台等数字化转型解决方案时也发现,企业实现云原生,并充分利用PaaS能力的第 ...