Dubbo_特性1

来源:互联网 发布:百事淘宝跟淘宝的区别 编辑:程序博客网 时间:2024/06/05 18:10

一、Main方法是启动加载,spring默认配置,日志框架的加载

1、从Main的入口可以看见,加载时使用了钩子对配置或者默认配置的container进行加载(也就是dubbo-container源码中的四个模块,日志、spring容器、服务器(现在只能使用jetty)和logback),会加载子模块下的/dubbo-container/dubbo-container-spring/target/classes/META-INF/dubbo/internal/com.alibaba.dubbo.container.Container(四个container的位置一致)。

/* * Copyright 1999-2011 Alibaba Group. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   *      http://www.apache.org/licenses/LICENSE-2.0 *   * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.container;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Arrays;import java.util.Date;import java.util.List;import com.alibaba.dubbo.common.Constants;import com.alibaba.dubbo.common.extension.ExtensionLoader;import com.alibaba.dubbo.common.logger.Logger;import com.alibaba.dubbo.common.logger.LoggerFactory;import com.alibaba.dubbo.common.utils.ConfigUtils;/** * Main. (API, Static, ThreadSafe) *  * @author william.liangf */public class Main {    public static final String CONTAINER_KEY = "dubbo.container";    public static final String SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook";        private static final Logger logger = LoggerFactory.getLogger(Main.class);    private static final ExtensionLoader<Container> loader = ExtensionLoader.getExtensionLoader(Container.class);        private static volatile boolean running = true;    public static void main(String[] args) {        try {            if (args == null || args.length == 0) {                String config = ConfigUtils.getProperty(CONTAINER_KEY, loader.getDefaultExtensionName());                args = Constants.COMMA_SPLIT_PATTERN.split(config);            }            // dubbo的核心扩展机制(从dubbo的dubbo-contrainer源码部分可以看见包含jetty、log4j、logback、spring的容器)            final List<Container> containers = new ArrayList<Container>();                        for (int i = 0; i < args.length; i ++) {            // 就会加载默认或者配置好的容器(spring也是从该处进行加载)                containers.add(loader.getExtension(args[i]));            }            logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce.");                        if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) {            Runtime.getRuntime().addShutdownHook(new Thread() {                public void run() {                    for (Container container : containers) {                        try {                            container.stop();                            logger.info("Dubbo " + container.getClass().getSimpleName() + " stopped!");                        } catch (Throwable t) {                            logger.error(t.getMessage(), t);                        }                        synchronized (Main.class) {                            running = false;                            Main.class.notify();                        }                    }                }            });            }                        for (Container container : containers) {                container.start();                logger.info("Dubbo " + container.getClass().getSimpleName() + " started!");            }            System.out.println(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]").format(new Date()) + " Dubbo service server started!");        } catch (RuntimeException e) {            e.printStackTrace();            logger.error(e.getMessage(), e);            System.exit(1);        }        synchronized (Main.class) {            while (running) {                try {                    Main.class.wait();                } catch (Throwable e) {                }            }        }    }    }


2、加载日志模块的container的时候会使用工厂进行初始化,也说明了可以在

<dubbo:application name="order-prodider" owner="kevin" logger="slf4j" />

中进行配置的logger属性的值,并且默认值为log4j。

/* * Copyright 1999-2011 Alibaba Group. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   *      http://www.apache.org/licenses/LICENSE-2.0 *   * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.common.logger;import java.io.File;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import com.alibaba.dubbo.common.extension.ExtensionLoader;import com.alibaba.dubbo.common.logger.jcl.JclLoggerAdapter;import com.alibaba.dubbo.common.logger.jdk.JdkLoggerAdapter;import com.alibaba.dubbo.common.logger.log4j.Log4jLoggerAdapter;import com.alibaba.dubbo.common.logger.slf4j.Slf4jLoggerAdapter;import com.alibaba.dubbo.common.logger.support.FailsafeLogger;/** * 日志输出器工厂 *  * @author william.liangf */public class LoggerFactory {private LoggerFactory() {}private static volatile LoggerAdapter LOGGER_ADAPTER;private static final ConcurrentMap<String, FailsafeLogger> LOGGERS = new ConcurrentHashMap<String, FailsafeLogger>();// 查找常用的日志框架static {    String logger = System.getProperty("dubbo.application.logger");    if ("slf4j".equals(logger)) {    setLoggerAdapter(new Slf4jLoggerAdapter());    } else if ("jcl".equals(logger)) {    setLoggerAdapter(new JclLoggerAdapter());    } else if ("log4j".equals(logger)) {    setLoggerAdapter(new Log4jLoggerAdapter());    } else if ("jdk".equals(logger)) {    setLoggerAdapter(new JdkLoggerAdapter());    } else {    try {    setLoggerAdapter(new Log4jLoggerAdapter());            } catch (Throwable e1) {                try {                setLoggerAdapter(new Slf4jLoggerAdapter());                } catch (Throwable e2) {                    try {                    setLoggerAdapter(new JclLoggerAdapter());                    } catch (Throwable e3) {                        setLoggerAdapter(new JdkLoggerAdapter());                    }                }            }    }}public static void setLoggerAdapter(String loggerAdapter) {    if (loggerAdapter != null && loggerAdapter.length() > 0) {        setLoggerAdapter(ExtensionLoader.getExtensionLoader(LoggerAdapter.class).getExtension(loggerAdapter));    }}/** * 设置日志输出器供给器 *  * @param loggerAdapter *            日志输出器供给器 */public static void setLoggerAdapter(LoggerAdapter loggerAdapter) {if (loggerAdapter != null) {Logger logger = loggerAdapter.getLogger(LoggerFactory.class.getName());logger.info("using logger: " + loggerAdapter.getClass().getName());LoggerFactory.LOGGER_ADAPTER = loggerAdapter;for (Map.Entry<String, FailsafeLogger> entry : LOGGERS.entrySet()) {entry.getValue().setLogger(LOGGER_ADAPTER.getLogger(entry.getKey()));}}}/** * 获取日志输出器 *  * @param key *            分类键 * @return 日志输出器, 后验条件: 不返回null. */public static Logger getLogger(Class<?> key) {FailsafeLogger logger = LOGGERS.get(key.getName());if (logger == null) {LOGGERS.putIfAbsent(key.getName(), new FailsafeLogger(LOGGER_ADAPTER.getLogger(key)));logger = LOGGERS.get(key.getName());}return logger;}/** * 获取日志输出器 *  * @param key *            分类键 * @return 日志输出器, 后验条件: 不返回null. */public static Logger getLogger(String key) {FailsafeLogger logger = LOGGERS.get(key);if (logger == null) {LOGGERS.putIfAbsent(key, new FailsafeLogger(LOGGER_ADAPTER.getLogger(key)));logger = LOGGERS.get(key);}return logger;}/** * 动态设置输出日志级别 *  * @param level 日志级别 */public static void setLevel(Level level) {LOGGER_ADAPTER.setLevel(level);}/** * 获取日志级别 *  * @return 日志级别 */public static Level getLevel() {return LOGGER_ADAPTER.getLevel();}/** * 获取日志文件 *  * @return 日志文件 */public static File getFile() {return LOGGER_ADAPTER.getFile();}}

3、加载spring的container的时,约定优于配置的"classpath*:META-INF/spring/*.xml"位置加载spring配置

/* * Copyright 1999-2011 Alibaba Group. *   * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *   *      http://www.apache.org/licenses/LICENSE-2.0 *   * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.alibaba.dubbo.container.spring;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.alibaba.dubbo.common.extension.ExtensionLoader;import com.alibaba.dubbo.common.logger.Logger;import com.alibaba.dubbo.common.logger.LoggerFactory;import com.alibaba.dubbo.common.utils.ConfigUtils;import com.alibaba.dubbo.container.Container;/** * SpringContainer. (SPI, Singleton, ThreadSafe) *  * @author william.liangf */public class SpringContainer implements Container {    private static final Logger logger = LoggerFactory.getLogger(SpringContainer.class);    public static final String SPRING_CONFIG = "dubbo.spring.config";        // 所以默认加载classpath*:META-INF/spring/*.xml的spring配置    public static final String DEFAULT_SPRING_CONFIG = "classpath*:META-INF/spring/*.xml";    static ClassPathXmlApplicationContext context;        public static ClassPathXmlApplicationContext getContext() {return context;}public void start() {        String configPath = ConfigUtils.getProperty(SPRING_CONFIG);        if (configPath == null || configPath.length() == 0) {            configPath = DEFAULT_SPRING_CONFIG;        }        context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"));        context.start();    }    public void stop() {        try {            if (context != null) {                context.stop();                context.close();                context = null;            }        } catch (Throwable e) {            logger.error(e.getMessage(), e);        }    }}

二、Admin控制中心(用来做服务的治理,如:服务的权重、服务的路由等)

在spring源码中找到dubbo-admin的web项目,将该服务进行启动,单独进行部署即可。

       启动前在/dubbo-admin/src/main/webapp/WEB-INF/dubbo.properties中修改注册中心的地址和使用的用户信息,如下:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"><bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /><property name="ignoreResourceNotFound" value="true" /><property name="locations"><list><value>/WEB-INF/dubbo.properties</value><value>file://${user.home}/dubbo.properties</value></list></property></bean><dubbo:application name="dubbo-admin" /><dubbo:registry address="${dubbo.registry.address}" check="false" file="false" /><dubbo:reference id="registryService" interface="com.alibaba.dubbo.registry.RegistryService" check="false" /><bean id="configService" class="com.alibaba.dubbo.governance.service.impl.ConfigServiceImpl" /><bean id="consumerService" class="com.alibaba.dubbo.governance.service.impl.ConsumerServiceImpl" /><bean id="overrideService" class="com.alibaba.dubbo.governance.service.impl.OverrideServiceImpl" /><bean id="ownerService" class="com.alibaba.dubbo.governance.service.impl.OwnerServiceImpl" /><bean id="providerService" class="com.alibaba.dubbo.governance.service.impl.ProviderServiceImpl" ></bean><bean id="routeService" class="com.alibaba.dubbo.governance.service.impl.RouteServiceImpl" /><bean id="userService" class="com.alibaba.dubbo.governance.service.impl.UserServiceImpl"><property name="rootPassword" value="${dubbo.admin.root.password}" /><property name="guestPassword" value="${dubbo.admin.guest.password}" /></bean><bean id="governanceCache" class="com.alibaba.dubbo.governance.sync.RegistryServerSync" /></beans>

dubbo.registry.address=zookeeper://127.0.0.1:2181dubbo.admin.root.password=rootdubbo.admin.guest.password=guest



三、Simple监控中心(监控服务的调用次数、调用关系、响应时间等)

监控中心本身就是一个dubbo服务,同样也会注册到注册中心。

同样在/dubbo-monitor-simple/src/main/assembly/conf/dubbo.properties中提供了以下配置:

### Copyright 1999-2011 Alibaba Group.#  # Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at#  #      http://www.apache.org/licenses/LICENSE-2.0#  # Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.##dubbo.container=log4j,spring,registry,jettydubbo.application.name=simple-monitordubbo.application.owner=dubbo.registry.address=multicast://224.5.6.7:1234#dubbo.registry.address=zookeeper://127.0.0.1:2181#dubbo.registry.address=redis://127.0.0.1:6379#dubbo.registry.address=dubbo://127.0.0.1:9090dubbo.protocol.port=7070dubbo.jetty.port=8080dubbo.jetty.directory=${user.home}/monitordubbo.charts.directory=${dubbo.jetty.directory}/chartsdubbo.statistics.directory=${user.home}/monitor/statisticsdubbo.log4j.file=logs/dubbo-monitor-simple.logdubbo.log4j.level=WARN

四、Dubbo提供的telnet命令(进入后可以使用 ls pwd clear invoke 等命令)

1、telnet ip port 到服务提供的服务器

2、cd com.kevin.dubbo.order.IOrderServices   找服务的地址

3、使用invoke对服务进行调用


原创粉丝点击