dubbo源码分析-dubboProtocol

本文深入分析了dubboProtocol在dubbo框架中的关键作用,包括服务的暴露(export)和引用(refer)过程。export方法通过生成serviceKey并缓存,然后启动socket服务器来实现服务暴露。服务端还需向注册中心注册服务。客户端则通过createProxy和refer方法进行服务引用。整个流程涵盖了服务端接收请求和服务发现的完整步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

dubboProtocol是dubbo中的核心类,具体实现了暴露服务和引用服务。也就是export方法。

 public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        URL url = invoker.getUrl();
        
        // export service.
        String key = serviceKey(url);
        DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
        exporterMap.put(key, exporter);
        // .....
        openServer(url);
        
        return exporter;
    }

export的方法很简单,上面只保留了核心代码,可以看到首先根据url生成serviceKey,也就是这个invoker的唯一标识,然后放到exportMap中缓存起来。openServer会启动一个socket服务(默认监听20880端口),里面最终会调用createServer方法:

private ExchangeServer createServer(URL url) {
        //....
        ExchangeServer server;
        try {
            server = Exchangers.bind(url, requestHandler);
        } catch (RemotingException e) {
            throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
        }
        // ....
        return server;
    }
可以看到server里面放置了一个requestHandler,来处理所有的请求,其实这个handler也是一个dispatcher:

public Object reply(ExchangeChannel channel, Object message) throws RemotingException {
            if (message instanceof Invocation) {
                Invocation inv = (Invocation) message;
                Invoker<?> invoker = getInvoker(channel, inv);
                // ....
                RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
                return invoker.invoke(inv);
            }
            throw new RemotingException(channel, "Unsupported request: " + message == null ? null : (message.getClass().getName() + ": " + message) + ", channel: consumer: " + channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress());
        }
reply就是requestHanlder的核心方法,getInvoker会计算inv的serviceKey,然后从exporter缓存中找到exporter,进而拿到invoker,调用后返回结果。

export方法执行完成后就标志服务端可以接收客户端的请求了,但是还需要向注册中心注册:

public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
        //export invoker
        final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
        //registry provider
        final Registry registry = getRegistry(originInvoker);
        final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
        registry.register(registedProviderUrl);
        // .....
    }
这是RegistryProtocol的export方法,可以看到调用getRegistry拿到Registry后,其实Registry是一个代理,调用了远程服务Registry的register方法完成注册。

ok,这就是服务端暴露服务的过程。

再来看客户端引用的过程:从下图中可以看到客户端在通过getBean方法最终会调用createProxy,然后是refer方法:



private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
        RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
        directory.setRegistry(registry);
        directory.setProtocol(protocol);
        URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, NetUtils.getLocalHost(), 0, type.getName(), directory.getUrl().getParameters());
        if (! Constants.ANY_VALUE.equals(url.getServiceInterface())
                && url.getParameter(Constants.REGISTER_KEY, true)) {
            registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
                    Constants.CHECK_KEY, String.valueOf(false)));
        }
        directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY, 
                Constants.PROVIDERS_CATEGORY 
                + "," + Constants.CONFIGURATORS_CATEGORY 
                + "," + Constants.ROUTERS_CATEGORY));
        return cluster.join(directory);
    }
这是RegistryProtocol的doRefer方法,可以看到是向Registry请求感兴趣的服务地址,Registry返回的每一个url都会被dubboProtocol使用refer封装成一个invoker,最后RegistryProtocol使用cluster把所有的invoker封装成一个invoker(加入了负载均衡的逻辑),也就是代理。

ok,这就是服务暴漏,服务注册,服务发现,服务调用的所有过程了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值