motan服务启动
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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服务启动的主要内容,如果未能解决你的问题,请参考以下文章