xxl-job定時任務框架原理分析(二)

xxl-job執行器源碼分享

執行器的分類

xxl-job一共定義了5種類型的執行器,這裏放個截圖
xxl-job執行器
這裏我們挑選springboot項目來進行分析。

源碼分析

  • 既然是boot項目,那麼首先肯定是找執行類:XxlJobExecutorApplication,這是個簡單的啓動類。
public static void main(String[] args) {
     SpringApplication.run(XxlJobExecutorApplication.class, args);
}
  • 之後會進入配置類:XxlJobConfig,這裏會讀取resources/application.properties的配置信息,然後執行xxlJobExecutor()方法,貼下代碼。
@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;
    }
  • 這裏可以看到接下來就會調用XxlJobSpringExecutorstart()方法,OK,讓我們在來看看他做了什麼。
@Override
public void start() throws Exception {

    // 註冊所有的jobHandler
    initJobHandlerRepository(applicationContext);

    // 不是很重要,就是註冊個工程
    GlueFactory.refreshInstance(1);

    // 調用父類的start方法
    super.start();
}
  • 父類也就是XxlJobExecutorstart()方法執行,我們在來看看。
public void start() throws Exception {

        // 初始化日誌路徑
        XxlJobFileAppender.initLogPath(logPath);

        // 初始化調度中心的本地列表
        initAdminBizList(adminAddresses, accessToken);

        // 日誌清除線程
        JobLogFileCleanThread.getInstance().start(logRetentionDays);

        // 回調線程開啓
        TriggerCallbackThread.getInstance().start();
        port = port>0?port: NetUtil.findAvailablePort(9999);
        ip = (ip!=null&&ip.trim().length()>0)?ip: IpUtil.getIp();
        // 初始化服務器
        initRpcProvider(ip, port, appName, accessToken);
    }
  • 這裏需要關注的是initAdminBizList()initRpcProvider(),那麼同樣看代碼。
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) {

                    String addressUrl = address.concat(AdminBiz.MAPPING);

                    AdminBiz adminBiz = (AdminBiz) new XxlRpcReferenceBean(
                            NetEnum.JETTY,
                            Serializer.SerializeEnum.HESSIAN.getSerializer(),
                            CallType.SYNC,
                            LoadBalance.ROUND,
                            AdminBiz.class,
                            null,
                            10000,
                            addressUrl,
                            accessToken,
                            null,
                            null
                    ).getObject();

                    if (adminBizList == null) {
                        adminBizList = new ArrayList<AdminBiz>();
                    }
                    adminBizList.add(adminBiz);
                }
            }
        }
    }

這裏主要意思就是得到AdminBiz代理並放入到adminBizList集合中,獲取代理的方法是getObject(),然後接着看,接下來就是完成向任務調度中心發送請求進行服務註冊操作,我們主要看如何發起請求的代碼。

client.asyncSend(finalAddress, xxlRpcRequest);

在這裏插入圖片描述
這裏會有三種實現,xxl-job默認採用JettyClient,繼續追蹤會發現其實就是封裝了一個Request請求,然後向註冊中心發送。這樣註冊流程就完成了。

  • 接下來該看看initRpcProvider()方法,那這個方法做了什麼呢?想必看名字也大概知道了,沒錯,就是啓動一個web服務,供之後調度中心的分發任務,看代碼。
private void initRpcProvider(String ip, int port, String appName, String accessToken) throws Exception {

        // 初始化服務註冊工廠
        String address = IpUtil.getIpPort(ip, port);
        Map<String, String> serviceRegistryParam = new HashMap<String, String>();
        serviceRegistryParam.put("appName", appName);
        serviceRegistryParam.put("address", address);

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

        // 添加服務
        xxlRpcProviderFactory.addService(ExecutorBiz.class.getName(), null, new ExecutorBizImpl());

        // 啓動一個web服務
        xxlRpcProviderFactory.start();

    }
  • 在進入start()方法。
public void start() throws Exception {
		// start server
		serviceAddress = IpUtil.getIpPort(this.ip, port);
		server = netType.serverClass.newInstance();
		server.setStartedCallback(new BaseCallback() {		// serviceRegistry started
			@Override
			public void run() throws Exception {
				// start registry
				if (serviceRegistryClass != null) {
					serviceRegistry = serviceRegistryClass.newInstance();
					serviceRegistry.start(serviceRegistryParam);
					if (serviceData.size() > 0) {
						serviceRegistry.registry(serviceData.keySet(), serviceAddress);
					}
				}
			}
		});
		server.setStopedCallback(new BaseCallback() {		// serviceRegistry stoped
			@Override
			public void run() {
				// stop registry
				if (serviceRegistry != null) {
					if (serviceData.size() > 0) {
						serviceRegistry.remove(serviceData.keySet(), serviceAddress);
					}
					serviceRegistry.stop();
					serviceRegistry = null;
				}
			}
		});
		//前面就是一些地址,回調的設置,這裏就是啓動了一個jetty服務
		server.start(this);
	}
  • 至此,執行器的任務基本完成,來總結下,執行器啓動後,首先會向註冊中心註冊自身,然後自己會啓動一個jetty服務供之後的註冊中心來分發任務。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章