自己写一个分布式定时任务框架+负载均衡+OpenAPI异步调用!!

自己写一个分布式定时任务框架+负载均衡+OpenAPI异步调用! 主流框架往往为了适配更多的场景,支持足够多的功能,往往体积大,且不易动态扩展,为了对项目有最大的控制,在解决以上业务场景的前提下,进行部分功能的修剪,也希望能更好的从中学习主流框架的设计思想,于是决定重写一个定时任务框架。对于producer,前面提到,为了应对大量定时任务的场景,对于任务的操作,应全部是异步的,我们引入超时机制即可,当超过一定的时间未收到ack,或者返回错误响应,选择下一个server发起重试。),意味着只有被分配到线程(消费者)消费时,才能被ack,而活跃的线程数并不多。 阅读详情

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

e47f1fddd7fd1dfab6016452c8899f14.gif

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、ERP、CRM、AI 大模型等等功能:

  • Boot 多模块架构:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • Cloud 微服务架构:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK 17/21 + SpringBoot 3.3、JDK 8/11 + Spring Boot 2.7 双版本 

来源:juejin.cn/post/
7436925608943419411


项目背景

目前的定时任务框架已经很成熟,从QuartZ到xxl-job,再到近几年出现的PowerJob,既然有这么多的好的实现,为什么还是选择重写一个定时任务框架呢?

开发中遇到这样的场景,业务层面需要频繁的创建修改定时任务,在考虑分布式的架构下,对于目前可以实现该功能的框架中:

  • MQ的延时队列无法动态调整任务参数;

  • redis的过期策略需要保存太久的key且可能会有BigKey

  • xxljob没有原生的openAPI,其基于数据库锁的调度只是实现server的高可用而不是高性能;

  • powerjob的openAPI又是基于http的同步阻塞调度,并且对于server的负载均衡,由于其分组隔离设计,需要开发者手动配置,在高并发下的定时任务操作下,并不能很好的调度server集群。

主流框架往往为了适配更多的场景,支持足够多的功能,往往体积大,且不易动态扩展,为了对项目有最大的控制,在解决以上业务场景的前提下,进行部分功能的修剪,也希望能更好的从中学习主流框架的设计思想,于是决定重写一个定时任务框架。

本文章主要介绍该项目相对于目前主流定时任务框架的特性,对于定时任务调度和发现的详细可以见源码,文章末尾也给出了流程图方便理解

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

定位

这是一个基于 PowerJob 的重写和重构版本,修改和扩展了原始项目的功能,以更好地适配业务需求。

  • 支持定时任务频繁创建和任务参数频繁动态变动的场景(提供轻量API,并使用内置消息队列异步处理)

  • 支持大量定时任务并发执行的场景,实现负载均衡(分组隔离+应用级别的锁实现)

  • 主要针对小型任务 ,无需过多配置,不对任务实例进行操作

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

技术选型

通信 : gRPC(基于netty的nio)
序列化 :Protobuf编码格式编解码
负载均衡 :自己实现的注册中心NameServer
    |___ 策略 : 服务端最小调度次数策略
    |___ 交互 :pull+push
消息队列 : 自己实现的简易消息队列
    |___ 消息发送 : 异步+超时重试
    |___ 持久化 :mmap+同步刷盘策略
    |___ 消息重试 :多级延时队列+死信队列
定时调度 : 时间轮算法

项目结构

├── LICENSE
├── k-job-common // 各组件的公共依赖,开发者无需感知
├── k-job-nameServer // server和worker的注册中心,提供负载均衡
├── k-job-producer //普通Jar包,提供 OpenAPI,内置消息队列的异步发送
├── k-job-server // 基于SpringBoot实现的调度服务器
├── k-job-worker-boot-starter // kjob-worker 的 spring-boot-starter ,spring boot 应用可以通用引入该依赖一键接入 kjob-server 
├── k-job-worker // 普通Jar包,接入kjob-server的应用需要依赖该Jar包
└── pom.xml

特性

负载均衡(解决大量定时任务并发执行场景)

对于worker的负载均衡策略有许多且已经由较好的解决(轮询,健康值等),但是,我们目前的系统存在大量的定时任务,考虑server层面,可能会存在以下情况:

  • server一次调度从DB中获取太多任务,可能会OOM

  • 发起调度请求是由线程池负责,可能会有性能瓶颈,我们的系统对时间是敏感的,对时间精度高要求

  • 我们的OpenAPI同样也不希望大量请求落在同一个server上

在分布式系统下,解决定时任务并发执行往往考虑server集群的负载均衡(这里的负载均衡特指server集群能够根据自身负载,动态调度worker集群),但是对于定时任务框架,需要关注集群下的任务重复调度问题,目前的定时任务框架大都为了解决该问题而不能较好实现负载均衡。

通过查看源码,xxljob的调度,在每次查询数据库获取任务前,通过数据库行锁进行了全局加锁,保证同一时刻只有一个server在进行调度来避免重复调度,但是无法发挥集群server的调度能力

对于powerjob的调度,通过分组隔离机制(详细可以看官方文档)避免了重复调度,但是同样带来了问题:同一app下的worker集群只能被一台server调度,如果该server的任务太多了呢?如果只有一个业务对应的app,如何用server集群来负载均衡呢?

基于以上问题,增加了一个注册中心nameServer模块来负责负载均衡:

8a7ecb94b8ea6d6ae27899b5b13a0ca1.jpeg

最小调度次数策略:NameServer记录server集群状态并维护各个server的分配任务次数,由于server是否调度某个worker由表中数据决定,worker会在每次pull判断是否发起请求更新server中的调度关系表,并将目前分组交由最小调度次数的server来调度,当且仅当以下发生:

  • 同一app分组下的workerNum > threshold

  • 该分组对应的server的scheduleTimes > minServerScheduleTime x 2

考虑到server的地理位置,通信效率等因素,后续可以考虑增加每个server的权重来更优分配

关键代码如下:

public ReBalanceInfo getServerAddressReBalanceList(String serverAddress, String appName) {
        // first req, serverAddress is empty
        if(serverAddress.isEmpty()){
            ReBalanceInfo reBalanceInfo = new ReBalanceInfo();
            reBalanceInfo.setSplit(false);
            reBalanceInfo.setServerIpList(new ArrayList<String>(serverAddressSet));
            reBalanceInfo.setSubAppName("");
            return reBalanceInfo;
        }
        ReBalanceInfo reBalanceInfo = new ReBalanceInfo();
        // get sorted scheduleTimes serverList
        List<String> newServerIpList = serverAddress2ScheduleTimesMap.keySet().stream().sorted(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return (int) (serverAddress2ScheduleTimesMap.get(o1) - serverAddress2ScheduleTimesMap.get(o2));
            }
        }).collect(Collectors.toList());

        // see if split
        if(!appName2WorkerNumMap.isEmpty() && appName2WorkerNumMap.get(appName) > maxWorkerNum && appName2WorkerNumMap.get(appName) % maxWorkerNum == 1){
            // return new serverIpList
            reBalanceInfo.setSplit(true);
            reBalanceInfo.setChangeServer(false);
            reBalanceInfo.setServerIpList(newServerIpList);
            reBalanceInfo.setSubAppName(appName + ":" + appName2WorkerNumMap.size());
            return reBalanceInfo;
        }
        // see if need change server
        Long lestScheduleTimes = serverAddress2ScheduleTimesMap.get(newServerIpList.get(newServerIpList.size() - 1));
        Long comparedScheduleTimes = lestScheduleTimes == 0 ? 1 : lestScheduleTimes;
        if(serverAddress2ScheduleTimesMap.get(serverAddress) / comparedScheduleTimes > 2){
            reBalanceInfo.setSplit(false);
            reBalanceInfo.setChangeServer(true);
            // first server is target lest scheduleTimes server
            reBalanceInfo.setServerIpList(newServerIpList);
            reBalanceInfo.setSubAppName("");
            return reBalanceInfo;
        }
        // return default list
        reBalanceInfo.setSplit(false);
        reBalanceInfo.setServerIpList(new ArrayList<String>(serverAddressSet));
        reBalanceInfo.setSubAppName("");
        return reBalanceInfo;

    }

实现功能:

  • app组自动拆分: 可以为app设置组内worker数量阈值,超过阈值自动拆分subApp并分配负载均衡后的server

  • worker动态分配: 对于每一个subApp,当触发pull时,根据最小调度次数策略,可以分配至负载均衡后的server,开发者无需感知subApp

以上,解决PowerJob中同一worker分组只能被一个server调度问题,且subApp分组可以根据server的负载,实现动态依附至不同server,对于可能的重复调度问题,我们只需加上App级别的锁,相对于xxl-job的全局加锁性能更好。

消息队列(解决任务大量创建和频繁更改场景)

其实一开始用powerjob作为项目中的中间件,业务中的任务操作使用其openAPI。过程中感受最大的就是,我的业务只是根据任务id修改了任务参数,并不需要server的响应,为什么要同步阻塞?可靠性应由server保证而不是客户端的大量重试及等待。对于业务中频繁创建定时任务和改动,更应是异步操作。

一开始的想法是,使用grpc的futureStub进行异步发送,请求由Reactor线程监听事件,当事件可读时分配给业务线程池进行处理(gRPC内部已经实现)。所以需要做的似乎只是做一个Producer服务,并把stub全换成Future类型,对于jobId,我们用雪花算法拿到一个全局id就可以,无需server分配。

f06be29394c6a5c7842ae3aac0ceb97c.jpeg

但是以上设计有一个致命的问题------阻塞在BlockingQueue的请求无法ack,且server宕机存在消息丢失的可能!这违背了消息队列的设计(入队--ack--持久化--消费),意味着只有被分配到线程(消费者)消费时,才能被ack,而活跃的线程数并不多。故不能仅仅依赖gRPC的内部实现,需要自己实现消息队列

  • 可靠消息

以rocketMQ为例,producer的消息会先到达broker中的队列后返回ack,consumer再轮询从broker中pull重平衡处理后的消息消费。

考虑到本项目的设计无需路由,所有的server都可以接受消息,于是不再设计broker,将server和broker结合,每个server维护自己的队列,且消费自己队列的消息,这样还能减少一次通信。

这样可靠消息的解决就变成了:

  • producer到server的消息丢失------失败或者超时则依次遍历所有的server,一定能保证消息抵达,不再阐述

  • server的队列消息丢失(机器宕机)------持久化,采用同步刷盘策略,百分之百的可靠

持久化:同步刷盘机制借鉴了rocketMQ的mmap和commitLog/consumerQueue设计,将磁盘的文件映射到内存进行读写,每次消息进来先存到buffer后触发刷盘,成功后执行写响应的回调;用consumerQueue文件作为队列,server定时pull消费消息,详细见k-job-server.consumer.DefaultMessageStore,有详细注释

// 和rocketMQ一样,读写都是用mmap,因为内存buffer就是文件的映射,只是有刷盘机制
private MappedByteBuffer commitLogBuffer;  // 映射到内存的commitlog文件
private MappedByteBuffer consumerQueueBuffer; // 映射到内存的consumerQueue文件
private final AtomicLong commitLogBufferPosition = new AtomicLong(0);// consumerLog的buffer的位置,同步刷盘的情况下与consumerLog文件的位置保持一致
private final AtomicLong commitLogCurPosition = new AtomicLong(0);// consumerLog文件的目前位置,每次刷盘后就等于buffer位置
private final AtomicLong lastProcessedOffset = new AtomicLong(0);// consumerQueue的buffer拉取commitLog的位置,与commitLog相比,重启时就是consumerQueue文件最后一条消息的索引位置
private final AtomicLong currentConsumerQueuePosition = new AtomicLong(0); // consumerQueue文件的目前位置
private final AtomicLong consumerPosition = new AtomicLong(0); // 记录消费者在consumerQueue中的消费位置,这个只在目前的系统中有,类似于rocketMQ通过pull远程拉取
  • 消息重试

对于producer,前面提到,为了应对大量定时任务的场景,对于任务的操作,应全部是异步的,我们引入超时机制即可,当超过一定的时间未收到ack,或者返回错误响应,选择下一个server发起重试

对于consumer(server),使用多级延时队列,当某个消息消费失败后,投递至下一级延迟更久的延时队列,若全都消费失败则进入死信队列,需要人工干预

private static final Deque<MqCausa.Message> deadMessageQueue = new ArrayDeque<>();

    private static final List<DelayQueue<DelayedMessage>> delayQueueList = new ArrayList<>(2);
    /**
     * 逆序排序,因为重试次数到0则不再重试
     */
    private static List<Long> delayTimes = Lists.newArrayList(10000L, 5000L);
    public static void init(Consumer consumer) {
        delayQueueList.add(new DelayQueue<>());
        delayQueueList.add(new DelayQueue<>());
        Thread consumerThread1 = new Thread(() -> {
            try {
                while (true) {
                    // 从延时队列中取出消息(会等待直到消息到期)
                    DelayQueue<DelayedMessage> delayQueue = delayQueueList.get(0);
                    if(!delayQueue.isEmpty()) {
                        DelayedMessage message = delayQueue.take();
                        consumer.consume(message.message);
                        delayQueue.remove(message);
                        System.out.println("Consumed: " + message.getMessage() + " at " + System.currentTimeMillis());
                    }
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("Consumer thread interrupted");
            }
        });
     //  其他等级的延时队列

        consumerThread1.start();
    }
    public static void reConsume(MqCausa.Message msg) {
        if (msg.getRetryTime() == 0) {
            log.error("msg : {} is dead", msg);
            deadMessageQueue.add(msg);
            return;
        }
        MqCausa.Message build = msg.toBuilder().setRetryTime(msg.getRetryTime() - 1).build();
        DelayedMessage delayedMessage = new DelayedMessage(build, delayTimes.get(build.getRetryTime()));
        delayQueueList.get(msg.getRetryTime() - 1).add(delayedMessage);
    }


// 定义一个延时消息类,实现 Delayed 接口
static class DelayedMessage implements Delayed {
    private final MqCausa.Message message;
    private final long triggerTime; // 到期时间

    public DelayedMessage(MqCausa.Message message, long delayTime) {
        this.message = message;
        // 当前时间加上延时时间,设置消息的触发时间
        this.triggerTime = System.currentTimeMillis() + delayTime;
    }
    // 获取剩余的延时时间
    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(triggerTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }
    // 比较方法,用于确定消息的顺序
    @Override
    public int compareTo(Delayed other) {
        if (this.triggerTime < ((DelayedMessage) other).triggerTime) {
            return -1;
        } else if (this.triggerTime > ((DelayedMessage) other).triggerTime) {
            return 1;
        }
        return 0;
    }
    public MqCausa.Message getMessage() {
        return message;
    }
}

最终实现如图所示:

ef7fb26dfda9ed73f3d05e7d38762e1e.jpeg

实现功能:

  • 对于任务操作请求的异步发送

  • 轮询策略实现消费的负载均衡

其他

附上个人总结的对于worker和server之间服务发现以及调度的流程图

服务发现

95d51a3856498ccd4787fdcd11d8e839.jpeg

调度

7cf4b2677cdb571776fdd3b2fa719aa6.jpeg

项目地址

https://github.com/karatttt/k-job


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,“长按”或“扫描”下方二维码噢:

53a6c2c224fd0176d5597e96adc046c8.png

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

b27ab9cf456d69ce4492870f53e3c0bb.png

a50cc295337e5ea78d35fe19deace794.png8e42111c519a7e73d367125c5fbf9097.pnge19cb67935242a561fd3f03948bc1140.png3c634438c7d568f543d5510fb4cb4de3.png

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
分布式定时任务框架+负载均衡+OpenAPI异步调用 主流框架往往为了适配更多的场景,支持足够多的功能,往往体积大,且不易动态扩展,为了对项目有最大的控制,在解决以上业务场景的前提下,进行部分功能的修剪,也希望能更好的从中学习主流框架的设计思想,于是决定重写一个定时任务框架。对于producer,前面提到,为了应对大量定时任务的场景,对于任务的操作,应全部是异步的,我们引入超时机制即可,当超过一定的时间未收到ack,或者返回错误响应,选择下一个server发起重试。),意味着只有被分配到线程(消费者)消费时,才能被ack,而活跃的线程数并不多。 阅读详情

相关推荐

(R,线性回归)R语言里的模型诊断图(Residuals vs Fitted,Normal QQ , Scale-Location ,Residuals Leverage)

线性回归,是概率统计学里最重要的统计方法,也是机器学习中一类非常重要的算法。线性模型简单理解非常容易,但是内涵是非常深奥的。尤其是线性回归模型中的Diagnostics plot的阅读与理解一直被认为是线性回归中的一个难点。 在任何线性模型中,能够直接“lm”(模型有意义),既要考虑各个参数的t-test所得出的p-value,也要考虑总体模型F-检验得出的p-value。在这之后,还要清楚一个...

qq_35837578的博客 7万+

分布式定时任务调度框架

分布式定时任务框架的对比

代码让AI扣 9600

【React Native】源码分析之Native UI的封装和管理

转载请注明出处:http://blog.youkuaiyun.com/u013531824/article/details/54020287,谢谢。  ReactNative作为使用React开发Native应用的新框架,随着时间的增加,无论是社区还是个人对她的兴趣与日递增。此文目的是希望和大家一起欣赏一下ReactNative的部分源码。阅读源码好处多多,让攻城狮更溜的开发ReactNative应用的同时,也

Tiny的专栏 9779

分布式定时任务Quartz框架介绍

之前在项目中用定时任务都是直接用的Spring的@Scheduled注解,因为遇到的业务都比较简单,比如定时更新榜单,支付功能中的定时查单,最近在写一个课堂助手的项目,要实现定时任务的业务对任务有增删改查的需求,@Scheduled已经无法满足了,so,我选择了QuartzQuartz是OpenSymphony开源的一个项目,是一个由Java编写的开源作业调度框架。

GJ_863的博客 2014

USRP N210与MATLAB连接实战:从驱动安装到信号接收

本文详细介绍了USRP N210与MATLAB连接的完整流程,涵盖驱动安装、网络配置、支持包安装及信号接收实战。重点解决了安装过程中的常见错误和硬件连接问题,并通过MATLAB代码示例展示了如何配置接收器、处理信号数据,帮助用户快速实现从设备对接到信号分析的全过程。

blue的专栏 821

狂神说docker(最全笔记)

一.Docker入门 1. Docker 为什么会出现 2. Docker的历史 3.Docker最新超详细版教程通俗易懂 Docker是基于Go语言开发的!开源项目 官网 官方文档Docker文档是超详细的 仓库地址 4. 虚拟化技术和容器化技术对比 4.1. 虚拟化技术的缺点 资源占用十分多 冗余步骤多 启动很慢 2.2. 容器化技术 比较Docker和虚拟化技术的不同 传统虚拟机, 虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软.

qq_21197507的博客 5万+

分布式定时任务调度框架Quartz

一、Quartz引言 Quartz是一个定时任务调度框架,比如你遇到这样的问题: 比如淘宝的待支付功能,后台会在你生成订单后24小时后,查看订单是否支付,未支付则取消订单 比如vip的每月自动续费功能 … 想定时在某个时间,去做某件事 Quartz是一套轻量级的任务调度框架,只需要定义了 Job(任务),Trigger(触发器)和 Scheduler(调度器),即可实现一个定时调度能力。支持基于数据库的集群模式,可以做到任务幂等执行。 二、Quartz使用 2.1 导入依赖 <!-

哈哈 2万+

【Android Performance】Android CPU绑核实战:从taskset到cpuset的完整调优指南

本文系统讲解Android系统中的CPU绑核(CPU Affinity)技术,涵盖用户空间的taskset命令行绑核、内核cpuset分组机制的原理与操作、进程级与线程级绑核的代码实现、以及中断绑核的底层方法。文中深入拆解CPU亲和性掩码的计算规则、各cpuset分组的默认策略差异、绑核后的验证手段及常见踩坑场景,并配有多项实操命令与C代码示例。适合从事Android系统性能调优、进程调度优化的开发者阅读。

weixin_44081096的博客 1312

springcloud:新一代分布式定时任务框架——PowerJob

PowerJob是基于java开发的企业级的分布式任务调度平台,与xxl-job一样,基于web页面实现任务调度配置与记录,使用简单,上手快速,因此迅速得到用户的欢迎。相对于其他定时任务框架具有无锁化设计,更强悍的性能支撑,我们通过官网的产品对比可以了解详情。定时任务类型与传统的定时任务框架对比,powerJob支持更多的定时任务类型:API: 通过客户端提供的api接口触发,服务端不会主动调度,适用于与业务服务上下连接或只调度一次的业务场景。

55555的博客 1万+

C#winform自定义绘制曲线控件实例

本文实例讲解自定义绘制曲线控件过程。 在实际项目中,需要绘制曲线,系统的提供的绘制曲线的控件有时不能满足自己的需要,需要根据项目需要定制开发曲线控件。 实例目标,实时绘制显示温湿度值曲线。

qq_30725967的博客 1735

python代码实现了一个基于图注意力网络(GAT)和长短期记忆网络(LSTM)的股票成交量预测模型

自定义数据集类:定义了类,继承自。该类用于生成股票数据的时间序列样本,每个样本包含一个长度为seq_length的时间序列和对应的目标成交量。数据加载器:使用DataLoader对数据集进行批量加载,设置批量大小为 64,并开启数据打乱功能。GAT - LSTM 模型:定义了GAT_LSTM类,继承自。该模型结合了 GAT 和 LSTM 两种神经网络:GAT 部分:使用GATConv处理全局图特征,捕获股票之间的相互关系。LSTM 部分:使用nn.LSTM处理时间序列数据,捕捉时间序列的动态变化。

huanghm88的专栏 426

分布式定时任务框架原理

分布式定时任务框架原理 1. 定时任务 定时任务非常常见,如定时清理状态、定时生成订单、定时处理日志.....,总之定时任务使用得非常之广泛,定时任务的框架也比较多,如crontab,quartz,spring-batch,elastic-job,dts,tbschedule等,框架还是比较多。今天重点介绍quartz...

高福来 776

筑牢上线前安全防线:安全运维服务中的检测实践与深化

在日益严峻的网络安全形势下,将漏洞扫描、渗透测试和基线核查有机结合的上线前安全检测,是保障信息系统安全、稳定、合规上线的基石。通过专业、严谨、协作的检测实践,乙方安全团队能够有效协助甲方在系统生命周期的起点就构筑起坚固的安全防线,为业务的顺利开展和用户的信任保驾护航,真正实现“安全赋能业务”的价值。这道“守门人”的职责,是数字时代企业稳健前行的不可或缺的保障。专业的安全服务提供商(乙方)需要与甲方(系统所有者/运营方)建立紧密、透明、协作的伙伴关系,实现风险的闭环管理,甚至推动甲方安全能力的长期提升。

huluang的专栏 184

自己写一个分布式定时任务框架+负载均衡+OpenAPI异步调用

定时任务框架+负载均衡+消息队列,谁说定时任务调度无法高并发?

m0_75081815的博客 1328

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

分布式定时任务框架的自研实践:锁、负载均衡与OpenAPI异步回调

在分布式系统中,定时任务要同时解决触发、路由与结果传递三大问题。其核心原理是通过注册中心维护任务与节点状态,由调度器基于Redis有序集合产生触发事件,再用分布式锁校验执行权,避免重复调度;负载均衡策略决定任务落到哪个节点,保证长任务不拖垮单机。这些机制共同支撑高可用的异步任务处理。OpenAPI异步调用则为外部系统提供标准HTTP回调与状态查询能力,解决跨技术栈的结果通知难题。在实际业务中,无论是批处理、报表生成还是订单同步,只要存在重复执行、任务丢失或回调乱序等痛点,都可以参考这套设计,理解分布式定时任

weixin_32596893的博客 328

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

从零实现分布式定时任务框架:调度、负载均衡与异步实践

在分布式系统设计中,定时任务调度是保障业务自动化的关键基础设施。当任务规模扩大,单机调度无法满足高可用与扩展性,就需要引入调度中心、执行节点与可靠存储协同工作。一个成熟的分布式定时任务框架,核心在于任务状态机管理、触发机制(如数据库轮询与时间轮)、以及任务分发策略。常见负载均衡算法如加权轮询、一致性哈希和最少活跃调用,能有效提升执行节点的资源利用率。同时,异步化设计配合回调接口,可避免线程阻塞,提高吞吐量。此类技术广泛应用于报表生成、数据同步、缓存预热等场景。从工程实践角度出发,完整复盘了基于 Redis

weixin_32075843的博客 151

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

自研分布式定时任务框架:从时间轮到OpenAPI异步调用的实践

在分布式系统架构中,任务调度是保障数据同步、批处理等场景稳定运行的关键环节。传统单机定时任务难以应对多节点并发、长耗时任务与故障转移的挑战,而Quartz等成熟框架在扩展性与灵活性上存在局限。本文以工程实践视角,剖析如何自研一套轻量级分布式定时任务框架,涵盖时间轮触发、负载均衡策略、节点心跳感知、OpenAPI异步调用等核心模块,探讨任务幂等与状态追踪的实现要点。结合真实踩坑案例,给出任务重复执行、队列堆积、回调丢失等高频问题的排查方法,为需要多节点任务分发与外部系统接入的团队提供可落地的参考方案。

weixin_33585822的博客 279

自研分布式定时任务框架:负载均衡与OpenAPI异步调度实现

分布式任务调度是构建高可靠业务系统的核心基础设施之一,但传统单机定时任务在集群环境下暴露出重复执行、单点故障和资源分配不均等问题。分布式锁作为保障多节点互斥写入的关键机制,配合等开销负载均衡策略,能够将任务合理分发至不同执行节点,从而提升整体吞吐与稳定性。异步接口设计则帮助企业级系统在开放API场景下实现快速响应,避免因任务处理时间过长而阻塞连接。当现成的开源调度框架难以满足动态创建任务、异步语义、自定义分发策略等特定业务需求时,从零实现一套轻量级分布式定时任务框架就成为可行的工程方案。本文从架构设计、Re

weixin_30431445的博客 310

自研分布式定时任务框架:调度、负载均衡与OpenAPI异步调用实战

在分布式系统架构中,任务调度是保障业务自动化运转的核心能力。传统单机定时任务面临单点故障、重复执行、长耗时阻塞等挑战,而成熟开源框架往往偏重、定制成本高。本文从调度模型出发,讲解时间轮触发机制、调度器与执行器分离架构、一致性协调及任务分片等底层原理,并探讨负载均衡在任务分发中的真实落地,如动态权重、一致性哈希与故障转移策略。同时,针对外部系统的高耗时调用场景,介绍基于OpenAPI的异步任务提交、状态查询与回调通知的设计思路,以及AK/SK签名、限流等安全实践。文章结合生产环境和百万级调度经验,剖析时钟跳跃

weixin_32466193的博客 231

并行分布式框架:Celery、rq、funboost

Celery是一个异步任务的调度工具,也可以叫做 "分布式任务队列(Distributed Task Queue)"。

freeking101的博客 5万+

自研分布式任务调度框架:任务调度、负载均衡与异步接入全解析

分布式任务调度是微服务架构下的核心基础设施,关系到定时任务在复杂环境中的稳定执行。多节点部署时,单一任务可能被重复触发,数据一致性面临挑战。基于分布式锁与一致性哈希等机制,可构建可靠的负载均衡与幂等防线;结合时间轮实现高并发触发,并通过OpenAPI异步接口满足外部系统灵活接入。本文以一个自研框架为例,完整拆解调度中心、Worker节点、负载均衡策略的设计思路,还剖析了分布式锁续期、Netty长连接通信等工程实践中常见的坑点,为需要自研或优化任务调度系统的团队提供参考。

weixin_33491377的博客 230
上一篇: 字节一面:kafka为什么这么快?
下一篇: 代码越“整洁”,性能越“拉胯”?
公众号-芋道源码
博客等级 码龄10年 1634粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值