- 调度中心注册
下面我们直接看源码的实现
这是执行器启动的时候的一个动作,上一篇努力的小胖学习记录三-xxl-job已经介绍,这里主要是初始化所有需要的AdminBiz,后期定时发送心跳包和注册就是调用AdminBiz.registry方法,执行器这边获取的AdminBiz是个代理对象,代理的逻辑就在XxlRpcReferenceBean.getObject方法。
public Object getObject() {
return Proxy.newProxyInstance(Thread.currentThread()
.getContextClassLoader(), new Class[] { iface },
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String className = method.getDeclaringClass().getName();
// filter method like "Object.toString()"
if (Object.class.getName().equals(className)) {
logger.info(">>>>>>>>>>> xxl-rpc proxy class-method not support [{}.{}]", className, method.getName());
throw new XxlRpcException("xxl-rpc proxy class-method not support");
}
// address
String address = routeAddress();
if (address==null || address.trim().length()==0) {
throw new XxlRpcException("xxl-rpc reference bean["+ className +"] address empty");
}
// request
XxlRpcRequest xxlRpcRequest = new XxlRpcRequest();
xxlRpcRequest.setRequestId(UUID.randomUUID().toString());
xxlRpcRequest.setCreateMillisTime(System.currentTimeMillis());
xxlRpcRequest.setAccessToken(accessToken);
xxlRpcRequest.setClassName(className);
xxlRpcRequest.setMethodName(method.getName());
xxlRpcRequest.setParameterTypes(method.getParameterTypes());
xxlRpcRequest.setParameters(args);
// send
if (CallType.SYNC == callType) {
try {
// future set
XxlRpcFutureResponse futureResponse = new XxlRpcFutureResponse(xxlRpcRequest, null);
// do invoke
client.asyncSend(address, xxlRpcRequest);
// future get
XxlRpcResponse xxlRpcResponse = futureResponse.get(timeout, TimeUnit.MILLISECONDS);
if (xxlRpcResponse.getErrorMsg() != null) {
throw new XxlRpcException(xxlRpcResponse.getErrorMsg());
}
return xxlRpcResponse.getResult();
} catch (Exception e) {
logger.info(">>>>>>>>>>> xxl-job, invoke error, address:{}, XxlRpcRequest{}", address, xxlRpcRequest);
throw (e instanceof XxlRpcException)?e:new XxlRpcException(e);
} finally{
// remove-InvokerFuture
XxlRpcFutureResponseFactory.removeInvokerFuture(xxlRpcRequest.getRequestId());
}
} else if (CallType.FUTURE == callType) {
// thread future set
XxlRpcInvokeFuture invokeFuture = null;
try {
// future set
invokeFuture = new XxlRpcInvokeFuture(new XxlRpcFutureResponse(xxlRpcRequest, null));
XxlRpcInvokeFuture.setFuture(invokeFuture);
// do invoke
client.asyncSend(address, xxlRpcRequest);
return null;
} catch (Exception e) {
logger.info(">>>>>>>>>>> xxl-job, invoke error, address:{}, XxlRpcRequest{}", address, xxlRpcRequest);
// remove-InvokerFuture
invokeFuture.stop();
throw (e instanceof XxlRpcException)?e:new XxlRpcException(e);
}
} else if (CallType.CALLBACK == callType) {
// get callback
XxlRpcInvokeCallback finalInvokeCallback = invokeCallback;
XxlRpcInvokeCallback threadInvokeCallback = XxlRpcInvokeCallback.getCallback();
if (threadInvokeCallback != null) {
finalInvokeCallback = threadInvokeCallback;
}
if (finalInvokeCallback == null) {
throw new XxlRpcException("xxl-rpc XxlRpcInvokeCallback(CallType="+ CallType.CALLBACK.name() +") cannot be null.");
}
try {
// future set
XxlRpcFutureResponse futureResponse = new XxlRpcFutureResponse(xxlRpcRequest, finalInvokeCallback);
client.asyncSend(address, xxlRpcRequest);
} catch (Exception e) {
logger.info(">>>>>>>>>>> xxl-job, invoke error, address:{}, XxlRpcRequest{}", address, xxlRpcRequest);
// future remove
XxlRpcFutureResponseFactory.removeInvokerFuture(xxlRpcRequest.getRequestId());
throw (e instanceof XxlRpcException)?e:new XxlRpcException(e);
}
return null;
} else if (CallType.ONEWAY == callType) {
client.asyncSend(address, xxlRpcRequest);
return null;
} else {
throw new XxlRpcException("xxl-rpc callType["+ callType +"] invalid");
}
}
});
}
这个就是源码方法,很清楚的看到,这里用的Jdk的动态代理,他对目标方法的调用实际是通过http的方式发送请求,然后将结果拿回并且封装,这里是执行器的处理,我们再看调度中心对应的处理。
这里是直接提供了一个controller去接受http请求,然后通过jettyServerHandler再转交给xxlRpcProviderFactory处理,接下来看XxlRpcProviderFactory.invokeService方法
从这里可以很清楚看到,实际是通过反射调用获取结果然后返回,执行器向调度中心发送心跳和注册就到此结束了。
- rpc实现
RPC实现和上面的向调度中心注册原理是一样的,核心也是XxlRpcReferenceBean,每一个服务消费者都被包装成一个XxlRpcReferenceBean,执行器作为服务提供者只提供一个Service(ExecutorBizImpl),下面看获取的地方
RPC和发送心跳实现方式唯一不同的就是发送心跳的实现是直接使用的Controller实现,但是RPC是使用了现有的框架,像jetty或者netty,他们会自动处理这些HTTP请求,但是本质都是一样