首页 > 代码库 > motan服务启动

motan服务启动

motan(https://github.com/weibocom/motan.git)是微博开源出来的一款轻量级RPC框架,结合Spring食用,配置简单易上手。之前搞过facebook开源的thrift框架,thrift虽然支持众多语言,但像服务注册与发现、负载均衡这些重要的功能都没有提供,自己实现的费时费力又不稳定,最总还是放弃了。

这次说说motan的启动:

先说一下Spring的BeanPostProcessor接口,该接口中定义了两个方法:

public interface BeanPostProcessor {

    /**
     * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
     * initialization callbacks (like InitializingBean‘s {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one;
     * if {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
     * initialization callbacks (like InitializingBean‘s {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
     * instance and the objects created by the FactoryBean (as of Spring 2.0). The
     * post-processor can decide whether to apply to either the FactoryBean or created
     * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
     * <p>This callback will also be invoked after a short-circuiting triggered by a
     * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
     * in contrast to all other BeanPostProcessor callbacks.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one;
     * if {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     * @see org.springframework.beans.factory.FactoryBean
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
postProcessBeforeInitialization在实例化及依赖注入完成后、在任何初始化代码调用之前调用;postProcessAfterInitialization在初始化代码调用之后调用。
motan的com.weibo.api.motan.config.springsupport.AnnotationBean类实现了BeanPostProcessor接口,并且在postProcessAfterInitialization方法中完成了rpc服务的配置与启动:
    /**
     * init service config and export servcice
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (!isMatchPackage(bean)) {
            return bean;
        }
        Class<?> clazz = bean.getClass();
        if (isProxyBean(bean)) {
            clazz = AopUtils.getTargetClass(bean);
        }
        MotanService service = clazz.getAnnotation(MotanService.class);
        if (service != null) {
            ServiceConfigBean<Object> serviceConfig = new ServiceConfigBean<Object>();
            if (void.class.equals(service.interfaceClass())) {
                if (clazz.getInterfaces().length > 0) {
                    Class<Object> clz = (Class<Object>) clazz.getInterfaces()[0];
                    serviceConfig.setInterface(clz);
                } else {
                    throw new IllegalStateException("Failed to export remote service class " + clazz.getName()
                            + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces.");
                }
            } else {
                serviceConfig.setInterface((Class<Object>) service.interfaceClass());
            }
            if (beanFactory != null) {

                serviceConfig.setBeanFactory(beanFactory);

                if (service.basicService() != null && service.basicService().length() > 0) {
                    serviceConfig.setBasicService(beanFactory.getBean(service.basicService(), BasicServiceInterfaceConfig.class));
                }

                if (service.export() != null && service.export().length() > 0) {
                    serviceConfig.setExport(service.export());
                }

                if (service.host() != null && service.host().length() > 0) {
                    serviceConfig.setHost(service.host());
                }

                String protocolValue = null;
                if (service.protocol() != null && service.protocol().length() > 0) {
                    protocolValue = service.protocol();
                } else if (service.export() != null && service.export().length() > 0) {
                    protocolValue = ConfigUtil.extractProtocols(service.export());
                }

                if (!StringUtils.isBlank(protocolValue)) {
                    List<ProtocolConfig> protocolConfigs = SpringBeanUtil.getMultiBeans(beanFactory, protocolValue, SpringBeanUtil.COMMA_SPLIT_PATTERN,
                            ProtocolConfig.class);
                    serviceConfig.setProtocols(protocolConfigs);
                }

//                String[] methods() default {};

                if (service.registry() != null && service.registry().length() > 0) {
                    List<RegistryConfig> registryConfigs = SpringBeanUtil.getMultiBeans(beanFactory, service.registry
                            (), SpringBeanUtil.COMMA_SPLIT_PATTERN, RegistryConfig.class);
                    serviceConfig.setRegistries(registryConfigs);
                }

                if (service.extConfig() != null && service.extConfig().length() > 0) {
                    serviceConfig.setExtConfig(beanFactory.getBean(service.extConfig(), ExtConfig.class));
                }

                if (service.application() != null && service.application().length() > 0) {
                    serviceConfig.setApplication(service.application());
                }
                if (service.module() != null && service.module().length() > 0) {
                    serviceConfig.setModule(service.module());
                }
                if (service.group() != null && service.group().length() > 0) {
                    serviceConfig.setGroup(service.group());
                }

                if (service.version() != null && service.version().length() > 0) {
                    serviceConfig.setVersion(service.version());
                }

                if (service.proxy() != null && service.proxy().length() > 0) {
                    serviceConfig.setProxy(service.proxy());
                }

                if (service.filter() != null && service.filter().length() > 0) {
                    serviceConfig.setFilter(service.filter());
                }


                if (service.actives() > 0) {
                    serviceConfig.setActives(service.actives());
                }

                if(service.async()) {
                    serviceConfig.setAsync(service.async());
                }

                if (service.mock() != null && service.mock().length() > 0) {
                    serviceConfig.setMock(service.mock());
                }


                // 是否共享 channel
                if (service.shareChannel()) {
                    serviceConfig.setShareChannel(service.shareChannel());
                }

                // if throw exception when call failure,the default value is ture
                if (service.throwException()) {
                    serviceConfig.setThrowException(service.throwException());
                }
                if(service.requestTimeout()>0) {
                    serviceConfig.setRequestTimeout(service.requestTimeout());
                }
                if (service.register()) {
                    serviceConfig.setRegister(service.register());
                }
                if (service.accessLog()) {
                    serviceConfig.setAccessLog("true");
                }
                if (service.check()) {
                    serviceConfig.setCheck("true");
                }
                if (service.usegz()) {
                    serviceConfig.setUsegz(service.usegz());
                }

                if(service.retries()>0) {
                    serviceConfig.setRetries(service.retries());
                }

                if(service.mingzSize()>0) {
                    serviceConfig.setMingzSize(service.mingzSize());
                }

                if (service.codec() != null && service.codec().length() > 0) {
                    serviceConfig.setCodec(service.codec());
                }

                try {
                    serviceConfig.afterPropertiesSet();
                } catch (RuntimeException e) {
                    throw (RuntimeException) e;
                } catch (Exception e) {
                    throw new IllegalStateException(e.getMessage(), e);
                }
            }
            serviceConfig.setRef(bean);
            serviceConfigs.add(serviceConfig);
            serviceConfig.export();
        }
        return bean;
    }

 postProcessAfterInitialization先是检查当前bean是否是一个rpc服务,如果是就去加载各种配置,最后调用serviceConfig.export(),完成服务的启动。

serviceConfig.export()最终调用com.weibo.api.motan.registry.zookeeper.ZookeeperRegistry.doAvailable(URL)方法,在注册中心上添加一个节点,将该服务的地址暴露出去(motan目前支持两种注册中心,Consul和Zookeeper)。

服务并不会在启动完成之后马上注册到注册中心,motan设置了一个全局的开关,只有通过SwitcherService打开开关,服务才会进行注册

//执行该语句后,服务才会被注册到注册中心,才能对外提供服务
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);

 

motan服务启动