RpcContext内部有一个ThreadLocal变量,它是作为ThreadLocalMap的key,表明每个线程有一个RpcContext。
public class RpcContext { private static final ThreadLocal<RpcContext> LOCAL = new ThreadLocal<RpcContext>() { @Override protected RpcContext initialValue() { return new RpcContext(); } }; //如果get在set之前,则get会返回initialValue()创建的对象 public static RpcContext getContext() { return LOCAL.get(); } }
1. RpcContext的一种用法是:存放Future。Future封装了consumer的请求和响应,发送请求时会创建Future对象,此时响应是null,而DubboClientHandler线程会设置响应值。
设置调用方式为异步:
<dubbo:service interface="com.zhang.HelloService" ref="helloServiceImpl" protocol="dubbo"> <dubbo:method name="sayHello" retries="0" async="true"></dubbo:method> </dubbo:service>
RpcContext设置Future:
//DubboInvoker protected Result doInvoke(final Invocation invocation) throws Throwable { RpcInvocation inv = (RpcInvocation) invocation; final String methodName = RpcUtils.getMethodName(invocation); inv.setAttachment(Constants.PATH_KEY, getUrl().getPath()); inv.setAttachment(Constants.VERSION_KEY, version); ExchangeClient currentClient; if (clients.length == 1) { currentClient = clients[0]; } else { currentClient = clients[index.getAndIncrement() % clients.length]; } try { boolean isAsync = RpcUtils.isAsync(getUrl(), invocation); boolean isOneway = RpcUtils.isOneway(getUrl(), invocation); int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY,
Constants.DEFAULT_TIMEOUT); if (isOneway) { boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false); currentClient.send(inv, isSent); RpcContext.getContext().setFuture(null); return new RpcResult(); } else if (isAsync) { //异步调用,设置Future ResponseFuture future = currentClient.request(inv, timeout) ; RpcContext.getContext().setFuture(new FutureAdapter<Object>(future)); return new RpcResult(); } else { RpcContext.getContext().setFuture(null); return (Result) currentClient.request(inv, timeout).get(); } } catch (TimeoutException e) { } catch (RemotingException e) { } }
调用时直接返回:
HelloService helloService = (HelloService) appCtx.getBean("hello"); //返回null String str = helloService.sayHello(); Future<String> future = RpcContext.getContext().getFuture(); //阻塞获取结果 String str2 = future.get();