在上一篇文章中http://blog.youkuaiyun.com/zhangw1236/article/details/65630952 给大家分析了dubbo的扩展点加载机制,在dubbo整体的框架中,扩展点加载是他的核心部分。本篇文章将带着大家看一下dubbo服务的启动过程,是怎么一步步将每个人写的不同的业务逻辑暴露出去的。这里我们使用dubbo源码自带的dubbo-demo-provider和dubbo-demo-consumer作为例子。
dubbo-demo-provider的业务代码只有一个接口和一个实现
public interface DemoService {
String sayHello(String name);
}
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
return "Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress();
}
}
作为服务提供方,也就是server端,逻辑非常简单:收到服务消费方也就是client端的消息后,打印消息,并回复response。这部分就是业务代码,剩下的只需要提供一些配置,dubbo就可以帮你把这个服务暴露出去。
下面我们来看看main函数:
private static final ExtensionLoader<Container> loader = ExtensionLoader.getExtensionLoader(Container.class);
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);
}
final List<Container> containers = new ArrayList<Container>();
//根据container名称,获取指定的扩展点
for (int i = 0; i < args.length; i ++) {
containers.add(loader.getExtension(args[i]));
}
logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce.");
//程序退出时,关闭container
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();
}
}
}
});
}
//启动具体的container
for (Container container : containers) {
System.out.println("Dubbo " + container.getClass().getSimpleName() + " starting...");
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) {
}
}
}
}
配置文件:
dubbo.container=log4j,spring
dubbo.application.name=demo-provider
dubbo.application.owner=
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.monitor.protocol=registry
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.service.loadbalance=roundrobin
dubbo.log4j.file=logs/dubbo-demo-provider.log
dubbo.log4j.level=INFO
dubbo的启动是包含在容器(container)中的,这里配置的容器是spring,从配