`
ahua186186
  • 浏览: 562006 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

summercool-hsf &Netty3.X总结5--客户端异步调用service API

 
阅读更多
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-hsf:自动从code.google.compsummercool-hsf导出

    笔者工作的这几年之中,总结并开发了如下几个框架: summercool(Web 框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、 summercool-...

    summercool-hsf:从 code.google.compsummercool-hsf 自动导出

    summercool-hsf Automatically exported from code.google.com/p/summercool-hsf 1.目前为止性能最高的RPC远程通讯框架 2.也可以做为手机长连接的Server,经测试已经达到了50W以上的性能长连接 (需调整linux内核...

    summercool-ddl:从 code.google.compsummercool-ddl 自动导出

    summercool-ddlAutomatically exported from code.google.com/p/summercool-ddl1.依赖Xml代码 收藏代码org.summercoolsummercool-ddl1.0源码svn地址:2.准备Sql映射文件Xml代码 收藏...3.Spring配置Xml代码 收藏代码

    summercool-ddl:自动从code.google.compsummercool-ddl导出

    summercool-ddl Automatically exported from code.google.com/p/summercool-ddl 学习了解使用!

    summercool:从 code.google.compsummercool 自动导出

    笔者工作的这几年之中,总结并开发了如下几个框架: summercool( Web框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、summercool-...

    Ibatis之分表分库解决方案

    3. **分布式事务**:分库分表后,跨表操作可能会涉及多个数据库,这时就需要解决分布式事务的问题。Ibatis不提供内置的分布式事务管理,但可以通过其他开源框架如Seata(原名:TCC)来实现。 4. **数据一致性**:...

Global site tag (gtag.js) - Google Analytics