xxl-job(spring boot)客户端执行器初始化bean与接收rpc请求处理流程简单分析

xxl-job客户端如何接入spring boot,按xxl-job官方给出来的demo,需要以下几个过程

  1. 首先是配置
  2. 接着配置扫描地址,把对应的jobHandler加载到spring容器中
  3. 配置XxlJobSpringExecutor,接着启动项目即可
1、======================================================================
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin,http://192.168.1.168:1888/xxl-job-admin

### xxl-job executor address
xxl.job.executor.appname=app-job-executor
xxl.job.executor.ip=
xxl.job.executor.port=9998

### xxl-job, access token
xxl.job.accessToken=

### xxl-job log path
xxl.job.executor.logpath=D:/xxl-job
### xxl-job log retention days
xxl.job.executor.logretentiondays=-1
2、=========================================================================
@Configuration
@ComponentScan(basePackages = "com.xxl.job.executor.service.jobhandler")
3、=========================================================================
@Bean(initMethod = "start", destroyMethod = "destroy")
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppName(appName);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    }

ok,那我们分析一下主要的init流程与接收调度中心调度请求的流程

1、首先定位到XxlJobSpringExecutor的initMethod,start()

@Override
    public void start() throws Exception {

        //初始化jobHandler
        initJobHandlerRepository(applicationContext);

        // refresh GlueFactory
        GlueFactory.refreshInstance(1);


        // super start
        super.start();
    }

private void initJobHandlerRepository(ApplicationContext applicationContext){
        if (applicationContext == null) {
            return;
        }

        // 从spring中拿到JobHandler注解的bean map
        Map serviceBeanMap = applicationContext.getBeansWithAnnotation(JobHandler.class);

        if (serviceBeanMap!=null && serviceBeanMap.size()>0) {
            for (Object serviceBean : serviceBeanMap.values()) {
                //判断是否IJobHandler
                if (serviceBean instanceof IJobHandler){
                    String name = serviceBean.getClass().getAnnotation(JobHandler.class).value();
                    IJobHandler handler = (IJobHandler) serviceBean;
                    if (loadJobHandler(name) != null) {
                        throw new RuntimeException("xxl-job jobhandler naming conflicts.");
                    }
                    //拿到JobHandler注解的名字,以及IJobHandler放入jobHandlerRepository中
                    registJobHandler(name, handler);
                }
            }
        }
    }
// ---------------------- job handler repository ----------------------
    private static ConcurrentHashMap jobHandlerRepository = new ConcurrentHashMap();
    public static IJobHandler registJobHandler(String name, IJobHandler jobHandler){
        logger.info(">>>>>>>>>>> xxl-job register jobhandler success, name:{}, jobHandler:{}", name, jobHandler);
        return jobHandlerRepository.put(name, jobHandler);
    }

 2、调用父类XxlJobExecutor的start()方法,首先我们看initAdminBizList();

private static List adminBizList;
//拿到我们刚才设置的adminAddresses列表(xxl.job.admin.addresses)
private void initAdminBizList(String adminAddresses, String accessToken) throws Exception {
        if (adminAddresses!=null && adminAddresses.trim().length()>0) {
            for (String address: adminAddresses.trim().split(",")) {
                if (address!=null && address.trim().length()>0) {
                    //addressUrl地址:http://127.0.0.1:8080/xxl-job-admin/api
                    String addressUrl = address.concat(AdminBiz.MAPPING);
                    //通过XxlRpcReferenceBean#getObject()设置动态代理,主要用来请求和处理rpc信息,这里使用的是JETTY,JettyServer和JettyClient去处理,还支持mima,netty等的扩展
                    AdminBiz adminBiz = (AdminBiz) new XxlRpcReferenceBean(NetEnum.JETTY, Serializer.SerializeEnum.HESSIAN.getSerializer(), CallType.SYNC,
                            AdminBiz.class, null, 10000, addressUrl, accessToken, null).getObject();

                    if (adminBizList == null) {
                        adminBizList = new ArrayList();
                    }
                    //放入adminBizList中
                    adminBizList.add(adminBiz);
                }
            }
        }
    }
//XxlRpcReferenceBean#getObject()
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 {
                //....代码太多,略过
                }
            }
        });
    }

3、启动日志清理守护线程

//感兴趣可以自己看
JobLogFileCleanThread.getInstance().start(logRetentionDays);

4、启动触发器回调守护线程

TriggerCallbackThread.getInstance().start();
/******************************************************************/
//判断我们在步骤2中获取到的adminBizList是否有值
 if (XxlJobExecutor.getAdminBizList() == null) {
     return;
}
//启动任务执行完成的回调线程
triggerCallbackThread = new Thread(new Runnable() {

            @Override
            public void run() {

                // normal callback
                while(!toStop){
                    try {
//使用一个无界队列(LinkedBlockingQueue)保存执行结果,并take()得到就执行回调
                        HandleCallbackParam callback = getInstance().callBackQueue.take();
                        if (callback != null) {

                            // callback list param
                            List callbackParamList = new ArrayList();
                           //移除队列中可用的元素,加入到callBackParamList中
                            int drainToNum = getInstance().callBackQueue.drainTo(callbackParamList);
                            callbackParamList.add(callback);

                            // callback, will retry if error
                            if (callbackParamList!=null && callbackParamList.size()>0) {
                                //执行doCallBack方法,看下方
                                doCallback(callbackParamList);
                            }
                        }
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                    }
                }

                // last callback
                try {
                    List callbackParamList = new ArrayList();
                    int drainToNum = getInstance().callBackQueue.drainTo(callbackParamList);
                    if (callbackParamList!=null && callbackParamList.size()>0) {
                        doCallback(callbackParamList);
                    }
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
                logger.info(">>>>>>>>>>> xxl-job, executor callback thread destory.");

            }
        });
        triggerCallbackThread.setDaemon(true);
        triggerCallbackThread.start();

private void doCallback(List callbackParamList){
        boolean callbackRet = false;
        // callback, will retry if error
        for (AdminBiz adminBiz: XxlJobExecutor.getAdminBizList()) {
            try {
                //AdminBiz->刚刚用XxlRpcReferenceBean设置动态代理的对象
                //实际上会通过XxlRpcRequest调用xxl-job-admin /api接口
                //并通过XxlRpcProviderFactory,使用反射,调用adminBiz的实现类的callBack方法
                ReturnT callbackResult = adminBiz.callback(callbackParamList);
                if (callbackResult!=null && ReturnT.SUCCESS_CODE == callbackResult.getCode()) {
                    callbackLog(callbackParamList, "
----------- xxl-job job callback finish."); callbackRet = true; break; } else { callbackLog(callbackParamList, "
----------- xxl-job job callback fail, callbackResult:" + callbackResult); } } catch (Exception e) { callbackLog(callbackParamList, "
----------- xxl-job job callback error, errorMsg:" + e.getMessage()); } } if (!callbackRet) { appendFailCallbackFile(callbackParamList); } }

5、执行initRpcProvider(),默认jetty启动端口是9999,并开启

private void initRpcProvider(String ip, int port, String appName, String accessToken) throws Exception {
        // init invoker factory
        xxlRpcInvokerFactory = new XxlRpcInvokerFactory();

        // init, provider factory
        //执行器执行地址
        String address = IpUtil.getIpPort(ip, port);
        Map serviceRegistryParam = new HashMap();
        serviceRegistryParam.put("appName", appName);
        serviceRegistryParam.put("address", address);

        xxlRpcProviderFactory = new XxlRpcProviderFactory();
        //初始化xxlRpcProvinderFactory
        xxlRpcProviderFactory.initConfig(NetEnum.JETTY, Serializer.SerializeEnum.HESSIAN.getSerializer(), ip, port, accessToken, ExecutorServiceRegistry.class, serviceRegistryParam);

        // add services
        xxlRpcProviderFactory.addService(ExecutorBiz.class.getName(), null, new ExecutorBizImpl());

        // start
       xxlRpcProviderFactory.start();

    }

6、(代码较多)启动刚才在步骤2中设置的NetEnum的JettyServer,并设置开启后的回调方法和关闭回调方法

public void start() throws Exception {
        //1、指定server为JettyServer 
        this.server = (Server)this.netType.serverClass.newInstance();
        //2、设置启动后的回调
        this.server.setStartedCallback(new BaseCallback() {
            public void run() throws Exception {
                if (XxlRpcProviderFactory.this.serviceRegistryClass != null) {
                    //实例化XxlRpcProviderFactory
                    XxlRpcProviderFactory.this.serviceRegistry = (ServiceRegistry)XxlRpcProviderFactory.this.serviceRegistryClass.newInstance();
                    //调用ExecutorServiceRegistry的start方法,启动一个ExecutorRegistryThread守护线程,每30秒去注册一次                    XxlRpcProviderFactory.this.serviceRegistry.start(XxlRpcProviderFactory.this.serviceRegistryParam);
                    if (XxlRpcProviderFactory.this.serviceData.size() > 0) {
                        String ipPort = IpUtil.getIpPort(XxlRpcProviderFactory.this.ip, XxlRpcProviderFactory.this.port);
                        Iterator i$ = XxlRpcProviderFactory.this.serviceData.keySet().iterator();

                        while(i$.hasNext()) {
                            String serviceKey = (String)i$.next();
                            XxlRpcProviderFactory.this.serviceRegistry.registry(serviceKey, ipPort);
                        }
                    }
                }

            }
        });
        //3、设置关闭后的回调
        this.server.setStopedCallback(new BaseCallback() {
            public void run() {
                if (XxlRpcProviderFactory.this.serviceRegistry != null) {
                    if (XxlRpcProviderFactory.this.serviceData.size() > 0) {
                        String ipPort = IpUtil.getIpPort(XxlRpcProviderFactory.this.ip, XxlRpcProviderFactory.this.port);
                        Iterator i$ = XxlRpcProviderFactory.this.serviceData.keySet().iterator();

                        while(i$.hasNext()) {
                            String serviceKey = (String)i$.next();
                            XxlRpcProviderFactory.this.serviceRegistry.remove(serviceKey, ipPort);
                        }
                    }

                    XxlRpcProviderFactory.this.serviceRegistry.stop();
                    XxlRpcProviderFactory.this.serviceRegistry = null;
                }

            }
        });
        //4、开启jetty服务
        this.server.start(this);
    }
//4、JettyServer#start()
public void start(final XxlRpcProviderFactory xxlRpcProviderFactory) throws Exception {
        this.thread = new Thread(new Runnable() {
            public void run() {
                JettyServer.this.server = new org.eclipse.jetty.server.Server(new QueuedThreadPool());
                ServerConnector connector = new ServerConnector(JettyServer.this.server);
                connector.setPort(xxlRpcProviderFactory.getPort());
                JettyServer.this.server.setConnectors(new Connector[]{connector});
                HandlerCollection handlerc = new HandlerCollection();
                //****设置接收xxl-job-admin rpc请求处理
                handlerc.setHandlers(new Handler[]{new JettyServerHandler(xxlRpcProviderFactory)});
                JettyServer.this.server.setHandler(handlerc);

                try {
                    //开启jetty
                    JettyServer.this.server.start();
                    JettyServer.logger.info(">>>>>>>>>>> xxl-rpc remoting server start success, nettype = {}, port = {}", JettyServer.class.getName(), xxlRpcProviderFactory.getPort());
                    //回调步骤2
                    JettyServer.this.onStarted();
                    //让出时间片
                    JettyServer.this.server.join();
                } catch (Exception var12) {
                    JettyServer.logger.error(">>>>>>>>>>> xxl-rpc remoting server start error.", var12);
                } finally {
                    try {
                        JettyServer.this.stop();
                    } catch (Exception var11) {
                        JettyServer.logger.error(var11.getMessage(), var11);
                    }

                }

            }
        });
        this.thread.setDaemon(true);
        this.thread.start();
    }
//5、执行开启后的回调(步骤2),执行注册
public void onStarted() {
        if (this.startedCallback != null) {
            try {
                this.startedCallback.run();
            } catch (Exception var2) {
                logger.error(">>>>>>>>>>> xxl-rpc, server startedCallback error.", var2);
            }
        }

    }

7、延续一下6的注册过程,通过rpc每30秒注册到xxl-job-admin一次

//ExecutorRegistryThread#start()
public void start(final String appName, final String address){

        // valid
        if (appName==null || appName.trim().length()==0) {
            logger.warn(">>>>>>>>>>> xxl-job, executor registry config fail, appName is null.");
            return;
        }
        if (XxlJobExecutor.getAdminBizList() == null) {
            logger.warn(">>>>>>>>>>> xxl-job, executor registry config fail, adminAddresses is null.");
            return;
        }

        registryThread = new Thread(new Runnable() {
            @Override
            public void run() {

                // registry
                while (!toStop) {
                    try {
                       //构建注册请求参数
                        RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), appName, address);
                        for (AdminBiz adminBiz: XxlJobExecutor.getAdminBizList()) {
                            try {
                             //调用XxlRpcReferenceBean动态代理方法getObject(),执行xxl-job-admin的api接口,执行AdminBiz子类的registry方法
                                ReturnT registryResult = adminBiz.registry(registryParam);
                                if (registryResult!=null && ReturnT.SUCCESS_CODE == registryResult.getCode()) {
                                    registryResult = ReturnT.SUCCESS;
                                    logger.info(">>>>>>>>>>> xxl-job registry success, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
                                    break;
                                } else {
                                    logger.info(">>>>>>>>>>> xxl-job registry fail, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
                                }
                            } catch (Exception e) {
                                logger.info(">>>>>>>>>>> xxl-job registry error, registryParam:{}", registryParam, e);
                            }

                        }
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                    }

                    try {
                        //每30秒执行一次
                        TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
                    } catch (InterruptedException e) {
                        logger.warn(">>>>>>>>>>> xxl-job, executor registry thread interrupted, error msg:{}", e.getMessage());
                    }
                }

                // registry remove
                //触发toStop之后,会停止注册,并一样通过rpc调用registryRemove()方法
                try {
                    RegistryParam registryParam = new RegistryParam(RegistryConfig.RegistType.EXECUTOR.name(), appName, address);
                    for (AdminBiz adminBiz: XxlJobExecutor.getAdminBizList()) {
                        try {
                            ReturnT registryResult = adminBiz.registryRemove(registryParam);
                            if (registryResult!=null && ReturnT.SUCCESS_CODE == registryResult.getCode()) {
                                registryResult = ReturnT.SUCCESS;
                                logger.info(">>>>>>>>>>> xxl-job registry-remove success, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
                                break;
                            } else {
                                logger.info(">>>>>>>>>>> xxl-job registry-remove fail, registryParam:{}, registryResult:{}", new Object[]{registryParam, registryResult});
                            }
                        } catch (Exception e) {
                            logger.info(">>>>>>>>>>> xxl-job registry-remove error, registryParam:{}", registryParam, e);
                        }

                    }
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
                logger.info(">>>>>>>>>>> xxl-job, executor registry thread destory.");

            }
        });
        registryThread.setDaemon(true);
        registryThread.start();
    }

8、处理rpc请求,刚才在启动jetty的时候设置了HandlerConnection为JettyServerHandler

public class JettyServerHandler extends AbstractHandler {
//处理rpc请求
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        StringBuffer stringBuffer;
        if (!"/services".equals(target)) {
            stringBuffer = null;

            XxlRpcRequest xxlRpcRequest;
            try {
                //读取流并反序列化
                xxlRpcRequest = this.parseRequest(request);
            } catch (Exception var8) {
                //反序列化失败就返回异常
                this.writeResponse(baseRequest, response, ThrowableUtil.toString(var8).getBytes());
                return;
            }
            //构建返回结果
            XxlRpcResponse xxlRpcResponse = this.xxlRpcProviderFactory.invokeService(xxlRpcRequest);
            byte[] responseBytes = this.xxlRpcProviderFactory.getSerializer().serialize(xxlRpcResponse);
            //序列化后返回给xxl-job-admin
            this.writeResponse(baseRequest, response, responseBytes);
        } else {
            stringBuffer = new StringBuffer("");
            Iterator i$ = this.xxlRpcProviderFactory.getServiceData().keySet().iterator();

            while(i$.hasNext()) {
                String serviceKey = (String)i$.next();
                stringBuffer.append("
  • ").append(serviceKey).append(": ").append(this.xxlRpcProviderFactory.getServiceData().get(serviceKey)).append("
  • "); } stringBuffer.append("
    "); this.writeResponse(baseRequest, response, stringBuffer.toString().getBytes()); } } } //XxlRpcProviderFactory#invokeService public XxlRpcResponse invokeService(XxlRpcRequest xxlRpcRequest) { //构建返回结果response XxlRpcResponse xxlRpcResponse = new XxlRpcResponse(); xxlRpcResponse.setRequestId(xxlRpcRequest.getRequestId()); String serviceKey = makeServiceKey(xxlRpcRequest.getClassName(), xxlRpcRequest.getVersion()); //获取执行的服务,步骤5设置 Object serviceBean = this.serviceData.get(serviceKey); if (serviceBean == null) { xxlRpcResponse.setErrorMsg("The serviceKey[" + serviceKey + "] not found."); return xxlRpcResponse; } else if (System.currentTimeMillis() - xxlRpcRequest.getCreateMillisTime() > 180000L) { xxlRpcResponse.setErrorMsg("The timestamp difference between admin and executor exceeds the limit."); return xxlRpcResponse; } else if (this.accessToken != null && this.accessToken.trim().length() > 0 && !this.accessToken.trim().equals(xxlRpcRequest.getAccessToken())) { xxlRpcResponse.setErrorMsg("The access token[" + xxlRpcRequest.getAccessToken() + "] is wrong."); return xxlRpcResponse; } else { try { Class serviceClass = serviceBean.getClass(); //run String methodName = xxlRpcRequest.getMethodName(); Class[] parameterTypes = xxlRpcRequest.getParameterTypes(); Object[] parameters = xxlRpcRequest.getParameters(); Method method = serviceClass.getMethod(methodName, parameterTypes); method.setAccessible(true); //通过反射执行对应的方法,这里调用的是ExecutorBizImpl#run() Object result = method.invoke(serviceBean, parameters); xxlRpcResponse.setResult(result); } catch (Throwable var11) { logger.error("xxl-rpc provider invokeService error.", var11); xxlRpcResponse.setErrorMsg(ThrowableUtil.toString(var11)); } return xxlRpcResponse; } }

    9、执行ExecutorBizImpl#run方法,从而执行最终的IJobHandler#executor方法

    public ReturnT run(TriggerParam triggerParam) {
            //先判断是否存在处理jobId的jobThread,不存在就注册一个
            JobThread jobThread = XxlJobExecutor.loadJobThread(triggerParam.getJobId());
            //获取IJobHandler
            IJobHandler jobHandler = jobThread!=null?jobThread.getHandler():null;
            String removeOldReason = null;
    
            // valid:jobHandler + jobThread
            GlueTypeEnum glueTypeEnum = GlueTypeEnum.match(triggerParam.getGlueType());
            if (GlueTypeEnum.BEAN == glueTypeEnum) {
    
                // 根据jobHandler的名称,获取我们一开始就存入jobHandlerResp中的IJobHandler
                IJobHandler newJobHandler = XxlJobExecutor.loadJobHandler(triggerParam.getExecutorHandler());
    
                // valid old jobThread
                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;
                }
    
                // valid handler
                //如果是第一次触发,jobHandler为空,那么就设置对应的jobHandler
                if (jobHandler == null) {
                    jobHandler = newJobHandler;
                    if (jobHandler == null) {
                        return new ReturnT(ReturnT.FAIL_CODE, "job handler [" + triggerParam.getExecutorHandler() + "] not found.");
                    }
                }
    
            } 
            //.....这里去掉了 我们没分析的glue模式
            // executor block strategy
            //jobThread不为空,说明任务执行中,这个时候可以通过阻塞策略做对应的动作
            //比如说丢弃、覆盖等,具体可以看xxl-job-admin任务的阻塞策略
            if (jobThread != null) {
                ExecutorBlockStrategyEnum blockStrategy = ExecutorBlockStrategyEnum.match(triggerParam.getExecutorBlockStrategy(), null);
                 //执行丢弃后续调度逻辑
                if (ExecutorBlockStrategyEnum.DISCARD_LATER == blockStrategy) {
                    // discard when running
                    if (jobThread.isRunningOrHasQueue()) {
                        return new ReturnT(ReturnT.FAIL_CODE, "block strategy effect:"+ExecutorBlockStrategyEnum.DISCARD_LATER.getTitle());
                    }
                //覆盖之前调度逻辑
                } else if (ExecutorBlockStrategyEnum.COVER_EARLY == blockStrategy) {
                    // kill running jobThread
                    if (jobThread.isRunningOrHasQueue()) {
                        removeOldReason = "block strategy effect:" + ExecutorBlockStrategyEnum.COVER_EARLY.getTitle();
    
                        jobThread = null;
                    }
                } else {
                    // just queue trigger
                }
            }
            //如果是第一次执行,那么就新建一个jobThread,并start(),并放入XxlJobExecutor.jobThreadRepository中
            // replace thread (new or exists invalid)
            if (jobThread == null) {
                jobThread = XxlJobExecutor.registJobThread(triggerParam.getJobId(), jobHandler, removeOldReason);
            }
    
            // push data to queue
            //放入执行队列,实现快速的吞吐
            ReturnT pushResult = jobThread.pushTriggerQueue(triggerParam);
            return pushResult;
        }

    10、由于开启了JobThread,所以最后处理逻辑就来到了JobThread的run()中,会一直检查一次队列中是否有待执行任务

    public void run() {
    
        	// init
        	try {
                //IJobHandler#init()方法,这里我们没用到
    			handler.init();
    		} catch (Throwable e) {
        		logger.error(e.getMessage(), e);
    		}
    
    		// execute
    		while(!toStop){
    			running = false;
                //等待时间
    			idleTimes++;
    
                TriggerParam triggerParam = null;
                ReturnT executeResult = null;
                try {
    				// to check toStop signal, we need cycle, so wo cannot use queue.take(), instand of poll(timeout)
                    //从触发队列中获取待触发任务,3秒超时
    				triggerParam = triggerQueue.poll(3L, TimeUnit.SECONDS);
    				if (triggerParam!=null) {
    					running = true;
    					idleTimes = 0;
    					triggerLogIdSet.remove(triggerParam.getLogId());
    
    					// log filename, like "logPath/yyyy-MM-dd/9999.log"
    					String logFileName = XxlJobFileAppender.makeLogFileName(new Date(triggerParam.getLogDateTim()), triggerParam.getLogId());
    					XxlJobFileAppender.contextHolder.set(logFileName);
                        //设置分片信息
    					ShardingUtil.setShardingVo(new ShardingUtil.ShardingVO(triggerParam.getBroadcastIndex(), triggerParam.getBroadcastTotal()));
    
    					// execute
    					XxlJobLogger.log("
    ----------- xxl-job job execute start -----------
    ----------- Param:" + triggerParam.getExecutorParams()); //判断是否有执行超时的设置 if (triggerParam.getExecutorTimeout() > 0) { // limit timeout Thread futureThread = null; try { final TriggerParam triggerParamTmp = triggerParam; //有的话则通过futurnTask去做,jdk8做有类似做法的还有CompletableFuture.supplyAsync(()->{ }).get() FutureTask> futureTask = new FutureTask>(new Callable>() { @Override public ReturnT call() throws Exception { //执行IJobHandler#execute 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 { //中断future线程 futureThread.interrupt(); } } else { // just execute //没设置超时,直接执行IJobHandler#execute executeResult = handler.execute(triggerParam.getExecutorParams()); } if (executeResult == null) { executeResult = IJobHandler.FAIL; } XxlJobLogger.log("
    ----------- xxl-job job execute end(finish) -----------
    ----------- ReturnT:" + executeResult); } else { //等待时间不能超过30秒 if (idleTimes > 30) { XxlJobExecutor.removeJobThread(jobId, "excutor idel times over limit."); } } } catch (Throwable e) { if (toStop) { XxlJobLogger.log("
    ----------- JobThread toStop, stopReason:" + stopReason); } StringWriter stringWriter = new StringWriter(); e.printStackTrace(new PrintWriter(stringWriter)); String errorMsg = stringWriter.toString(); executeResult = new ReturnT(ReturnT.FAIL_CODE, errorMsg); XxlJobLogger.log("
    ----------- JobThread Exception:" + errorMsg + "
    ----------- xxl-job job execute end(error) -----------"); } finally { if(triggerParam != null) { // callback handler info if (!toStop) { // 把执行结果放入TriggerCallbackThread中的callBack队列,进行结果回调 TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), triggerParam.getLogDateTim(), executeResult)); } else { // is killed ReturnT stopResult = new ReturnT(ReturnT.FAIL_CODE, stopReason + " [job running,killed]"); TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), triggerParam.getLogDateTim(), stopResult)); } } } } // callback trigger request in queue while(triggerQueue !=null && triggerQueue.size()>0){ TriggerParam triggerParam = triggerQueue.poll(); if (triggerParam!=null) { // is killed ReturnT stopResult = new ReturnT(ReturnT.FAIL_CODE, stopReason + " [job not executed, in the job queue, killed.]"); TriggerCallbackThread.pushCallBack(new HandleCallbackParam(triggerParam.getLogId(), triggerParam.getLogDateTim(), stopResult)); } } // destroy try { handler.destroy(); } catch (Throwable e) { logger.error(e.getMessage(), e); } logger.info(">>>>>>>>>>> xxl-job JobThread stoped, hashCode:{}", Thread.currentThread()); }

    至此、客户端执行器初始化bean与接收rpc请求处理流程简单分析解析

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