微博Motan中的transport模組一些點

tony0087發表於2021-09-09

首先看一段程式碼

nettyClient = new NettyClient(url);
nettyClient.open();
RpcContext.getContext().putAttribute(MotanConstants.ASYNC_SUFFIX, true);
Response response;
try {
    response = nettyClient.request(request);
    Assert.assertTrue(response instanceof ResponseFuture);
    Object result = response.getValue();//獲取返回結果會阻塞
    RpcContext.destroy();
    Assert.assertNotNull(result);
    Assert.assertEquals("method: " + request.getMethodName() + " requestId: " + request.getRequestId(), result);
} catch (MotanServiceException e) {
    e.printStackTrace();
    assertTrue(false);
} catch (Exception e) {
    e.printStackTrace();
    assertTrue(false);
}

主要是建立一個客戶端的連線,傳送請求,然後獲取返回。

nettyClient.open();
open的時候會去建立一個channel的連線池,可以點進去看
所以當呼叫request的時候最終會走到這樣一個方法
private Response request(Request request, boolean async) throws TransportException {
    Channel channel;
    Response response;
    try {
        channel = getChannel();//從連線池獲取channel
        if (channel == null) {
            LoggerUtil.error("NettyClient borrowObject null: url=" + url.getUri() + " " + MotanFrameworkUtil.toString(request));
            return null;
        }
        // async request
        response = channel.request(request);
    } catch (Exception e) {
       
    }
    // aysnc or sync result
    response = asyncResponse(response, async);
    return response;
}

最終發起呼叫是在com.weibo.api.motan.transport.netty4.NettyChannel中的request方法
@Override
public Response request(Request request) throws TransportException {
    int timeout = nettyClient.getUrl().getMethodParameter(request.getMethodName(), request.getParamtersDesc(), URLParamType.requestTimeout.getName(), URLParamType.requestTimeout.getIntValue());
    if (timeout 


當服務端返回資料後會呼叫處理返回的handler

com.weibo.api.motan.transport.netty4.NettyClient中的handler
new MessageHandler() {
    @Override
    public Object handle(Channel channel, Object message) {
        Response response = (Response) message;
        System.out.println("獲取到message");
        ResponseFuture responseFuture = NettyClient.this.removeCallback(response.getRequestId());

        if (responseFuture == null) {
            LoggerUtil.warn("NettyClient has response from server, but responseFuture not exist, requestId={}", response.getRequestId());
            return null;
        }
        if (response.getException() != null) {
            responseFuture.onFailure(response);
        } else {
            responseFuture.onSuccess(response);
        }
        return null;
    }
}

可以看到如果服務端返回了,就會獲取到響應的DefaultResponse
然後將返回結果傳入到之前構建的responseFuture
if (response.getException() != null) {
    responseFuture.onFailure(response);
} else {
    responseFuture.onSuccess(response);
}

onSuccess中會呼叫之前的listener,執行listen回撥方法

關於

DefaultResponseFuture
透過物件鎖protected Object lock = new Object();來保證等待結果的返回


獲取返回結果會阻塞,如果服務端還沒有返回
 Object result = response.getValue();//獲取返回結果會阻塞
 
@Override
public Object getValue() {
    System.out.println("getValue");
    synchronized (lock) {
        if (!isDoing()) {
            return getValueOrThrowable();//如果不是在執行就報錯
        }
        System.out.println("timeout:"+timeout);
        if (timeout  0) {
                for (; ; ) {
                    try {
                        lock.wait(waitTime);
                    } catch (InterruptedException e) {
                    }

                    if (!isDoing()) {
                        break;
                    } else {
                        waitTime = timeout - (System.currentTimeMillis() - createTime);
                        if (waitTime 






來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1747/viewspace-2812489/,如需轉載,請註明出處,否則將追究法律責任。

相關文章