LTS原理--JobClient提交任务过程(二)

       JobClient是任务的发起者,JobClient的作用就是将相关的任务信息提交到JobTracker中,然后等待接收JobTracker的任务执行结果。

一、示例:

官方示例地址:https://github.com/ltsopensource/lts-examples

1、属性配置

配置zk的注册地址,其中JobTracker也是注册到zk中,因此JobClient可以从zk中获取JobTracker的执行地址

lts.jobclient.cluster-name=test_cluster
lts.jobclient.registry-address=zookeeper://127.0.0.1:2181
lts.jobclient.node-group=test_jobClient
lts.jobclient.use-retry-client=true
lts.jobclient.configs.job.fail.store=mapdb

2、注入JobClient

<bean id="jobClient" class="com.github.ltsopensource.spring.JobClientFactoryBean" init-method="start">
        <property name="locations" value="lts.properties"/>
        <property name="jobCompletedHandler">
            <bean class="com.github.ltsopensource.example.spring.JobCompletedHandlerImpl"/>
        </property>
    </bean>

3、提交任务

public class Main {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("/lts-jobclient.xml");

        JobClient jobClient = (JobClient) context.getBean("jobClient");

        Job job = new Job();
        job.setTaskId("t_realtime_5556666");
        job.setParam("shopId", "1122222221");
        job.setTaskTrackerNodeGroup("test_trade_TaskTracker");
        job.setNeedFeedback(true);
        job.setReplaceOnExist(true);        // 当任务队列中存在这个任务的时候,是否替换更新
        Response response = jobClient.submitJob(job);
        System.out.println(response);
    }

}

二、运行流程

我们通过跟踪代码来查看jobClient提交任务和获取任务执行结果的流程,接下来我们看看任务提交和获取任务执行结果的流程。

Response response = jobClient.submitJob(job)完成了任务提交和运行结果返回操作。

在JobClient中异步线程提交任务

//提交任务
public Response submitJob(Job job) throws JobSubmitException {
        checkStart();
        return protectSubmit(Collections.singletonList(job));
    }

    private Response protectSubmit(List<Job> jobs) throws JobSubmitException {
        //线程池异步提交任务
        return protector.execute(jobs, new JobSubmitExecutor<Response>() {
            @Override
            public Response execute(List<Job> jobs) throws JobSubmitException {
                return submitJob(jobs, SubmitType.ASYNC);
            }
        });
    }

在submitJob中根据任务创建任务提交请求,创建任务回调方法,根据提交方法选择asyncSubmit和syncSubmit提交任务

protected Response submitJob(final List<Job> jobs, SubmitType type) throws JobSubmitException {
        // 检查参数
        checkFields(jobs);

        final Response response = new Response();
        try {
			//创建任务提交请求
            JobSubmitRequest jobSubmitRequest = CommandBodyWrapper.wrapper(appContext, new JobSubmitRequest());
            jobSubmitRequest.setJobs(jobs);

            RemotingCommand requestCommand = RemotingCommand.createRequestCommand(
                    JobProtos.RequestCode.SUBMIT_JOB.code(), jobSubmitRequest);

			//创建任务提交及回调方法
            SubmitCallback submitCallback = new SubmitCallback() {
                @Override
                public void call(RemotingCommand responseCommand) {
                    if (responseCommand == null) {
                        response.setFailedJobs(jobs);
                        response.setSuccess(false);
                        response.setMsg("Submit Job failed: JobTracker is broken");
                        LOGGER.warn("Submit Job failed: {}, {}", jobs, "JobTracker is broken");
                        return;
                    }

                    if (JobProtos.ResponseCode.JOB_RECEIVE_SUCCESS.code() == responseCommand.getCode()) {
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug("Submit Job success: {}", jobs);
                        }
                        response.setSuccess(true);
                        return;
                    }
                    // 失败的job
                    JobSubmitResponse jobSubmitResponse = responseCommand.getBody();
                    response.setFailedJobs(jobSubmitResponse.getFailedJobs());
                    response.setSuccess(false);
                    response.setCode(JobProtos.ResponseCode.valueOf(responseCommand.getCode()).name());
                    response.setMsg("Submit Job failed: " + responseCommand.getRemark() + " " + jobSubmitResponse.getMsg());
                    LOGGER.warn("Submit Job failed: {}, {}, {}", jobs, responseCommand.getRemark(), jobSubmitResponse.getMsg());
                }
            };
			//根据任务提交方式提交任务
            if (SubmitType.ASYNC.equals(type)) {
                asyncSubmit(requestCommand, submitCallback);
            } else {
                syncSubmit(requestCommand, submitCallback);
            }
        } catch (JobTrackerNotFoundException e) {
            response.setSuccess(false);
            response.setCode(ResponseCode.JOB_TRACKER_NOT_FOUND);
            response.setMsg("Can not found JobTracker node!");
        } catch (Exception e) {
            response.setSuccess(false);
            response.setCode(ResponseCode.SYSTEM_ERROR);
            response.setMsg(StringUtils.toString(e));
        } finally {
            // 统计
            if (response.isSuccess()) {
                stat.incSubmitSuccessNum(jobs.size());
            } else {
                stat.incSubmitFailedNum(CollectionUtils.sizeOf(response.getFailedJobs()));
            }
        }

        return response;
    }

在syncSubmit或asyncSubmit中调用remoteingClient的inokeSync方法提交任务

private void syncSubmit(RemotingCommand requestCommand, final SubmitCallback submitCallback)
            throws JobTrackerNotFoundException {
        submitCallback.call(remotingClient.invokeSync(requestCommand));
    }

在invokeSync方法中会从注册中心中获取JobTracker节点的节点信息,并且会根据一些策略选择(一致性hash,随机、轮训和主从策略)

各种类型节点zk中的信息

public RemotingCommand invokeSync(RemotingCommand request)
            throws JobTrackerNotFoundException {

		//从注册中心中获取JobTracker节点的节点信息,会有一些策略
        Node jobTracker = getJobTrackerNode();

        try {
			//rpc远程调用
            RemotingCommand response = remotingClient.invokeSync(jobTracker.getAddress(),
                    request, appContext.getConfig().getInvokeTimeoutMillis());
            this.serverEnable = true;
			//返回调用结果
            return response;
        } catch (Exception e) {
            // 将这个JobTracker移除
            jobTrackers.remove(jobTracker);
            try {
                Thread.sleep(100L);
            } catch (InterruptedException e1) {
                LOGGER.error(e1.getMessage(), e1);
            }
            // 只要不是节点 不可用, 轮询所有节点请求
            return invokeSync(request);
        }
    }

在invokeSync中封装了一些通信方式(netty,mina和lts)与JobTracker通信,并返回执行结果。

@Override
    public RemotingCommand invokeSync(String addr, final RemotingCommand request, long timeoutMillis)
            throws InterruptedException, RemotingConnectException, RemotingSendRequestException,
            RemotingTimeoutException {
        final Channel channel = this.getAndCreateChannel(addr);
        if (channel != null && channel.isConnected()) {
            try {
                //远程通信,底层Netty、Mina或LTS实现
                return this.invokeSyncImpl(channel, request, timeoutMillis);
            } catch (RemotingSendRequestException e) {
                LOGGER.warn("invokeSync: send request exception, so close the channel[{}]", addr);
                this.closeChannel(addr, channel);
                throw e;
            } catch (RemotingTimeoutException e) {
                LOGGER.warn("invokeSync: wait response timeout exception, the channel[{}]", addr);
                // 超时异常如果关闭连接可能会产生连锁反应
                // this.closeChannel(addr, channel);
                throw e;
            }
        } else {
            this.closeChannel(addr, channel);
            throw new RemotingConnectException(addr);
        }
    }

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值