Introdução de cena
Os fornecedores tradicionais de gerenciamento de dados (que não usam tecnologia de computação em nuvem) costumam usar Oracle como armazenamento para data warehouses e Kettle como ETL e ferramentas de agendamento de processos. Contando com a estabilidade, alta eficiência e flexibilidade do Kettle da Oracle, a arquitetura tradicional pode lidar com vários cenários complexos. A estrutura de governança de dados é simplesmente esta:
Com o desenvolvimento e promoção contínuos da tecnologia de computação em nuvem, as arquiteturas tradicionais estão lentamente desaparecendo do mercado, mas durante o processo de entrega, é inevitável encontrar cenários que integram a computação em nuvem com fornecedores tradicionais. Por exemplo, usamos o produto DataWorks da Alibaba Cloud, que integra o armazenamento de dados em nuvem ODPS e a ferramenta de sincronização offline DataX, a arquitetura geral ficará assim:
Este artigo apresenta principalmente como garantir a sincronização de trabalhos DataX e trabalhos Kettle nos cenários acima.
Uma introdução
1. Crie um nó virtual ( vn_root
) no DataWorks e defina o nó para o estado "pausado" (as instâncias no estado pausado serão convertidas para o estado "falhou" quando o tempo de execução definido chegar) e, em seguida, todos os upstream do A tarefa de integração de dados DataX é configurada como este nó;
2. Use Java para encapsular a API DataWorks, o nome da classe de encapsulamento ResumeTask
e a saída como um pacote jar ( active_vn_root.jar
), o seguinte processo é implementado no código para ativar a tarefa DataX:
3. active_vn_root.jar
Reinicie o Kettle após colocá-lo no diretório data-integration \ lib
4. Adicione um nó de código java ao processo de negócios original. O código-fonte é o seguinte:
/* 引用 jar 包中的方法 */
import dataworks.ResumeTask;
public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
Object[] r = getRow();
if (r == null) {
setOutputDone();
return false;
}
/* 只处理第一行 */
if (first) {
first = false;
} else {
setOutputDone();
return false;
}
Object[] outputRow = createOutputRow(r, data.outputRowMeta.size());
/* 捕获上游信号 */
String signal = get(Fields.In, "signal").getString(r);
/* 处理信号 */
if (signal.compareTo("1") == 0) {
logBasic("signal is 1");
/* 节点号 1234 是固定值,不会变*/
int ret = ResumeTask.doResumeTask(1234);
/** ret 返回数字的含义
* 0 成功;
* -1 其他异常(网络异常);
* 1 查询异常,未查询到相关实例;
* 2 查询异常,查询到多个相关实例;
* 3 恢复失败;
* 4 恢复失败,任务为一次性任务;
* 5 恢复失败,任务为空跑任务;
* 6 恢复失败,接口调用返回值异常;
* 7 实例恢复成功,但重跑失败;
* 8 实例恢复成功,但重跑失败,任务并非失败任务,不需要重跑
* 9 实例恢复成功,但重跑失败,接口调用返回值异常;
*/
logBasic("return code is " + ret);
if (ret == 0) {
logBasic("active root node successfully: 调用成功");
get(Fields.Out, "result").setValue(outputRow, "success");
} else {
String err_msg = "UNKOWN ERROR";
switch(ret) {
case -1: err_msg="其他异常(网络异常);";break;
case 1: err_msg="查询异常,未查询到相关实例;";break;
case 2: err_msg="查询异常,查询到多个相关实例;";break;
case 3: err_msg="恢复失败;";break;
case 4: err_msg="恢复失败,任务为一次性任务;";break;
case 5: err_msg="恢复失败,任务为空跑任务;";break;
case 6: err_msg="恢复失败,接口调用返回值异常;";break;
case 7: err_msg="实例恢复成功,但重跑失败;";break;
case 8: err_msg="实例恢复成功,但重跑失败,任务并非失败任务,不需要重跑;";break;
case 9: err_msg="实例恢复成功,但重跑失败,接口调用返回值异常;";break;
}
logBasic("active root node failed: 调用失败," + err_msg);
get(Fields.Out, "result").setValue(outputRow, "fail");
}
} else {
logBasic("signal is not 1, will do nothing: 接收到的信号错误");
get(Fields.Out, "result").setValue(outputRow, "fail");
}
putRow(data.outputRowMeta, outputRow);
setOutputDone();
return false;
}
5. Como a API DataWorks é uma operação assíncrona (ou seja, retorna após a chamada e não espera que a tarefa seja executada), não há necessidade de se preocupar se a execução do nó bloqueará a execução do processo geral.