XxlJob深度性能优化实践

一、背景

天画项目的数据工厂目前在与xxl-job对接自动化数据生成任务,另外我司也在使用该组件做业务,所以想深入了解下XxlJob。在跟进了社区的github等仓库issue发现开发迭代停滞了一段时间,思来想去准备开个下游分支做一些性能优化和特性开发等,于是fork了下源码,将其作为天画社区关于任务调度的组件来使用。
我花了几天阅读源码,同时做了一些简单的调试,发现了一些问题之后着手进行优化,本文将从XxlJob的原理出发深入其性能瓶颈,并提出一些解决方案。相关优化的代码已经上传至gitee.

二、调度流程解读

在进行性能和安全改造之前,需要对xxljob的调度执行原理要非常了解,所以这里我们先简单看一下xxljob的调度流程和线程模型。

2.1 调度流程

  1. 服务端启动流程

xxlJob服务端启动流程.png

  1. 客户端启动流程

客户端启动流程 (2).png

  1. 客户端与服务端交互流程

客户端与服务端交互流程 (1).png

2.2 调度线程模型

通过上面的流程图我们可以梳理出如下服务端和客户端用到的线程和线程池,具体作用通过名称即可了解。
服务端:

  1. 触发器线程池(fastTriggerPool,slowTriggerPool)
  2. 注册&停止注册线程池(registryOrRemoveThreadPool)
  3. 注册监听线程(registryMonitorThread)
  4. 任务失败监听线程(monitorThread)
  5. 任务完成回调线程池(callbackThreadPool)
  6. 任务完成回调监听线程(monitorThread)
  7. 统计日志线程(logrThread)
  8. 调度线程(scheduleThread)
  9. 时间轮线程(ringThread)

客户端:

  1. http 交互监听线程(thread)
  2. 注册器线程(registryThread)
  3. 任务线程(JobThread)
  4. 任务回调日志线程(triggerCallbackThread)
  5. 回调日志重试线程(triggerRetryCallbackThread)

2.3 客户端API

这里需要说明的是,在一定程度上客户端(也就是执行器,以下统称为客户端)也会作为服务端接受调度中心(即xxl job server 服务端)的回调,所以这里是一个比较令人迷惑的地方。
这里列出服务端调用客户端的API
127.0.0.1:9999/beat
127.0.0.1:9999/idleBeat
127.0.0.1:9999/run
127.0.0.1:9999/kill
127.0.0.1:9999/log

2.4 服务端API

这里列出客户端调用服务端的API
127.0.0.1:8080/api/callback
127.0.0.1:8080/api/registry
127.0.0.1:8080/api/registryRemove

三、潜在问题

在反复看了xxljob 开源社区gitee/github上的issue之后,我对下面的几个问题比较关注,所以在业余时间中专门调试并且进行了一定的复现,这里简单回顾一下xxljob在高并发调度过程中可能产生的问题。

3.1 重复调度

重复调度的问题其实是偶发问题,问题的现象或者特征就是一个任务在一次调度中重复执行了两次,同时产生了 两条xxljob log,发生时间相同。

3.2 安全问题

xxljob控制台查询客户端日志的时候会返回accessToken,github上的issue讨论已经提供了复现步骤,这里目前作者已经提供升级,但是本文的重点不止于此,因为另外的安全问题就是accessToken在客户端与服务端之间的交互是明文传输的,另外也是服务端与所有客户端共用的,一旦泄露其实会比较危险。

3.3 并发调度变慢

XxlJob的调度在并发变高的时候从日志上可以看出调度会有一些延迟,出现这个问题的原因有以下几个方面:

  1. 一秒内调度量比较多,对客户端和服务端在一秒内会产生上千次调度
  2. 调度粒度是线程(JobThread)和单次粒度的,所以一秒内要处理2-3倍的数据库IO和网络IO
  3. 选用了busyover或者failover的调度策略,这两种需要在调度之前给对应的客户端发送心跳
  4. 日志处理,这里包括客户端的日志处理和服务端的日志处理,在并发比较高的情况下日志产生的量也比较大,

对调度业务会产生一定的资源占用。

3.4 线程模型的性能瓶颈

这个问题其实与3.3类似,从上面的调度流程图可以看到xxljob其实是对每个xxl_job_info在对应的客户端上构建一个JobThread,如果执行器对应的任务比较多且存在一秒内并发触发的话就可能导致客户端本身出现性能问题。

3.5 回调并发变慢

这个问题也是高并发调度下产生的问题,xxljob在日志处理上有两种方式:一种是在调度job方法内通过XxlJobHelper.log去记录产生的业务日志,这部分是存在于客户端的,另外一种则是调度日志,即对该job在当前调度结果的日志信息推送到服务端做记录或者统计,这部分数据存储在服务端的xxl_job_log表中。
在高并发调度的情况下,客户端的处理存在性能问题,一次回调推送的日志太少,客户端存在积压。

3.6 分页性能问题

在高并发或者大量任务的场景中xxlJob的管理控制台在任务管理和调度日志分页上存在性能问题,可能导致页面加载缓慢同时服务端进程崩溃,进而影响服务运行。

四、优化点

4.1 认证优化

在xxl job的源码中需要借助xxl.job.accessToken来完成客户端与服务端的认证,这个配置在客户端注册到服务端,以及客户端和服务端在相互调用过程中都会进行认证。由于配置是统一的,所以所有客户端都需要配置这个,另外认证过程中是accessToken是明文传输的,所以这种认证机制一定程度上是比较弱的。另外如果改动认证机制的话则客户端和服务端都要改,本次优化则花一定的精力来提升安全性。总结起来就是如下几点:

  1. 强制安全认证

客户端或者服务端不配置accessToken则启动失败

  1. 认证加密

客户端与服务端之间的交互均通过加密accessToken的方式

  1. 弱化accessToken在认证过程中的影响

对于每个客户端虽然都配置同样的accessToken,但是新生成的accessToken(原accessToken+appName)则是通过AES进行加密。
这里我们看一下进行强认证过程的时序图:

xxljob强认证方式 (1).png
下面我们看一下具体实现源码:
客户端:

 private String  initEmbedServer(String address, String ip, int port, String appname, String accessToken) throws Exception {// fill ip portport = port>0?port: NetUtil.findAvailablePort(9999);ip = (ip!=null&&ip.trim().length()>0)?ip: IpUtil.getIp();// generate address// registry-address:default use address to registry , otherwise use ip:port if address is nullif (address==null || address.trim().length()==0) {String ip_port_address = IpUtil.getIpPort(ip, port);address = "http://{ip_port}/".replace("{ip_port}", ip_port_address);}// accessTokenif (accessToken == null || accessToken.trim().length()==0) {throw new IllegalArgumentException("xxl-job accessToken need not  null. ");//logger.warn(">>>>>>>>>>> xxl-job accessToken is empty. To ensure system security, please set the accessToken.");}// startembedServer = new EmbedServer();//accessToken加密String accessCookie &#

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/456147.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

亚马逊社媒营销指南:提升品牌曝光与销售额的5大关键策略

随着互联网的快速发展,社交媒体营销已成为品牌推广和销售增长的重要手段。对于亚马逊卖家来说,利用社交媒体平台进行营销不仅可以提高品牌知名度,还能有效提升销售额。本文Nox聚星将和大家探讨亚马逊卖家如何巧妙运用社交媒体策略&#xff0c…

行业应用科普 | 患者护理应用连接器

【摘要/前言】 通过医疗专业人士为患者提供护理的种种需求,已经不限于手术室与医院的各种安全状况。当今许多患者的护理都是在其他环境进行,例如医生办公室、健康中心,还有越来越普遍的住家。尤其是需要长期看护的患者,所需的科技…

第3节、电机定速转动【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】,查看本系列全部文章 摘要:本节介绍用定时器定时的方式,精准控制脉冲时间,从而控制步进电机速度。 一、计算过程 电机每一步的角速度等于走这一步所花费的时间,走一步角度等于步距角&#xff…

python介绍,安装Cpython解释器,IDE工具pycharm的使用

python介绍 官方的Python解释器本质是基于C语言开发的一个软件,该软件的功能就是读取以py.结尾的文件内容,然后按照Guido定义好的语法和规则去翻译并执行相应的代码。这种C实现的解释器被称为Cpython。 python解释器的种类:Jython IPyth…

BUGKU-WEB Simple_SSTI_2

03 Simple_SSTI_2 题目描述 解题思路 进入场景后,显示: You need pass in a parameter named flag翻译即为:你需要传入一个名为flag的参数 查看源码,没有发现什么特别的: 结合第一题Simple_SSTI_1,对其…

MQ,RabbitMQ,SpringAMQP的原理与实操

MQ 同步通信 异步通信 事件驱动优势: 服务解耦 性能提升,吞吐量提高 服务没有强依赖,不担心级联失败问题 流量消峰 ​ 小结: 大多情况对时效性要求较高,所有大多数时间用同步。而如果不需要对方的结果,且吞吐…

【知识整理】一文理解系统服务高可用

一、如何理解高可用 1、什么是高可用 高可用性(英语: High Availability,缩写为 HA),指系统无中断地执行其功能的能力,代表系统的可用性程度,是进行系统设计时的准则之一。 2、决定可用性的两…

选择冒泡排序

有一浮点型数组A,用C语言写一函数实现对浮点数组A进行降序排序,并输出结果要求要以数组A作为函数的入口&#xff0c;请用冒泡和选择各写一遍 #include <stdio.h> void maopao() {int arr[5] {10,11,15,13,20};int i0,j0,temp;int len sizeof(arr)/sizeof(arr[0]);for(…

大白话介绍循环神经网络

循环神经网络实质为递归式的网络&#xff0c;它在处理时序任务表现出优良的效果&#xff0c;毕竟递归本来就是一步套一步的向下进行&#xff0c;而自然语言处理任务中涉及的文本天然满足这种时序性&#xff0c;比如我们写字就是从左到右一步步来的鸭&#xff0c;刚接触深度学习…

Windows显示空的可移动磁盘的解决方案

123  大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式…

字体图标的使用

icanfont 阿里图标库 在帮助中找到代码应用&#xff0c;我这里使用 font-class 引用 使用步骤如下&#xff1a; 第一步&#xff1a;拷贝项目下面生成的fontclass代码&#xff1a; 比如&#xff1a;at.alicdn.com/t/font_8d5l8fzk5b87iudi.css 这段代码来源&#xff1a; 首先…

忘掉Access吧,全新0代码表格编程工具登场,中国造

灵活好用&#xff0c;广为流传 曾几何时&#xff0c;Access作为微软推出的关系数据库管理系统&#xff0c;风光无限。它不仅是Office家族的一员&#xff0c;更以其易上手、开发周期短的特点&#xff0c;成为非IT专业办公人员的得力助手。一句“Excel使用高手&#xff0c;比不上…