服务暴露那点事

在初始化server的注册解析器时,不是封装到xxxConfig中,而是调用servceBean方法

@Override
public void init() {
    registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
    registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
    registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
}

ServiceBean实现了InitializingBean,ApplicationListener两个接口
InitializingBean在容器启动后完成初始化
ApplicationListener在容器创建完调用ContextRefreshedEvent回调函数
主要的两个核心方法

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware,
 ApplicationListener<ContextRefreshedEvent>, BeanNameAware {
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (isDelay() && !isExported() && !isUnexported()) {
            if (logger.isInfoEnabled()) {
                logger.info("The service ready on spring started. service: " + getInterface());
            }
            export();
        }
    }
    
    @Override
    @SuppressWarnings({"unchecked", "deprecation"})
    public void afterPropertiesSet() throws Exception {
        //属性设置
        ...
    }
}

先执行afterPropertiesSet(属性设置),将一些信息保存到ServiceBean中

容器刷新完成后

ServiceConfig.class
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
    if (isDelay() && !isExported() && !isUnexported()) {
        if (logger.isInfoEnabled()) {
            logger.info("The service ready on spring started. service: " + getInterface());
        }
        //执行服务暴露
        export();
    }
}

暴露服务时,先传入路径(数组类型)

ServiceConfig.class
@SuppressWarnings({"unchecked", "rawtypes"})
private void doExportUrls() {
    List<URL> registryURLs = loadRegistries(true);
    for (ProtocolConfig protocolConfig : protocols) {
        doExportUrlsFor1Protocol(protocolConfig, registryURLs);
    }
}

代理工厂先对路径等信息进行包装
再获取协议进行包装
ServiceConfig.class
    //获取Invoker
    private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
    Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
    DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
    
    Exporter<?> exporter = protocol.export(wrapperInvoker);
    exporters.add(exporter);
}

protocol,先注册protocol, 再判断使用什么协议,调用相关方法开启协议

RegistryProtocol.class

public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
    //export invoker  判断Protocol类型委托XXXProtocol使用netty(或其他)暴露
    final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);

    URL registryUrl = getRegistryUrl(originInvoker);

    //registry provider
    final Registry registry = getRegistry(originInvoker);
    //获取到注册提供者的地址
    final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);

    //to judge to delay publish whether or not
    boolean register = registedProviderUrl.getParameter("register", true);
    //将提供者的信息,注册到表中
    ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registedProviderUrl);
key为端口号, value为执行者的包装
public class ProviderConsumerRegTable {
    public static ConcurrentHashMap<String, Set<ProviderInvokerWrapper>> providerInvokers = new ConcurrentHashMap<String, Set<ProviderInvokerWrapper>>();
    public static ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>> consumerInvokers = new ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>>();
DubboProtocol 将服务进行暴露
public class DubboProtocol extends AbstractProtocol {
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
       ...
       //打开服务器
        openServer(url);
        optimizeSerialization(url);
        return exporter;
    }
    
    private void openServer(URL url) {
        // find server.
        String key = url.getAddress();
        //client can export a service which's only for server to invoke
        boolean isServer = url.getParameter(Constants.IS_SERVER_KEY, true);
        if (isServer) {
            ExchangeServer server = serverMap.get(key);
            if (server == null) {
                //创建服务器
                serverMap.put(key, createServer(url));
            } else {
                // server supports reset, use together with override
                server.reset(url);
            }
        }
    }
    
    private ExchangeServer createServer(URL url) {
        ...
        ExchangeServer server;
        try {
            //将服务器与当前ip地址进行绑定(传输层的绑定)
            server = Exchangers.bind(url, requestHandler);
        } catch (RemotingException e) {
            throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
        }
        ...
        return server;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值