抓到 Dubbo 异步调用的小 Bug,再送你一个贡献开源代码的机会
The following article is from 捉虫大师 Author 小楼MrRoshi
最近一个同学说遇到了一个 Dubbo 异步调用的问题,怀疑是个 Bug。提到 Bug 我可就不困了,说不定可以水,哦不...写一篇文章。
问题复现
接口返回类型是 boolean; 同步改为异步调用,返回的 boolean 和预期不符合; boolean 基本类型改成包装类型 Boolean 就能正常返回。
public interface DemoService { boolean isUser(); Boolean isFood();}@Servicepublic class DemoServiceImpl implements DemoService {
@Override public boolean isUser() { System.out.println("server is user : true"); return true; }
@Override public Boolean isFood() { System.out.println("server is food : true"); return true; }}@RestControllerpublic class DemoCallerService {
@Reference(injvm = false, check = false) private DemoService demoService;
@GetMapping(path = "/isUser") public String isUser() throws Exception { BlockingQueue<Boolean> q = new ArrayBlockingQueue<>(1); RpcContext.getContext().asyncCall( () -> demoService.isUser() ).handle( (isUser, throwable) -> { System.out.println("client is user = " + isUser); q.add(isUser); return isUser; }); q.take(); return "ok"; }
@GetMapping(path = "/isFood") public String isFood() throws Exception { BlockingQueue<Boolean> q = new ArrayBlockingQueue<>(1); RpcContext.getContext().asyncCall( () -> demoService.isFood() ).handle( (isFood, throwable) -> { System.out.println("client is food = " + isFood); q.add(isFood); return isFood; }); q.take(); return "ok"; }}// client ...client is user = false// server ...server is user : true// client ...client is food = true// server ...server is food : true问题排查
com.alibaba.dubbo.remoting.exchange.support.DefaultFuture#doReceived断点①为了证明我们的请求进来了; 断点②为了证明进了回调; 断点③为了能从接收到数据包的初始位置开始排查。
sc *.proxy0jad org.apache.dubbo.common.bytecode.proxy0//local invoke will return directlyserver is user : trueclient is user = true如何修复
public <T> CompletableFuture<T> asyncCall(Callable<T> callable) { try { try { setAttachment(ASYNC_KEY, Boolean.TRUE.toString()); final T o = callable.call(); //local invoke will return directly if (o != null) { if (o instanceof CompletableFuture) { return (CompletableFuture<T>) o; } if (injvm()) { // 伪代码 return CompletableFuture.completedFuture(o); } } else { // The service has a normal sync method signature, should get future from RpcContext. } } catch (Exception e) { throw new RpcException(e); } finally { removeAttachment(ASYNC_KEY); } } catch (final RpcException e) { // .... } return ((CompletableFuture<T>) getContext().getFuture());}最后
- EOF -
看完本文有收获?请转发分享给更多人
关注「ImportNew」,提升Java技能
点赞和在看就是最大的支持❤️