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);
时间: 2024-11-09 05:06:49

motan服务启动的相关文章

react-native服务启动,运行项目到安卓模拟器

1.在CMD中进入要启动的项目下,输入react-native start,等待启动成功.成功之后再浏览器中访问http://localhost:8081/index.android.bundle?platform=android,如果可以访问,表示服务器端启动成功. 2.在上个服务启动的情况下,重新打开一个CMD,进入项目目录下,输入命令react-native run-android运行,第一次运行的时候会下载gradle,时间较长,成功之后,会在android模拟器中安装上,出现Welco

Delphi启动/停止Windows服务,启动类型修改为&quot;自动&quot;

unit U_StartServices; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, WinSVC, StdCtrls; type TForm1 = class(TForm) btn_StartServices: TButton; btn_StopServices: TButton; procedure btn_StartServicesCl

关于.net服务启动注册到zookeeper,但是注册节点20分钟自动消失解决办法

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,作用简单描述就是相当于一个中介,服务提供者将服务注册到zk,服务调用者直接从zk获取,zk的作用就是协调 最近碰到公司iis服务启动了,然后该服务在zk成功注册节点并且provider有了节点,但是超过20分钟没有访问后,发现provider中的节点消失了,请教了开发知道,对于新增的服务器安装iis服务后,原来对于服务的应用程序池需要做3个操作才行. 如图1-1,需要在服务的应用程序池,选择服务-高级设置-禁用重叠回收[True

安装VisualSVN Server 报&quot; Service &#39;VisualSVN Server&#39; failed to start. &quot; 服务启动失败

安装VisualSVN Server 报"Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for more details"错误.原因是启动"VisualSVN Server"失败 2 咱们先来看一下这个服务在哪,计算机-右键-管理或者系统服务-在服务里面可以看到一个"VisualSVN Server"项,状

SQL SERVER 服务启动失败

好久没用SQL SERVER了,今天启动SQL,发现服务启动失败,报错如下:--发生错误 1069-(由于登录失败而无法启动服务.) ,百度一下,解决方案如下: 请按下列步骤操作: 1.右键单击[我的电脑]管理,单击打开[服务和运用程序]中的[服务]: 2.右键单击SQL Server (MSSQLSERVER)服务属性,单击[登录]页签,单击选中"本地系统帐户",选中"允许服务于桌面交互",单击确定,启动服务即可: 上面的方法经过测试,对我来说可行,如有问题,就请

Apache服务启动失败couldn&#39;t start errorlog process, unable to open logs

在某用户环境下,Apache服务启动失败,报错信息如下 couldn't start errorlog process unable to open logs Apache是我们的产品组件,未防止日志过大 我们使用了Apache自带的切割滚存日志的组件rotatelogs.exe 在httpd.conf配置如下: ErrorLog "|bin/rotatelogs.exe logs/%Y%m%d%H%M%S_error.log 30M" 只要屏蔽这个设置,就可以正常启动Apache,谷

交通银行 Java Socket 服务启动 管理 WINDOWS 版

按照交通银行提供的无界面启动方法试验了很多次,都没有成功,所以自己动手用C# 知识写了一个. 小工具可以判断 交通银行 JAVA SOCKET 服务是否启动,并可以启动/关闭服务 主要代码如下: 判断服务是否启动 引用 :using System.Management; SelectQuery selectQuery = new SelectQuery(“select * from Win32_Process where Name = ‘java.exe’”); object cmdLine =

破解windows下MySQL服务启动不了的情况下不能对其进行完全卸载的解决方案

以下的文章主要介绍的是在MySQL服务启动不了的情况下,不能对其进行完全卸载的实际解决办法的描述,以下就是对解决MySQL服务启动不了的情况下具体方案的描述,希望在你今后的学习中会对你有所帮助. MySQL 5.1 安装过程中报apply security setting错误的解决办法 1, 卸载MySQL 2, 删除目录 C:\Documents and Settings\All Users\Application Data\MySQL 3, 重新安装MySQL 就 OK 啦 [MySQL]

shell脚本生成服务演示服务启动、停止过程。

1.编写服务脚本/root/bin/testsrv.sh,完成如下要求 1.编写服务脚本/root/bin/testsrv.sh,完成如下要求 (1) 脚本可接受参数: start, stop, restart, status(2) 如果参数非此四者之一,提示使用格式后报错退出(3) 如是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示"启动成功"考虑:如果事先已经启动过一次,该如何处理?(4) 如是stop:则删除/var/lock/subsys/