1.异步调用:
核心原理:利用JDK的动态代理类创建service代理对象,然后在InvocationHandler中调用channel发送数据, 同时在客户端维护一个回调对象callback集合或InvokeFuture对象集合,方便客户端接收消息的时候异步回调。
核心本质我的理解就是 futrue模式(本质就是setResult(),getResult()) + callback模式(本质就是个监听器对象)
相关核心代码:
创建代理:
/**
* @Title: wrapAsyncProxy4Service
* @Description: 为远程服务创建异步动态代理,返回代理对象
* @author 简道
* @param serviceInterface
* 远程服务接口
* @param asyncType
* 异步类型
* @param callback
* 回调
* @param dispatchStrategy
* 分发策略
* @return T 返回类型
*/
@SuppressWarnings("unchecked")
private static <T> T wrapAsyncProxy4Service(Class<T> serviceInterface, AsyncType asyncType,
AsyncCallback<?> callback, AsyncDispatchStrategy dispatchStrategy) {
if (serviceInterface == null) {
throw new IllegalArgumentException("serviceInterface can not be null.");
} else if (!serviceInterface.isInterface()) {
throw new IllegalArgumentException("serviceInterface is required to be interface.");
} else if (dispatchStrategy == null) {
throw new IllegalArgumentException("dispatchStrategy can not be null.");
}
InvocationHandler requestHandler = new AsyncServiceRequestHandler(serviceInterface.getSimpleName(), asyncType,
callback, dispatchStrategy);
// 创建代理
T serviceProxy = (T) Proxy.newProxyInstance(getClassLoader(serviceInterface), new Class[] { serviceInterface },
requestHandler);
return serviceProxy;
}
异步请求处理:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
RemoteServiceObject remoteServiceObject = new RemoteServiceObject();
remoteServiceObject.setMethodName(method.getName());
remoteServiceObject.setServiceName(serviceName);
remoteServiceObject.setArgs(args);
InvokeResult result;
if (AsyncType.Callback.equals(asyncType)) {
result = dispatchStrategy.dispatch(remoteServiceObject, callback);
} else {
result = dispatchStrategy.dispatch(remoteServiceObject, asyncType);
}
if (result != null && result.size() == 1) {
Object retObj = result.getFirstValue();
TLSUtil.setData(InvokeFuture.class, retObj);
} else if (AsyncType.Future.equals(asyncType)) {
MultiInvokeFuture multiInvokeFuture = new MultiInvokeFuture();
Set<Object> keySet = result.keySet();
for (Object groupName : keySet) {
multiInvokeFuture.addFuture((InvokeFuture) result.get(groupName));
}
TLSUtil.setData(InvokeFuture.class, multiInvokeFuture);
}
return ReflectionUtil.getDefaultValue(method.getReturnType());
}
消息分发:
@Override
public InvokeResult dispatch(Object message, AsyncType asyncType) {
if (message == null) {
throw new IllegalArgumentException("Message can not be null.");
} else if (!service.isAlived()) {
throw new IllegalStateException("service is not alived.");
} else if (AsyncType.Callback.equals(asyncType)) {
throw new IllegalArgumentException("only support AsyncType.None and AsyncType.Future.");
}
// 默认为None
if (asyncType == null) {
asyncType = AsyncType.Default;
}
InvokeResult invokeResult = new InvokeResult();
HsfChannel channel = getChannel(service.getGroups());
switch (asyncType) {
case Default:
invokeResult.put(((HsfChannel) channel).getChannelGroup().getName(), channel.write(message));
break;
case Future:
invokeResult.put(channel.getChannelGroup().getName(), channel.writeAsync(message));
break;
}
return invokeResult;
}
HsfChannel write并保存维护callback对象:
public void writeAsync(Object msg, final AsyncCallback<?> callback) {
// 创建Request对象
RequestObject request = new RequestObject();
final long seq = getSeq();
request.setSeq(seq);
request.setTarget(msg);
//
if (callback != null) {
// 流量控制
flowAcquire();
try {
// 存储callback
callbacks.put(seq, callback);
//
Object param = getCallbackMessage(msg);
if (param != null && LangUtil.parseBoolean(service.getOption(HsfOptions.HOLD_CALLBACK_PARAM), false)) {
// 存储参数,缓存Callback方式发送的消息,缓存后将会在发送失败时回调doException方法参数传入, default is false
cbParamMap.put(seq, param);
}
// 发送Request对象
ChannelFuture channelFuture = write(request);
channelFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {//异常处理
callbacks.remove(seq);
//
Object m = cbParamMap.remove(seq);
try {
CallbackRegister.setCallbackParam(m);
//
callback.doExceptionCaught(future.getCause(), HsfChannel.this, m);
} catch (Exception e) {
logger.error(StackTraceUtil.getStackTrace(e));
} finally {
CallbackRegister.clearCallbackParam();
}
}
}
});
} catch (Throwable e) {
// 释放流量
flowRelease();
}
} else {
// no callback
request.setNeedCallback(false);
//
write(msg);
}
}
读取响应消息并回调:
@SuppressWarnings({ "rawtypes", "unchecked" })
private void processResponse(ChannelHandlerContext ctx, ResponseObject response, HsfChannel channel) {
// 处理Seq为-1的异常信息
if (response.getSeq() == -1) {
if (response.getCause() != null) {
ctx.sendUpstream(new DefaultExceptionEvent(channel, response.getCause()));
}
return;
}
// Future方式
InvokeFuture future = channel.getFutures().remove(response.getSeq());
if (future != null) {
if (response.getCause() != null) {
future.setCause(response.getCause());
} else {
future.setResult(response.getTarget());
}
// 释放流量
flowRelease(channel);
}
// Callback方式
AsyncCallback callback = channel.getCallbacks().remove(response.getSeq());
if (callback != null) {
//
Object param = channel.getCallbackParamMap().remove(response.getSeq());
try {
CallbackRegister.setCallbackParam(param);
//
if (response.getCause() != null) {
callback.doExceptionCaught(response.getCause(), channel, null);
} else {
callback.doCallback(response.getTarget());
}
} catch (Throwable ex) {
logger.error(StackTraceUtil.getStackTrace(ex));
} finally {
// 释放流量
flowRelease(channel);
//
CallbackRegister.clearCallbackParam();
}
}
}
分享到:
相关推荐
笔者工作的这几年之中,总结并开发了如下几个框架: summercool(Web 框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、 summercool-...
summercool-hsf Automatically exported from code.google.com/p/summercool-hsf 1.目前为止性能最高的RPC远程通讯框架 2.也可以做为手机长连接的Server,经测试已经达到了50W以上的性能长连接 (需调整linux内核...
summercool-ddlAutomatically exported from code.google.com/p/summercool-ddl1.依赖Xml代码 收藏代码org.summercoolsummercool-ddl1.0源码svn地址:2.准备Sql映射文件Xml代码 收藏...3.Spring配置Xml代码 收藏代码
summercool-ddl Automatically exported from code.google.com/p/summercool-ddl 学习了解使用!
笔者工作的这几年之中,总结并开发了如下几个框架: summercool( Web框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、summercool-...
3. **分布式事务**:分库分表后,跨表操作可能会涉及多个数据库,这时就需要解决分布式事务的问题。Ibatis不提供内置的分布式事务管理,但可以通过其他开源框架如Seata(原名:TCC)来实现。 4. **数据一致性**:...