背景
公司项目服务间使用dubbo通信,引入xxl-job后,需要按照xxl-job的语法对任务予以改造,比如增加@XxlJob注解,修改返回参数等,并且每个服务要配置调度中心的地址,涉及到几十个服务,比较繁琐,并且公司之所以引入xxl-job,主要原因是之前定时任务运行在各自的服务内,没有统一的监控,引入xxl-job后就可以很方便的查看任务运行情况,以及邮件告警、重试等,对于任务具体的调度方式不是很关心,所以这里任务调度不再使用原生的xxl-rpc,而是引入dubbo的调度方式,与之前的项目风格保持一致
改造目标
新建任务的运行模式不再使用bean以及jobHandler,增加dubbo方式,选中后填入dubbo组件名称以及方法名称,触发调度时,到注册中心拉取清单,发起泛化调用
改造流程
添加dubbo以及nacos依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>0.2.3</version>
</dependency>
properties添加参数
### nacos
nacos.discovery.server-addr=47.92.xxx.xxx:8848
### dubbo
dubbo.application.name=xxl-job-dubbo-admin
dubbo.registry.address=nacos://47.92.xxx.xxx:8848
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
xxl_job_info表增加字段
`dubbo_component_name` varchar(255) NOT NULL DEFAULT '0' COMMENT 'dubbo组件名',
`dubbo_method_name` varchar(255) NOT NULL DEFAULT '0' COMMENT 'dubbo方法名',
XxlJobInfo实体类增加字段
private String dubboComponentName; // dubbo组件名
private String dubboMethodName; // dubbo方法名
修改XxlJobInfoMapper.xml,针对插入、修改、查询等sql增加字段dubbo_component_name和dubbo_method_name,如下图不再赘述
<result column="dubbo_component_name" property="dubboComponentName" />
<result column="dubbo_method_name" property="dubboMethodName" />
调用方式枚举类GlueTypeEnum增加枚举值dubbo
public enum GlueTypeEnum {
DUBBO("DUBBO", false, null, null),
BEAN("BEAN", false, null, null),
GLUE_GROOVY("GLUE(Java)", false, null, null),
GLUE_SHELL("GLUE(Shell)", true, "bash", ".sh"),
GLUE_PYTHON("GLUE(Python)", true, "python", ".py"),
GLUE_PHP("GLUE(PHP)", true, "php", ".php"),
GLUE_NODEJS("GLUE(Nodejs)", true, "node", ".js"),
GLUE_POWERSHELL("GLUE(PowerShell)", true, "powershell", ".ps1");
XxlJobAdminConfig注入nacos的命名服务
@NacosInjected
private NamingService namingService;
......
public NamingService getNamingService() {
return namingService;
}
XxlJobServiceImpl修改add方法,参照bean的格式增加dubbo类型的响应
对应在message_zh_CN.properties中添加文案
jobinfo_dubbo_component=dubbo组件
jobinfo_dubbo_component_placeholder=请输入dubbo组件名
jobinfo_dubbo_method=dubbo方法名
jobinfo_dubbo_method_placeholder=请输入dubbo方法名
修改jobinfo.index.1.js, 运行模式下拉框添加dubbo
$("#updateModal .form input[name='dubboComponentName']").val( row.dubboComponentName );
$("#updateModal .form input[name='dubboMethodName']").val( row.dubboMethodName );
修改jobinfo.index.ftl,新建任务的页面添加文本域组件名称、方法名
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_dubbo_component}<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="dubboComponentName" placeholder="${I18n.jobinfo_dubbo_component_placeholder}" maxlength="100" ></div>
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_dubbo_method}<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="dubboMethodName" placeholder="${I18n.jobinfo_dubbo_method_placeholder}" maxlength="100" ></div>
</div>
......
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_dubbo_component}<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="dubboComponentName" placeholder="${I18n.jobinfo_dubbo_component_placeholder}" maxlength="100" ></div>
<label for="lastname" class="col-sm-2 control-label">${I18n.jobinfo_dubbo_method}<font color="red">*</font></label>
<div class="col-sm-4"><input type="text" class="form-control" name="dubboMethodName" placeholder="${I18n.jobinfo_dubbo_method_placeholder}" maxlength="100" ></div>
</div>
xxlJob发起调度的逻辑在XxlJobTrigger中的processTrigger方法,只需要判断如果调度方式是dubbo,走我们新加的调用逻辑,否则走原来的分支即可
if (GlueTypeEnum.DUBBO==GlueTypeEnum.match(jobInfo.getGlueType())) {
try {
NamingService namingService = XxlJobAdminConfig.getAdminConfig().getNamingService();
List<Instance> list = namingService.getAllInstances(jobInfo.getDubboComponentName());
Instance instance = list.get(RandomUtils.nextInt(list.size()));
// 创建服务实例
ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
reference.setGeneric(true);
reference.setInterface(instance.getMetadata().get("interface"));
reference.setVersion(instance.getMetadata().get("version"));
// 获取缓存中的实例
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
GenericService genericService = cache.get(reference);
// 调用实例
Object result = genericService.$invoke(jobInfo.getDubboMethodName(), null, null);
} catch (Exception e) {
e.printStackTrace();
}
triggerResult = new ReturnT<String>(ReturnT.SUCCESS_CODE, null);
} else {
// 2、init trigger-param
......
对比修改前后
修改后不需要每个服务再到xxl-job这里注册信息,也就没有心跳和健康检查,不过这些都在公司的其它系统有监测,这部分功能可以直接舍弃