告别硬编码!XXL-JOB动态任务调度全攻略:从痛点到落地实践
引言:动态调度的时代呼唤
在当今快速变化的业务环境中,传统静态任务调度方式面临着严峻挑战。企业级应用普遍存在以下痛点:
- 发布周期长:新增或修改任务需重启应用,导致业务中断
- 资源利用率低:固定配置难以应对流量波动,造成资源浪费
- 运维成本高:任务变更需开发介入,响应速度慢
- 扩展性受限:无法根据业务需求实时调整任务执行策略
XXL-JOB作为一款分布式任务调度平台(Distributed Task Scheduling Platform),其动态任务调度能力为解决这些问题提供了完美方案。本文将深入剖析XXL-JOB的动态调度机制,通过实战案例展示如何在生产环境中实现任务的动态注册、调整与管理,帮助开发者构建弹性、高效的任务调度系统。
一、XXL-JOB动态调度核心原理
1.1 架构设计概览
XXL-JOB采用经典的"调度中心-执行器"架构,实现了任务调度与执行的解耦:
flowchart LR
subgraph 调度中心(Admin)
A[任务管理]
B[调度策略]
C[执行日志]
D[动态配置]
end
subgraph 执行器(Executor)
E[任务注册]
F[任务执行]
G[日志收集]
end
A -->|触发调度| B
B -->|发送指令| E
E --> F
F -->|反馈结果| C
D -->|动态调整| B
F -->|输出日志| G
G --> C
1.2 动态调度关键组件
核心类XxlJobExecutor提供了任务动态管理的基础能力:
| 方法 | 功能描述 | 动态调度价值 |
|---|---|---|
registJobHandler |
注册任务处理器 | 支持运行时添加新任务类型 |
loadJobHandler |
加载任务处理器 | 实现任务与执行逻辑的动态绑定 |
registJobThread |
注册任务线程 | 控制任务执行实例的生命周期 |
removeJobThread |
移除任务线程 | 支持任务的动态卸载 |
loadJobThread |
获取任务线程 | 实现对任务执行状态的动态监控 |
这些API构成了XXL-JOB动态调度的基石,允许开发者在不重启应用的情况下完成任务的全生命周期管理。
二、动态任务实现方案
2.1 基于注解的声明式开发
XXL-JOB提供@XxlJob注解实现任务的声明式注册,这是最简单的动态任务实现方式:
@Component
public class DynamicTaskExample {
/**
* 动态任务示例
* 注解value值对应调度中心配置的JobHandler名称
*/
@XxlJob("dynamicDemoJob")
public void dynamicDemoJob() throws Exception {
// 获取任务参数
String param = XxlJobHelper.getJobParam();
XxlJobHelper.log("动态任务执行,参数:{}", param);
// 业务逻辑处理
processBusiness(param);
// 任务结果处理(默认成功,可主动设置)
// XxlJobHelper.handleSuccess();
// XxlJobHelper.handleFail("执行失败原因");
}
private void processBusiness(String param) {
// 实际业务逻辑
}
}
工作原理:Spring容器初始化时,XxlJobSpringExecutor会扫描所有@XxlJob注解的方法,通过registJobHandler自动注册为任务处理器。
2.2 编程式任务注册
对于需要在运行时动态创建的任务,可使用编程式API实现任务注册:
@Service
public class DynamicJobService {
private static final Logger logger = LoggerFactory.getLogger(DynamicJobService.class);
/**
* 动态注册任务
* @param jobName 任务名称
* @param jobHandler 任务处理器
*/
public void registerJob(String jobName, IJobHandler jobHandler) {
// 注册任务处理器
XxlJobExecutor.registJobHandler(jobName, jobHandler);
logger.info("动态注册任务成功: {}", jobName);
}
/**
* 创建自定义任务处理器
* @param taskId 业务任务ID
* @return 任务处理器实例
*/
public IJobHandler createCustomJobHandler(Long taskId) {
return new IJobHandler() {
@Override
public void execute() throws Exception {
XxlJobHelper.log("动态任务[{}]执行开始", taskId);
// 此处调用实际业务逻辑
businessService.executeTask(taskId, XxlJobHelper.getJobParam());
XxlJobHelper.log("动态任务[{}]执行完成", taskId);
}
@Override
public void init() throws Exception {
// 任务初始化逻辑
logger.info("动态任务[{}]初始化", taskId);
}
@Override
public void destroy() throws Exception {
// 任务销毁逻辑
logger.info("动态任务[{}]销毁", taskId);
}
};
}
/**
* 动态移除任务
* @param jobId 任务ID
* @param reason 移除原因
*/
public void removeJob(int jobId, String reason) {
XxlJobExecutor.removeJobThread(jobId, reason);
logger.info("动态移除任务[{}]: {}", jobId, reason);
}
}
使用场景:用户自定义任务、临时任务、按需创建的一次性任务等需要在运行时动态生成的场景。
2.3 脚本任务动态执行
XXL-JOB支持通过脚本文件实现任务的动态执行,无需编译Java代码:
@XxlJob("dynamicScriptJob")
public void dynamicScriptJob() throws Exception {
String scriptContent = XxlJobHelper.getJobParam();
if (StringUtils.isEmpty(scriptContent)) {
XxlJobHelper.handleFail("脚本内容为空");
return;
}
// 将脚本内容写入临时文件
String scriptPath = FileUtil.writeToTempFile(scriptContent, "dynamic_job_", ".groovy");
// 执行脚本
int exitCode = ScriptUtil.execToFile(scriptPath, new File(XxlJobHelper.getJobLogFileName()));
if (exitCode == 0) {
XxlJobHelper.handleSuccess();
} else {
XxlJobHelper.handleFail("脚本执行失败,退出码:" + exitCode);
}
}
优势:脚本任务支持动态更新执行逻辑,特别适合需要频繁调整业务规则的场景,如营销活动规则、数据处理规则等。
三、任务动态配置与调整
3.1 任务参数动态传递
XXL-JOB支持在调度中心动态配置任务参数,实现任务执行逻辑的灵活调整:
@XxlJob("parametrizedJob")
public void parametrizedJob() throws Exception {
// 获取调度中心配置的参数
String jobParam = XxlJobHelper.getJobParam();
if (StringUtils.isEmpty(jobParam)) {
XxlJobHelper.log("未配置任务参数,使用默认配置");
jobParam = "{\"timeout\":3000,\"retryCount\":3}";
}
// 解析JSON参数
JobConfig config = GsonTool.fromJson(jobParam, JobConfig.class);
// 使用参数执行任务
businessService.processWithConfig(config);
XxlJobHelper.log("任务执行完成,参数: {}", jobParam);
}
// 参数配置类
static class JobConfig {
private int timeout; // 超时时间(ms)
private int retryCount; // 重试次数
private String strategy; // 处理策略
// getter和setter省略
}
最佳实践:参数应设计为JSON格式,便于扩展和解析;关键参数应设置默认值,提高系统健壮性。
3.2 任务调度策略动态调整
XXL-JOB调度中心提供了丰富的调度策略配置界面,支持动态调整:
pie
title 任务路由策略分布
"第一个" : 15
"最后一个" : 5
"轮询" : 30
"随机" : 20
"一致性哈希" : 15
"最不经常使用" : 5
"最近最久未使用" : 5
"故障转移" : 5
动态调整API:通过调度中心提供的REST API,可以在代码中动态修改任务调度策略:
/**
* 动态更新任务调度策略
* @param jobId 任务ID
* @param strategy 路由策略
*/
public void updateJobStrategy(int jobId, String strategy) {
// 调用调度中心API更新任务配置
String adminAddress = "http://xxl-job-admin:8080";
String accessToken = "default_token";
Map<String, Object> params = new HashMap<>();
params.put("id", jobId);
params.put("executorRouteStrategy", strategy);
HttpUtil.post(adminAddress + "/jobinfo/update",
params,
Header.create("XXL-JOB-ACCESS-TOKEN", accessToken));
}
3.3 任务生命周期管理
XXL-JOB支持任务的完整生命周期管理,包括初始化、执行和销毁三个阶段:
@XxlJob(value = "lifecycleJob", init = "initResource", destroy = "releaseResource")
public void lifecycleJob() throws Exception {
XxlJobHelper.log("任务执行中...");
// 任务执行逻辑
}
/**
* 任务初始化方法
*/
public void initResource() {
XxlJobHelper.log("初始化资源:加载配置、创建连接池等");
// 资源初始化逻辑
}
/**
* 任务销毁方法
*/
public void releaseResource() {
XxlJobHelper.log("释放资源:关闭连接、清理缓存等");
// 资源释放逻辑
}
生命周期管理优势:
- 初始化阶段:创建 expensive 资源(如数据库连接池、缓存客户端)
- 执行阶段:专注业务逻辑,避免重复创建资源
- 销毁阶段:确保资源正确释放,避免内存泄漏
四、实战案例:构建动态任务调度平台
4.1 系统架构设计
以下是一个基于XXL-JOB的动态任务调度平台架构:
flowchart TB
Client[业务系统] -->|创建任务| API[API网关]
API -->|权限校验| Auth[认证授权]
API -->|任务管理| Service[业务服务]
subgraph 动态任务平台
Service -->|1.保存元数据| DB[(数据库)]
Service -->|2.注册任务| Executor[XXL-JOB执行器]
Service -->|3.配置调度| Admin[XXL-JOB调度中心]
Executor -->|执行任务| Worker[任务工作节点]
Worker -->|输出日志| LogStore[(日志存储)]
Admin -->|调度触发| Executor
end
Monitor[监控系统] -->|监控指标| Service
Monitor -->|日志分析| LogStore
4.2 数据库设计
核心表结构设计,支持任务的动态管理:
CREATE TABLE `dynamic_job` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务ID',
`job_name` varchar(64) NOT NULL COMMENT '任务名称',
`job_handler` varchar(64) NOT NULL COMMENT '任务处理器名称',
`job_param` text COMMENT '任务参数',
`cron_expression` varchar(64) NOT NULL COMMENT 'Cron表达式',
`executor_route_strategy` varchar(50) DEFAULT 'ROUND' COMMENT '路由策略',
`executor_block_strategy` varchar(50) DEFAULT 'SERIAL_EXECUTION' COMMENT '阻塞处理策略',
`executor_timeout` int(11) DEFAULT 30000 COMMENT '任务超时时间(ms)',
`status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态(0-停止,1-运行)',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_job_handler` (`job_handler`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='动态任务表';
4.3 核心实现代码
4.3.1 任务管理服务
@Service
public class DynamicJobManager {
private static final Logger logger = LoggerFactory.getLogger(DynamicJobManager.class);
@Autowired
private DynamicJobMapper dynamicJobMapper;
@Autowired
private XxlJobAdminClient xxlJobAdminClient;
/**
* 创建动态任务
* @param job 任务信息
* @return 创建结果
*/
@Transactional
public Result<Long> createDynamicJob(DynamicJobDTO job) {
// 1. 生成唯一的JobHandler名称
String jobHandler = "dynamic_" + System.currentTimeMillis() + "_" + RandomUtils.nextInt(1000);
// 2. 保存任务元数据
DynamicJobDO jobDO = new DynamicJobDO();
BeanUtils.copyProperties(job, jobDO);
jobDO.setJobHandler(jobHandler);
jobDO.setStatus(0); // 初始状态为停止
dynamicJobMapper.insert(jobDO);
// 3. 注册任务处理器
IJobHandler jobHandlerInstance = createJobHandler(jobDO);
XxlJobExecutor.registJobHandler(jobHandler, jobHandlerInstance);
// 4. 在调度中心创建任务
XxlJobInfo xxlJobInfo = buildXxlJobInfo(jobDO);
xxlJobAdminClient.addJob(xxlJobInfo);
logger.info("动态任务创建成功: id={}, name={}", jobDO.getId(), jobDO.getJobName());
return Result.success(jobDO.getId());
}
/**
* 更新任务调度配置
* @param jobId 任务ID
* @param cronExpression 新的Cron表达式
* @return 更新结果
*/
public Result<Void> updateJobCron(Long jobId, String cronExpression) {
// 1. 验证Cron表达式合法性
if (!CronExpression.isValidExpression(cronExpression)) {
return Result.fail("Cron表达式格式不正确");
}
// 2. 更新本地数据库
DynamicJobDO jobDO = dynamicJobMapper.selectById(jobId);
if (jobDO == null) {
return Result.fail("任务不存在");
}
jobDO.setCronExpression(cronExpression);
dynamicJobMapper.updateById(jobDO);
// 3. 更新调度中心配置
xxlJobAdminClient.updateJobCron(jobDO.getJobHandler(), cronExpression);
logger.info("任务调度配置更新成功: id={}, cron={}", jobId, cronExpression);
return Result.success();
}
/**
* 启停任务
* @param jobId任务ID
* @param status 状态(0-停止,1-运行)
* @return 操作结果
*/
public Result<Void> changeJobStatus(Long jobId, int status) {
DynamicJobDO jobDO = dynamicJobMapper.selectById(jobId);
if (jobDO == null) {
return Result.fail("任务不存在");
}
// 更新调度中心任务状态
xxlJobAdminClient.changeJobStatus(jobDO.getJobHandler(), status == 1);
// 更新本地状态
jobDO.setStatus(status);
dynamicJobMapper.updateById(jobDO);
logger.info("任务状态更新成功: id={}, status={}", jobId, status);
return Result.success();
}
// 构建XXL-JOB任务信息
private XxlJobInfo buildXxlJobInfo(DynamicJobDO jobDO) {
XxlJobInfo info = new XxlJobInfo();
info.setJobDesc(jobDO.getJobName());
info.setJobHandler(jobDO.getJobHandler());
info.setCronExpression(jobDO.getCronExpression());
info.setExecutorRouteStrategy(jobDO.getExecutorRouteStrategy());
info.setExecutorBlockStrategy(jobDO.getExecutorBlockStrategy());
info.setExecutorTimeout(jobDO.getExecutorTimeout());
info.setAuthor("dynamic-job-manager");
info.setAlarmEmail("admin@example.com");
info.setStatus(0); // 初始为停止状态
return info;
}
// 创建任务处理器实例
private IJobHandler createJobHandler(DynamicJobDO jobDO) {
return new MethodJobHandler(this,
ReflectionUtils.findMethod(this.getClass(), "executeDynamicJob", Long.class),
null, null, jobDO.getId());
}
// 动态任务执行入口
public void executeDynamicJob(Long jobId) throws Exception {
DynamicJobDO jobDO = dynamicJobMapper.selectById(jobId);
if (jobDO == null) {
XxlJobHelper.handleFail("任务不存在: " + jobId);
return;
}
try {
// 记录任务开始执行日志
XxlJobHelper.log("动态任务开始执行: id={}, name={}", jobId, jobDO.getJobName());
// 执行任务逻辑
JobExecutorFactory.getExecutor(jobDO.getJobType())
.execute(jobDO.getJobParam(), XxlJobHelper.getJobLogFileName());
XxlJobHelper.handleSuccess();
} catch (Exception e) {
logger.error("动态任务执行失败: id={}", jobId, e);
XxlJobHelper.handleFail("任务执行失败: " + e.getMessage());
}
}
}
4.3.2 调度中心API客户端
@Component
public class XxlJobAdminClient {
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
/**
* 添加任务到调度中心
*/
public void addJob(XxlJobInfo jobInfo) {
Map<String, Object> params = new HashMap<>();
params.put("jobGroup", 1); // 默认执行器组
params.put("jobDesc", jobInfo.getJobDesc());
params.put("author", jobInfo.getAuthor());
params.put("alarmEmail", jobInfo.getAlarmEmail());
params.put("scheduleType", "CRON");
params.put("cronExpression", jobInfo.getCronExpression());
params.put("executorRouteStrategy", jobInfo.getExecutorRouteStrategy());
params.put("executorHandler", jobInfo.getJobHandler());
params.put("executorParam", jobInfo.getJobParam());
params.put("executorBlockStrategy", jobInfo.getExecutorBlockStrategy());
params.put("executorTimeout", jobInfo.getExecutorTimeout());
params.put("executorFailRetryCount", 3);
params.put("glueType", "BEAN");
params.put("status", jobInfo.getStatus());
doPost("/jobinfo/add", params);
}
/**
* 更新任务Cron表达式
*/
public void updateJobCron(String jobHandler, String cronExpression) {
// 查询任务ID
Map<String, Object> listParams = new HashMap<>();
listParams.put("jobGroup", 1);
listParams.put("executorHandler", jobHandler);
String jobList = doPost("/jobinfo/pageList", listParams);
// 解析任务ID并更新Cron
// 实际实现略...
}
/**
* 更改任务状态
*/
public void changeJobStatus(String jobHandler, boolean start) {
// 实现逻辑与updateJobCron类似
// 实际实现略...
}
private String doPost(String path, Map<String, Object> params) {
String url = adminAddresses + path;
HttpHeaders headers = new HttpHeaders();
headers.set("XXL-JOB-ACCESS-TOKEN", accessToken);
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(
mapToMultiValueMap(params), headers);
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
if (response.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException("调用调度中心API失败: " + response);
}
// 解析响应结果,处理错误码
// 实际实现略...
return response.getBody();
}
private MultiValueMap<String, Object> mapToMultiValueMap(Map<String, Object> map) {
MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
map.forEach(multiValueMap::add);
return multiValueMap;
}
}
4.4 前端管理界面设计
动态任务调度平台的前端界面应提供以下核心功能:
- 任务列表页:展示所有动态任务,支持搜索、筛选、排序
- 任务创建页:表单式创建新任务,包含任务基本信息、调度配置、参数配置
- 任务详情页:展示任务执行历史、日志、状态监控
- 任务编辑页:支持修改任务配置、启停任务、手动触发执行
关键界面原型:
+---------------------------------------------------+
| 动态任务管理平台 用户名 ▼ 退出 |
+---------------------------------------------------+
| 首页 | 任务管理 | 执行监控 | 日志查询 | 系统配置 |
+---------------------------------------------------+
| 任务列表 |
| +----+----------------+------------+------------+ |
| | ID | 任务名称 | 状态 | 操作 | |
| +----+----------------+------------+------------+ |
| | 1 | 数据同步任务 | 运行中 | ▶ ■ ✎ 🗑 | |
| | 2 | 报表生成任务 | 已停止 | ▶ ■ ✎ 🗑 | |
| | 3 | 日志清理任务 | 运行中 | ▶ ■ ✎ 🗑 | |
| +----+----------------+------------+------------+ |
| [新增任务] |
+---------------------------------------------------+
五、性能优化与最佳实践
5.1 动态任务性能优化
-
任务池化管理:
// 限制并发任务数量,避免资源耗尽 @Bean public ThreadPoolTaskExecutor jobExecutorPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(50); executor.setQueueCapacity(100); executor.setKeepAliveSeconds(60); executor.setThreadNamePrefix("dynamic-job-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return executor; } -
任务结果缓存:
// 对频繁执行的查询类任务结果进行缓存 @Cacheable(value = "jobResultCache", key = "#taskId") public ResultDTO executeQueryTask(Long taskId) { // 执行查询逻辑 return queryService.getData(taskId); } -
批量任务处理:
// 合并小任务为批处理任务,减少调度开销 @XxlJob("batchProcessingJob") public void batchProcessingJob() throws Exception { List<Long> pendingTasks = taskQueue.takeBatch(100); // 批量获取待处理任务 if (CollectionUtils.isEmpty(pendingTasks)) { XxlJobHelper.log("没有待处理任务"); return; } batchProcessor.process(pendingTasks); XxlJobHelper.log("批量处理完成,任务数量: {}", pendingTasks.size()); }
5.2 高可用部署策略
flowchart TB
Client[客户端请求] --> LB[负载均衡器]
subgraph 调度中心集群
Admin1[调度中心1]
Admin2[调度中心2]
Admin3[调度中心3]
end
subgraph 执行器集群
ExecutorGroup1[执行器组1]
ExecutorGroup2[执行器组2]
subgraph ExecutorGroup1
Exe1-1[执行器实例1]
Exe1-2[执行器实例2]
end
subgraph ExecutorGroup2
Exe2-1[执行器实例1]
Exe2-2[执行器实例2]
end
end
LB --> Admin1
LB --> Admin2
LB --> Admin3
Admin1 -->|调度任务| ExecutorGroup1
Admin2 -->|调度任务| ExecutorGroup2
Admin1 ---|数据同步| DB[(数据库)]
Admin2 ---|数据同步| DB
Admin3 ---|数据同步| DB
部署建议:
- 调度中心:至少3节点部署,确保高可用
- 执行器:按业务领域划分执行器组,便于资源隔离
- 数据库:主从架构,调度中心使用主库,执行器只读从库
- 配置中心:使用Nacos/Apollo管理动态配置,实现配置热更新
5.3 动态任务监控与运维
-
关键监控指标:
- 任务执行成功率:反映系统健康状况
- 任务平均耗时:反映任务执行效率
- 任务调度延迟:反映调度系统性能
- 执行器负载:CPU/内存/线程池使用率
-
日志管理:
@XxlJob("monitoredJob") public void monitoredJob() throws Exception { long startTime = System.currentTimeMillis(); String traceId = TraceContext.getTraceId(); XxlJobHelper.log("任务开始执行,traceId: {}", traceId); try { // 业务逻辑执行 businessService.execute(); long costTime = System.currentTimeMillis() - startTime; XxlJobHelper.log("任务执行成功,耗时: {}ms", costTime); // 记录性能指标 Metrics.record("job.success", costTime); } catch (Exception e) { long costTime = System.currentTimeMillis() - startTime; XxlJobHelper.log("任务执行失败,耗时: {}ms", costTime, e); // 记录错误指标 Metrics.record("job.failure", costTime); XxlJobHelper.handleFail("任务执行失败: " + e.getMessage()); } } -
故障处理机制:
- 任务超时自动终止:设置合理的任务超时时间
- 失败重试策略:关键任务配置失败自动重试
- 资源隔离:不同类型任务使用独立线程池
- 熔断保护:连续失败任务自动暂停调度
六、总结与展望
XXL-JOB的动态任务调度能力为构建灵活、高效的分布式任务系统提供了强大支持。通过本文介绍的技术方案,开发者可以实现任务的动态注册、配置调整和生命周期管理,满足业务快速变化的需求。
随着云原生技术的发展,XXL-JOB动态调度将向以下方向演进:
- 容器化部署:与Kubernetes等容器编排平台深度集成,实现任务的自动扩缩容
- Serverless架构:任务按需执行,进一步降低资源消耗
- AI辅助调度:基于机器学习算法预测任务负载,实现智能调度决策
- 低代码平台:通过可视化界面配置动态任务,降低使用门槛
动态任务调度是企业级应用的核心能力之一,掌握XXL-JOB的动态调度技术,将帮助开发者构建更具弹性和扩展性的分布式系统,从容应对业务快速变化的挑战。
读完本文你将获得:
- XXL-JOB动态调度核心原理与架构设计
- 三种动态任务实现方案(注解式、编程式、脚本式)
- 任务参数、调度策略、生命周期的动态管理方法
- 完整的动态任务平台构建实战案例
- 性能优化与高可用部署的最佳实践
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00- QQwen3-Coder-Next2026年2月4日,正式发布的Qwen3-Coder-Next,一款专为编码智能体和本地开发场景设计的开源语言模型。Python00
xw-cli实现国产算力大模型零门槛部署,一键跑通 Qwen、GLM-4.7、Minimax-2.1、DeepSeek-OCR 等模型Go06
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin08
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00