xxl-job(v2.1.0 Release)执行器端接收调度器任务执行的原理

(一)xxl-job介绍以及搭建过程
(二)xxl-job执行器端的执行器自动注册原理
(三)xxl-job调度器端的执行器自动注册原理
(四)xxl-job任务管理以及调度器端任务手动执行的原理
(五)xxl-job调度器端任务启动执行的原理
(六)xxl-job执行器端接收调度器任务执行的原理
调度中心通过netty发送调度请求,执行器有个专门的处理类ExecutorBizImpl去响应调度请求。

xxl-job(v2.1.0 Release)执行器端接收调度器任务执行的原理_第1张图片
实际上调度中心和执行器部署在不同的服务器上,通过executorBiz.run(triggerParam)并不会让执行器的处理类ExecutorBizImpl响应(ExecutorBizImpl实现了ExecutorBiz接口),executorBiz.run(triggerParam)执行的时候会触发InvocationHandler的invoke方法,通过netty向执行器发送请求。

  public Object getObject() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{this.iface}, new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String className = method.getDeclaringClass().getName();
                String varsion_ = XxlRpcReferenceBean.this.version;
                String methodName = method.getName();
                Class[] parameterTypes = method.getParameterTypes();
                Object[] parameters = args;
                    if (finalAddress != null && finalAddress.trim().length() != 0) {
                        XxlRpcRequest xxlRpcRequest = new XxlRpcRequest();
                        xxlRpcRequest.setRequestId(UUID.randomUUID().toString());
                        xxlRpcRequest.setCreateMillisTime(System.currentTimeMillis());
                        xxlRpcRequest.setAccessToken(XxlRpcReferenceBean.this.accessToken);
                        xxlRpcRequest.setClassName(className);
                        xxlRpcRequest.setMethodName(methodName);
                        xxlRpcRequest.setParameterTypes(parameterTypes);
                        xxlRpcRequest.setParameters(parameters);
                        XxlRpcFutureResponse futureResponse;
                        if (CallType.SYNC == XxlRpcReferenceBean.this.callType) {
                            futureResponse = new XxlRpcFutureResponse(XxlRpcReferenceBean.this.invokerFactory, xxlRpcRequest, (XxlRpcInvokeCallback)null);

                            Object var31;
                            try {
                              //通过netty向执行器发送请求
                                XxlRpcReferenceBean.this.client.asyncSend(finalAddress, xxlRpcRequest);
                                XxlRpcResponse xxlRpcResponse = futureResponse.get(XxlRpcReferenceBean.this.timeout, TimeUnit.MILLISECONDS);
                                if (xxlRpcResponse.getErrorMsg() != null) {
                                    throw new XxlRpcException(xxlRpcResponse.getErrorMsg());
                                }

                                var31 = xxlRpcResponse.getResult();
                            } catch (Exception var21) {
                                XxlRpcReferenceBean.logger.info(">>>>>>>>>>> xxl-rpc, invoke error, address:{}, XxlRpcRequest{}", finalAddress, xxlRpcRequest);
                                throw (Throwable)(var21 instanceof XxlRpcException ? var21 : new XxlRpcException(var21));
                            } finally {
                                futureResponse.removeInvokerFuture();
                            }

                            return var31;
                        }  

执行器的ExecutorBizImpl去处理任务执行请求,这里只介绍Bean模式任务方式(再次方式下Handler才能够使用)

  public class ExecutorBizImpl implements ExecutorBiz {
   
    @Override
    public ReturnT run(TriggerParam triggerParam) {
        // 获取任务线程
        JobThread jobThread = XxlJobExecutor.loadJobThread(triggerParam.getJobId());
        //通过jobThread 获取任务Handler
        IJobHandler jobHandler = jobThread!=null?jobThread.getHandler():null;
        String removeOldReason = null;

        // valid:jobHandler + jobThread
        GlueTypeEnum glueTypeEnum = GlueTypeEnum.match(triggerParam.getGlueType());
        if (GlueTypeEnum.BEAN == glueTypeEnum) {

            // 通过在任务管理添加的JobHandler参数获取对应的JobHandler类实例
            IJobHandler newJobHandler = XxlJobExecutor.loadJobHandler(triggerParam.getExecutorHandler());

            // 在这里判断通过jobId获取的jobHandler和通过JonHandler参数获取的newJobHandler是不是同一个
            //如果不是就要重新获取
            if (jobThread!=null && jobHandler != newJobHandler) {
                // change handler, need kill old thread
                removeOldReason = "change jobhandler or glue type, and terminate the old job thread.";

                jobThread = null;
                jobHandler = null;
            }
        }
     //在这里判断通过jobId获取的jobHandler和通过JonHandler参数获取的newJobHandler是不是同一个
     //重新实例化jobThread,并开启线程
    if (jobThread == null) {
        jobThread = XxlJobExecutor.registJobThread(triggerParam.getJobId(), jobHandler, removeOldReason);
    }

    //将调度中心发过来的请求参数都入队列
      ReturnT pushResult = jobThread.pushTriggerQueue(triggerParam);
    }

重新实例化jobThread,并开启线程

   private static ConcurrentMap jobThreadRepository = new ConcurrentHashMap();
        public static JobThread registJobThread(int jobId, IJobHandler handler, String removeOldReason){
            JobThread newJobThread = new JobThread(jobId, handler);
            newJobThread.start();
            //将jobThread存入jobThreadRepository,把老jobThread的删除并且停止线程
            JobThread oldJobThread = jobThreadRepository.put(jobId, newJobThread);	// putIfAbsent | oh my god, map's put method return the old value!!!
            if (oldJobThread != null) {
                oldJobThread.toStop(removeOldReason);
                oldJobThread.interrupt();
            }
    
            return newJobThread;
        }

然后将调度中心发过来的请求参数都入队列
ReturnT pushResult = jobThread.pushTriggerQueue(triggerParam);

 public class JobThread extends Thread{
    public ReturnT pushTriggerQueue(TriggerParam triggerParam) {
    	 
    	triggerLogIdSet.add(triggerParam.getLogId());
    	triggerQueue.add(triggerParam);
        return ReturnT.SUCCESS;
    }
    }

我们前面说到jobThreadRepository里面的jobThread都在启动状态
我们就来看看此线程做了什么

public class JobThread extends Thread{
 @Override
	public void run() {
    
		//在这里有个while循环,一直不断的在执行
		while(!toStop){
	 
            try {
			 //3秒钟出一次队列
				triggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS);
				if (triggerParam!=null) {
					running = true;
					idleTimes = 0;
					triggerLogIdSet.remove(triggerParam.getLogId());
                   //如果设置了任务执行的超值时间 就启动个线程并设置任务超时时间  
                   //此任务用来执行handler.execute()方法
					if (triggerParam.getExecutorTimeout() > 0) {
						// limit timeout
						Thread futureThread = null;
						try {
							final TriggerParam triggerParamTmp = triggerParam;
							FutureTask> futureTask = new FutureTask>(new Callable>() {
								@Override
								public ReturnT call() throws Exception {
									return handler.execute(triggerParamTmp.getExecutorParams());
								}
							});
							futureThread = new Thread(futureTask);
							futureThread.start();

							executeResult = futureTask.get(triggerParam.getExecutorTimeout(), TimeUnit.SECONDS);
						} catch (TimeoutException e) {

							XxlJobLogger.log("
----------- xxl-job job execute timeout"); XxlJobLogger.log(e); executeResult = new ReturnT(IJobHandler.FAIL_TIMEOUT.getCode(), "job execute timeout "); } finally { futureThread.interrupt(); } } else { //没有设置任务的超时时间 直接通过handler调用execute()方法 // just execute executeResult = handler.execute(triggerParam.getExecutorParams()); } if (executeResult == null) { executeResult = IJobHandler.FAIL; } else { executeResult.setMsg( (executeResult!=null&&executeResult.getMsg()!=null&&executeResult.getMsg().length()>50000) ?executeResult.getMsg().substring(0, 50000).concat("...") :executeResult.getMsg()); executeResult.setContent(null); // limit obj size } XxlJobLogger.log("
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:" + executeResult); } else { if (idleTimes > 30) { XxlJobExecutor.removeJobThread(jobId, "excutor idel times over limit."); } } } } }

xxl-job(v2.1.0 Release)执行器端接收调度器任务执行的原理_第2张图片

你可能感兴趣的:(xxl-job)