1. 程式人生 > >XXL-JOB原理--執行器註冊(二)

XXL-JOB原理--執行器註冊(二)

1、xxl-job新增執行器到任務排程中心有兩種方式

(1)客戶端執行器自動將名稱和機器地址註冊到任務排程中心

(2)可以在任務排程中心手動錄入執行器名稱和相關的機器地址(多個機器地址用逗號隔開)

2、自動註冊流程

(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 executor address
##任務排程器名稱和機器資訊
xxl.job.executor.appname=xxl-job-executor-sample
xxl.job.executor.ip=127.0.0.1
xxl.job.executor.port=9998

(2)相關注冊執行程式碼:

在執行器啟動時會讀取配置,當存在任務排程中心地址會依次向任務排程中心註冊其地址

XxlJobExecutor類在進行初始化時會進行如下操作。

//當存在多個任務排程中心時,建立代理類並註冊,在NetComClientProxy
private static 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 NetComClientProxy(AdminBiz.class, addressUrl, accessToken).getObject();
                    if (adminBizList == null) {
                        adminBizList = new ArrayList<AdminBiz>();
                    }
                    adminBizList.add(adminBiz);
                }
            }
        }
    }

在XxlJobExecutor被呼叫時執行getObject方法,完成向任務排程中心傳送請求進行服務註冊操作。

@Override
	public Object getObject() throws Exception {
		return Proxy.newProxyInstance(Thread.currentThread()
				.getContextClassLoader(), new Class[] { iface },
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

						// filter method like "Object.toString()"
						if (Object.class.getName().equals(method.getDeclaringClass().getName())) {
							logger.error(">>>>>>>>>>> xxl-rpc proxy class-method not support [{}.{}]", method.getDeclaringClass().getName(), method.getName());
							throw new RuntimeException("xxl-rpc proxy class-method not support");
						}
						
						// request
						RpcRequest request = new RpcRequest();
	                    request.setServerAddress(serverAddress);
	                    request.setCreateMillisTime(System.currentTimeMillis());
	                    request.setAccessToken(accessToken);
	                    request.setClassName(method.getDeclaringClass().getName());
	                    request.setMethodName(method.getName());
	                    request.setParameterTypes(method.getParameterTypes());
	                    request.setParameters(args);

	                    // send
						//向任務排程中心傳送請求進行服務註冊
	                    RpcResponse response = client.send(request);
	                    
	                    // valid response
						if (response == null) {
							throw new Exception("Network request fail, response not found.");
						}
	                    if (response.isError()) {
	                        throw new RuntimeException(response.getError());
	                    } else {
	                        return response.getResult();
	                    }
	                   
					}
				});

在JettyClient中呼叫send方法完成服務註冊操作

public RpcResponse send(RpcRequest request) throws Exception {
		try {
			// serialize request
			byte[] requestBytes = HessianSerializer.serialize(request);

			// reqURL
			String reqURL = request.getServerAddress();
			if (reqURL!=null && reqURL.toLowerCase().indexOf("http")==-1) {
				reqURL = "http://" + request.getServerAddress() + "/";	// IP:PORT, need parse to url
			}
            //傳送post請求進行服務註冊,簡單註冊一下IP和埠資訊等
			// remote invoke
			byte[] responseBytes = HttpClientUtil.postRequest(reqURL, requestBytes);
			if (responseBytes == null || responseBytes.length==0) {
				RpcResponse rpcResponse = new RpcResponse();
				rpcResponse.setError("Network request fail, RpcResponse byte[] is null");
				return rpcResponse;
            }

            // deserialize response
			RpcResponse rpcResponse = (RpcResponse) HessianSerializer.deserialize(responseBytes, RpcResponse.class);
			return rpcResponse;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);

			RpcResponse rpcResponse = new RpcResponse();
			rpcResponse.setError("Network request error: " + e.getMessage());
			return rpcResponse;
		}
	}

相關注冊資訊如下:

總結:其實執行器註冊到任務排程的資訊非常簡單,可以就簡單的認為為應用的一些基本資訊,IP、埠和應用名稱等等,並不用將具體的任務類等資訊註冊到任務排程中心,所以任務排程中心無法感知執行器一些具體資訊,只能需要靠運維和技術人員在任務排程中心進行選擇配置,否則可能會無法正常執行任務。