0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

xxl-job惊艳的设计,怎能叫人不爱

jf_ro2CN3Fa 来源:c1n.cn/N8Mln 2022-12-22 14:43 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

  • 通信底层介绍
  • 通信整体流程
  • 惊艳的设计

通信底层介绍

xxl-job 使用 netty http 的方式进行通信,虽然也支持 Mina,jetty,netty tcp 等方式,但是代码里面固定写死的是 netty http。

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

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

通信整体流程

我以调度器通知执行器执行任务为例,绘制的活动图:

cafb50e6-81b9-11ed-8abf-dac502259ad0.png活动图

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

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

惊艳的设计

看完了整个处理流程代码,设计上可以说独具匠心,将 netty,多线程的知识运用得行云流水。

我现在就将这些设计上出彩的点总结如下:

使用动态代理模式,隐藏通信细节

xxl-job 定义了两个接口 ExecutorBiz,AdminBiz,ExecutorBiz 接口中封装了向心跳,暂停,触发执行等操作,AdminBiz 封装了回调,注册,取消注册操作,接口的实现类中,并没有通信相关的处理。

XxlRpcReferenceBean 类的 getObject() 方法会生成一个代理类,这个代理类会进行远程通信。

全异步处理

执行器收到消息进行反序列化,并没有同步执行任务代码,而是将任务信息存储在 LinkedBlockingQueue 中,异步线程从这个队列中获取任务信息,然后执行。

而任务的处理结果,也不是说处理完之后,同步返回的,也是放到回调线程的阻塞队列中,异步的将处理结果返回回去。

这样处理的好处就是减少了 netty 工作线程的处理时间,提升了吞吐量。

对异步处理的包装

对异步处理进行了包装,代码看起来是同步调用的。

我们看下调度器,XxlJobTrigger 类触发任务执行的代码:

publicstaticReturnTrunExecutor(TriggerParamtriggerParam,Stringaddress){
ReturnTrunResult=null;
try{
ExecutorBizexecutorBiz=XxlJobScheduler.getExecutorBiz(address);
//这里面做了很多异步处理,最终同步得到处理结果
runResult=executorBiz.run(triggerParam);
}catch(Exceptione){
logger.error(">>>>>>>>>>>xxl-jobtriggererror,pleasecheckiftheexecutor[{}]isrunning.",address,e);
runResult=newReturnT(ReturnT.FAIL_CODE,ThrowableUtil.toString(e));
}

StringBufferrunResultSB=newStringBuffer(I18nUtil.getString("jobconf_trigger_run")+":");
runResultSB.append("
address:"
).append(address); runResultSB.append("
code:"
).append(runResult.getCode()); runResultSB.append("
msg:"
).append(runResult.getMsg()); runResult.setMsg(runResultSB.toString()); returnrunResult; }

ExecutorBiz.run 方法我们说过了,是走的动态代理,和执行器进行通信,执行器执行结果也是异步处理完,才返回的,而这里看到的 run 方法是同步等待处理结果返回。

我们看下xxl-job是如何同步获取处理结果的:调度器向执行器发出消息后,该线程阻塞。等到执行器处理完毕后,将处理结果返回,唤醒被阻塞的线程,调用处拿到返回值。

动态代理代码如下:

//代理类中的触发调用
if(CallType.SYNC==callType){
//future-responseset
XxlRpcFutureResponsefutureResponse=newXxlRpcFutureResponse(invokerFactory,xxlRpcRequest,null);
try{
//doinvoke
client.asyncSend(finalAddress,xxlRpcRequest);

//futureget
XxlRpcResponsexxlRpcResponse=futureResponse.get(timeout,TimeUnit.MILLISECONDS);
if(xxlRpcResponse.getErrorMsg()!=null){
thrownewXxlRpcException(xxlRpcResponse.getErrorMsg());
}
returnxxlRpcResponse.getResult();
}catch(Exceptione){
logger.info(">>>>>>>>>>>xxl-rpc,invokeerror,address:{},XxlRpcRequest{}",finalAddress,xxlRpcRequest);

throw(einstanceofXxlRpcException)?e:newXxlRpcException(e);
}finally{
//future-responseremove
futureResponse.removeInvokerFuture();
}
}

XxlRpcFutureResponse 类中实现了线程的等待,和线程唤醒的处理:

//返回结果,唤醒线程
publicvoidsetResponse(XxlRpcResponseresponse){
this.response=response;
synchronized(lock){
done=true;
lock.notifyAll();
}
}

@Override
publicXxlRpcResponseget(longtimeout,TimeUnitunit)throwsInterruptedException,ExecutionException,TimeoutException{
if(!done){
synchronized(lock){
try{
if(timeout< 0){
//线程阻塞
lock.wait();
}else{
longtimeoutMillis=(TimeUnit.MILLISECONDS==unit)?timeout:TimeUnit.MILLISECONDS.convert(timeout,unit);
lock.wait(timeoutMillis);
}
}catch(InterruptedExceptione){
throwe;
}
}
}

if(!done){
thrownewXxlRpcException("xxl-rpc,requesttimeoutat:"+System.currentTimeMillis()+",request:"+request.toString());
}
returnresponse;
}

有的同学可能会问了,调度器接收到返回结果,怎么确定唤醒哪个线程呢?

每一次远程调用,都会生成 uuid 的请求 id,这个 id 是在整个调用过程中一直传递的,就像一把钥匙,在你回家的的时候,拿着它就带开门。

这里拿着请求 id 这把钥匙,就能找到对应的 XxlRpcFutureResponse,然后调用 setResponse 方法,设置返回值,唤醒线程。

publicvoidnotifyInvokerFuture(StringrequestId,finalXxlRpcResponsexxlRpcResponse){

//通过requestId找到XxlRpcFutureResponse,
finalXxlRpcFutureResponsefutureResponse=futureResponsePool.get(requestId);
if(futureResponse==null){
return;
}
if(futureResponse.getInvokeCallback()!=null){

//callbacktype
try{
executeResponseCallback(newRunnable(){
@Override
publicvoidrun(){
if(xxlRpcResponse.getErrorMsg()!=null){
futureResponse.getInvokeCallback().onFailure(newXxlRpcException(xxlRpcResponse.getErrorMsg()));
}else{
futureResponse.getInvokeCallback().onSuccess(xxlRpcResponse.getResult());
}
}
});
}catch(Exceptione){
logger.error(e.getMessage(),e);
}
}else{
//里面调用lock的notify方法
futureResponse.setResponse(xxlRpcResponse);
}

//doremove
futureResponsePool.remove(requestId);

}


审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 通信
    +关注

    关注

    18

    文章

    6318

    浏览量

    139570
  • 代码
    +关注

    关注

    30

    文章

    4941

    浏览量

    73151

原文标题:xxl-job惊艳的设计,怎能叫人不爱

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    100V耐压80V60V48V降压12V5V3.3V/3A大电流车载音响驱动H6216L

    :≥3.3V。 电压精度:±3.5%。 结合惠海半导体同系列芯片 H6215L 以及电子发烧友网对 H62XXL 系列芯片的介绍可知,H6216L 可能还具有以下特性: 输入电压范围:属于 H62XXL
    发表于 07-23 11:36

    docker无法启用怎么解决?

    mengxing@mengxing-virtual-machine:/etc/docker$ sudo systemctl restart docker Job for docker.service failed because
    发表于 06-23 07:17

    长电科技荣膺2025年度大学生喜爱的雇主品牌

    近日,长电科技凭借在应届生招聘、培养与发展方面的卓越实践和持续投入,从众多优秀企业中脱颖而出,入选由中国领先的人力资源服务商前程无忧(51job.com)公布的“2025年度大学生喜爱的雇主品牌”榜单。
    的头像 发表于 06-20 16:23 816次阅读

    紫光闪存UNIS PN C2 PSSD怎么样

    大好春光,怎能宅家辜负?当你奔赴花海,手机咔咔不停,是不是常被数据存储难题搞得心烦意乱?别愁啦,紫光闪存 UNIS PN C2 PSSD 来救场咯!
    的头像 发表于 04-15 16:44 764次阅读

    Home Assistant Yellow:我怎能拒绝和树莓派CM5共舞?

    两年前,我们推出了HomeAssistantYellow,其设计理念是随着用户需求的增长而不断扩展其功能。如果需要更多存储空间,可以添加NVMe驱动器;如果需要基于Thread的Matter协议而非Zigbee,可以更改固件。
    的头像 发表于 03-25 09:34 771次阅读
    Home Assistant Yellow:我<b class='flag-5'>怎能</b>拒绝和树莓派CM5共舞?

    IMX6ULL如何通过USB将CANON LBP6030w激光打印机连接到其中?

    /2025:04:36:10 +0000] [Job 28] cfFilterGhostscript: Unable to open raster stream - : Broken pipe E
    发表于 03-20 07:24

    使用OpenVINO GenAI和LoRA适配器进行图像生成

    借助生成式 AI 模型(如 Stable Diffusion 和 FLUX.1),用户可以将平平无奇的文本提示词转换为令人惊艳的视觉效果。
    的头像 发表于 03-12 13:49 1543次阅读
    使用OpenVINO GenAI和LoRA适配器进行图像生成

    使用nonai_2d的CRC功能进行图像类型转换,nonai_2d模块的要如何使用?

    , __func__, __LINE__); return K_SUCCESS;}期待结果和实际结果 一直在提示 <3>[24] [Func]:config_job [Line
    发表于 03-11 06:44

    ?性能猛兽降临!RK3588 Mini PC 惊艳亮相

    还在为找不到一款性能炸裂又功耗友好的迷你主机而发愁吗?今天,必须给大家重磅揭秘这款 RK3588 Mini PC,绝对能打破你对迷你主机的固有印象! ?它搭载 Rockchip 新一代旗舰 AIoT SoC,运用先进的 8nm 光刻工艺精心雕琢而成。这意味着什么?直白来讲,它在性能上一骑绝尘,耗电表现更是优秀到极致,轻松拿捏性能与功耗的黄金平衡点。 ?RK3588 芯片组采用 big.LITTLE 架构的 CPU,宛如一支训练有素的精锐之师。其中,四个高性能 Cortex - A76 内核,如同勇猛无畏的先锋大将,面对复杂任务时冲锋陷阵,快速攻克难题;四个节能的 Cortex - A55 内核,则像精打细算的后勤管家,在日常轻负载场景下默默维持系统平稳运转,大幅降低能耗。二者紧密协作,让设备性能时刻满格,电量消耗却稳如泰山。 ?这款芯片堪称高端移动处理器中的潜力之星,实力强劲,未来可期。它性能卓越,无论是多任务并行处理、运行大型专业软件,还是流畅播放高清视频,都游刃有余;先进的视频处理技术,让画面每一帧都细腻入微、色彩绚烂夺目;多功能 AI 加速器更是为各类智能应用注入强大动力,无论是智能语音识别,还是图像精准识别,都能迅速响应。再加上其高效省电能力,彻底告别电量焦虑,让你尽情享受智能、流畅且超长续航的便捷生活。 入手这样一台 RK3588 Mini PC,就相当于把一个功能完备的小型工作站搬回了家。无论是日常办公、休闲娱乐,还是投身创意设计,它都能化身你最得力的助手。 快来一起领略它的独特魅力吧! #minipc #CPU #主机 #我的日常 #迷你主机 #128G #高颜值 #瑞芯微嵌入式主板 #瑞芯微嵌入式开发板 #瑞芯微嵌入式核心板
    发表于 02-15 11:51

    Flexus X 初体验之部署 xxl-job - 分布式任务调度平台

    前言                 第二次参加华为和 CSDN 的测评活动了,这一次测试的呢是华为云 Flexus 系列的云服务 X 实例,这个 Flexus X 产品和我们经常用的 ECS 弹性服务器来说呢是有一些区别的,ECS 一般指的是弹性云服务器, 而 Flexus 应用服务器 L 实例可视为轻量级应用服务器,主要是满足一些我们简单的 WEB 部署这些,适配一些简单的小型的应用或者场景. Flexus 云服务器 X 实例则位于 L 实例和 ECS 之间(也可以当作 ECS,毕竟控制台显示的就是 ECS)。X 实例通过提供更
    的头像 发表于 01-23 17:29 636次阅读
    Flexus X 初体验之部署 <b class='flag-5'>xxl-job</b> - 分布式任务调度平台

    N32A455xxL8系列产品简介

    电子发烧友网站提供《N32A455xxL8系列产品简介.pdf》资料免费下载
    发表于 01-22 16:37 0次下载
    N32A455<b class='flag-5'>xxL</b>8系列产品简介

    N32A455xxL7系列产品简介

    电子发烧友网站提供《N32A455xxL7系列产品简介.pdf》资料免费下载
    发表于 01-22 15:37 0次下载
    N32A455<b class='flag-5'>xxL</b>7系列产品简介

    宇树科技CES 2025大放异彩,多款创新产品惊艳亮相

    近日,在万众瞩目的CES 2025展会上,宇树科技携其最新研发的一系列产品惊艳亮相美国拉斯维加斯,为全球观众带来了一场科技盛宴。 此次参展,宇树科技带来了多款备受瞩目的机器人产品。其中,消费级四足
    的头像 发表于 01-09 11:32 2507次阅读

    在 Flexus X 上部署 ELK 日志系统

    Flexus X 上部署 Mysql 和一套 xxl-job 分布式任务管理系统,完成了 Flexus X 的首次操作,本次我
    的头像 发表于 01-02 11:59 527次阅读
    在 Flexus X 上部署 ELK 日志系统

    基于Flexus X加速MySQL镜像搭建XXL-JOB任务调度平台

    随着云计算技术的飞速发展,Flexus 云服务器 X 凭借其高性能和高可用性,成为了众多企业和开发者的首选。本文旨在通过搭建基于 Flexus X 加速 MySQL 镜像的 XXL-JOB 任务调度
    的头像 发表于 12-29 15:45 709次阅读
    基于Flexus X加速MySQL镜像搭建<b class='flag-5'>XXL-JOB</b>任务调度平台