dubbo 소스 해석 (3) Dubbo Invoker

9576 단어
전편의dubbo 원본 해석 (2) 에서 에이전트를 만들 때refprotocol을 통과한다고 말했습니다.refer(interfaceClass,urls.get(0)) 먼저 invoker 대상을 만듭니다
Dubbo Protocol의 경우
public  Invoker refer(Class serviceType, URL url) throws RpcException {
        // create rpc invoker.
        DubboInvoker invoker = new DubboInvoker(serviceType, url, getClients(url), invokers);
        invokers.add(invoker);
        return invoker;
    }

refer를 실행하면 DubboInvoker 객체가 반환됩니다.
Dubbo Invoker 이런 거 또 볼게요.
이 클래스는 Abstract Invoker에서 계승되었고 Abstract Invoker라는 클래스는 Invoker 인터페이스를 실현했고 invoke 방법도 실현했다.
방법은 다음과 같습니다.
public Result invoke(Invocation inv) throws RpcException {
        if(destroyed) {
            throw new RpcException("Rpc invoker for service " + this + " on consumer " + NetUtils.getLocalHost() 
                                            + " use dubbo version " + Version.getVersion()
                                            + " is DESTROYED, can not be invoked any more!");
        }
        RpcInvocation invocation = (RpcInvocation) inv;
        invocation.setInvoker(this);
        if (attachment != null && attachment.size() > 0) {
            invocation.addAttachmentsIfAbsent(attachment);
        }
        Map context = RpcContext.getContext().getAttachments();
        if (context != null) {
            invocation.addAttachmentsIfAbsent(context);
        }
        if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)){
            invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
        }
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
        
        
        try {
            return doInvoke(invocation);
        } catch (InvocationTargetException e) { // biz exception
            Throwable te = e.getTargetException();
            if (te == null) {
                return new RpcResult(e);
            } else {
                if (te instanceof RpcException) {
                    ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
                }
                return new RpcResult(te);
            }
        } catch (RpcException e) {
            if (e.isBiz()) {
                return new RpcResult(e);
            } else {
                throw e;
            }
        } catch (Throwable e) {
            return new RpcResult(e);
        }
    }

주로 세 가지 일을 했어요.
1. 일부 초기화 작업을 했다
2. 추상적인 방법doInvoke를 호출했다(하위 클래스에서 실현됨)
3. DoInvoke 방법의 이상을 포착하여 결과를 되돌려줍니다
이어서 Dubbo Invoker의 DoInvoke 방법을 보도록 하겠습니다.
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) {
                ResponseFuture future = currentClient.request(inv, timeout) ;
                RpcContext.getContext().setFuture(new FutureAdapter(future));
                return new RpcResult();
            } else {
                RpcContext.getContext().setFuture(null);
                return (Result) currentClient.request(inv, timeout).get();
            }
        } catch (TimeoutException e) {
            throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        } catch (RemotingException e) {
            throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }

원격과 상호작용하는 클라이언트를 판단하는 데 한 개라면 직접 사용하고 여러 개면 교대로 훈련한다
인터페이스가 일방적인 것으로 판단되면 원격으로 요청send()를 보내고, 그렇지 않으면 비동기적인 것으로 판단되며, 비동기적인 호출이면future를context에 넣고, 동기화되면 인터페이스가 실행된 후에 get결과를 내보냅니다.
 
전재 대상:https://www.cnblogs.com/liguangming/p/9929027.html

좋은 웹페이지 즐겨찾기