开发dubbo应用程序(一)入门demo详解

1.简介:

引用自Dubbo官方文档简介:

http://dubbo.apache.org/zh-cn/docs/user/dependencies.html

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。

垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。

分布式服务架构

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。

流动计算架构

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

2.Dubbo相关实例

dubbo的官方sample的github地址:

https://github.com/apache/dubbo-samples/tree/2.6.x

以下的demo参考以上官方文档而来:

开发dubbo应用程序(一)入门demo详解_第1张图片

pom.xm



  4.0.0

  com.home
  dubbo-demo
  1.0-SNAPSHOT
  
    demo-api
  
  pom

  dubbo-demo Maven Webapp
  
  http://www.example.com

  
    UTF-8
    1.7
    1.7
    2.7.3
  

  
    
    
      org.apache.dubbo
      dubbo
      ${dubbo.version}
      
        
          spring
          org.springframework
        
      
    

    
      org.apache.curator
      curator-framework
      4.0.1
    

    
    
      org.apache.curator
      curator-framework
      4.2.0
    

    
    
      org.apache.curator
      curator-recipes
      4.2.0
    
    
    
      org.springframework
      spring-webmvc
      4.3.14.RELEASE
    

    
    
      com.101tec
      zkclient
      0.11
    

    
      junit
      junit
      4.11
      test
    
  

  
    dubbo-demo
    
      
        
          maven-clean-plugin
          3.1.0
        
        
        
          maven-resources-plugin
          3.0.2
        
        
          maven-compiler-plugin
          3.8.0
        
        
          maven-surefire-plugin
          2.22.1
        
        
          maven-war-plugin
          3.2.2
        
        
          maven-install-plugin
          2.5.2
        
        
          maven-deploy-plugin
          2.8.2
        
      
    
  
EchoProvider:
package com.dubbo.service.provider;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class EchoProvider {


    public static void main(String[] args) throws IOException {

        ClassPathXmlApplicationContext context =  new ClassPathXmlApplicationContext(
                new String[]{"spring/echo-provider.xml"}
        );
        context.start();
        System.in.read();

    }
}
EchoServiceImpl:
package com.dubbo.service.impl;

import com.alibaba.dubbo.rpc.RpcContext;
import com.dubbo.service.EchoService;

import java.text.SimpleDateFormat;
import java.util.Date;

public class EchoServiceImpl implements EchoService {

    @Override
    public String echo(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 from provider: " + RpcContext.getContext().getLocalAddress();
    }
}
echo-provider.xml:


    

    
    
    
    
    
    
    
    
    
    
EchoProvider:
package com.dubbo.service.provider;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class EchoProvider {

    public static void main(String[] args) throws IOException {

        ClassPathXmlApplicationContext context =  new ClassPathXmlApplicationContext(
                new String[]{"spring/echo-provider.xml"}
        );
        context.start();
        System.in.read();

    }
}
echo-consumer.xml



    

    
    

    
    

    
    

EchoConsumer
package com.dubbo.service.consumer;

import com.dubbo.service.EchoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class EchoConsumer {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[]{"spring/echo-consumer.xml"}
        );
        context.start();
        EchoService echoService = (EchoService) context.getBean("echoService");


        String status = echoService.echo("hello world");

        System.out.println("echo:"+status);


    }
}

主要需要先启动Zokeeper,然后启动提供方,之后启动消费方就可以收到相应的消息了.

3.使用注解形式,摘自官方文档

项目结构如下:

AnnotationAction
/*
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements.  See the NOTICE file distributed with
 *   this work for additional information regarding copyright ownership.
 *   The ASF licenses this file to You 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 annotation.action;

import annotation.AnnotationConstants;
import annotation.api.GreetingService;
import annotation.api.HelloService;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Component;

@Component("annotationAction")
public class AnnotationAction {

    @Reference(interfaceClass = HelloService.class, version = AnnotationConstants.VERSION)
    private HelloService helloService;

    @Reference(interfaceClass = GreetingService.class,
            version = AnnotationConstants.VERSION,
            methods = {@Method(name = "greeting", timeout = 250, retries = 1)})
    private GreetingService greetingService;

    public String doSayHello(String name) {
        try {
            return helloService.sayHello(name);
        } catch (Exception e) {
            e.printStackTrace();
            return "Throw Exception";
        }
    }

    public String doSayGoodbye(String name) {
        try {
            return helloService.sayGoodbye(name);
        } catch (Exception e) {
            e.printStackTrace();
            return "Throw Exception";
        }

    }

    public String doGreeting(String name) {
        try {
            return greetingService.greeting(name);
        } catch (Exception e) {
            e.printStackTrace();
            return "Throw Exception";
        }

    }

    public String replyGreeting(String name) {
        try {
            return greetingService.replyGreeting(name);
        } catch (Exception e) {
            e.printStackTrace();
            return "Throw Exception";
        }
    }
}
GreetingService
package annotation.api;

import java.util.concurrent.CompletableFuture;

public interface GreetingService {

    String greeting(String name);

    default String replyGreeting(String name) {
        return "Fine, " + name;
    }

    default CompletableFuture greeting(String name, byte signal) {
        return CompletableFuture.completedFuture(greeting(name));
    }

}
HelloService
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 annotation.api;

public interface HelloService {

    String sayHello(String name);

    default String sayGoodbye(String name) {
        return "Goodbye, " + name;
    }
}
AnnotationGreetingServiceImpl
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 annotation.impl;

import annotation.AnnotationConstants;
import annotation.api.GreetingService;
import org.apache.dubbo.config.annotation.Service;

@Service(version = AnnotationConstants.VERSION)
public class AnnotationGreetingServiceImpl implements GreetingService {

    @Override
    public String greeting(String name) {
        System.out.println("provider received invoke of greeting: " + name);
        sleepWhile();
        return "Annotation, greeting " + name;
    }

    public String replyGreeting(String name) {
        System.out.println("provider received invoke of replyGreeting: " + name);
        sleepWhile();
        return "Annotation, fine " + name;
    }

    private void sleepWhile() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
AnnotationHelloServiceImpl
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 annotation.impl;


import annotation.AnnotationConstants;
import annotation.api.HelloService;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.annotation.Service;

@Service(version = AnnotationConstants.VERSION, methods = {@Method(name = "sayGoodbye", timeout = 250, retries = 0)})
public class AnnotationHelloServiceImpl implements HelloService {

    @Override
    public String sayHello(String name) {
        System.out.println("provider received invoke of sayHello: " + name);
        sleepWhile();
        return "Annotation, hello " + name;
    }

    public String sayGoodbye(String name) {
        System.out.println("provider received invoke of sayGoodbye: " + name);
        sleepWhile();
        return "Goodbye, " + name;
    }

    private void sleepWhile() {
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
AnnotationConstants
package annotation;

public interface AnnotationConstants {
    String VERSION = "1.0.0_annotation";
}

AnnotationConsumerBootstrap

/*
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements.  See the NOTICE file distributed with
 *   this work for additional information regarding copyright ownership.
 *   The ASF licenses this file to You 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 annotation;

import annotation.action.AnnotationAction;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

public class AnnotationConsumerBootstrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
        context.start();
        final AnnotationAction annotationAction = (AnnotationAction) context.getBean("annotationAction");

        System.out.println("hello :" + annotationAction.doSayHello("world"));
        System.out.println("goodbye :" + annotationAction.doSayGoodbye("world"));
        System.out.println("greeting :" + annotationAction.doGreeting("world"));
        System.out.println("reply :" + annotationAction.replyGreeting("world"));
    }


    @Configuration
    @EnableDubbo(scanBasePackages = "annotation.action")
    @PropertySource("classpath:/spring/dubbo-consumer.properties")
    @ComponentScan(value = {"annotation.action"})
    static public class ConsumerConfiguration {

    }

}
AnnotationProviderBootstrap
/*
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements.  See the NOTICE file distributed with
 *   this work for additional information regarding copyright ownership.
 *   The ASF licenses this file to You 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 annotation;


import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import java.util.concurrent.CountDownLatch;

public class AnnotationProviderBootstrap {

    public static void main(String[] args) throws Exception {
        new EmbeddedZooKeeper(2181, false).start();

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
        context.start();

        System.out.println("dubbo service started.");
        new CountDownLatch(1).await();
    }

    @Configuration
    @EnableDubbo(scanBasePackages = "annotation.impl")
    @PropertySource("classpath:/spring/dubbo-provider.properties")
    static public class ProviderConfiguration {
        @Bean
        public ProviderConfig providerConfig() {
            ProviderConfig providerConfig = new ProviderConfig();
            providerConfig.setTimeout(1000);
            return providerConfig;
        }
    }

}
EmbeddedZooKeeper:
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 annotation;

import org.apache.zookeeper.server.ServerConfig;
import org.apache.zookeeper.server.ZooKeeperServerMain;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.SmartLifecycle;
import org.springframework.util.ErrorHandler;
import org.springframework.util.SocketUtils;

import java.io.File;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.UUID;

/**
 * from: https://github.com/spring-projects/spring-xd/blob/v1.3.1.RELEASE/spring-xd-dirt/src/main/java/org/springframework/xd/dirt/zookeeper/ZooKeeperUtils.java
 * 

* Helper class to start an embedded instance of standalone (non clustered) ZooKeeper. *

* NOTE: at least an external standalone server (if not an ensemble) are recommended, even for * {@link org.springframework.xd.dirt.server.singlenode.SingleNodeApplication} * * @author Patrick Peralta * @author Mark Fisher * @author David Turanski */ public class EmbeddedZooKeeper implements SmartLifecycle { /** * Logger. */ private static final Logger logger = LoggerFactory.getLogger(EmbeddedZooKeeper.class); /** * ZooKeeper client port. This will be determined dynamically upon startup. */ private final int clientPort; /** * Whether to auto-start. Default is true. */ private boolean autoStartup = true; /** * Lifecycle phase. Default is 0. */ private int phase = 0; /** * Thread for running the ZooKeeper server. */ private volatile Thread zkServerThread; /** * ZooKeeper server. */ private volatile ZooKeeperServerMain zkServer; /** * {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. */ private ErrorHandler errorHandler; private boolean daemon = true; /** * Construct an EmbeddedZooKeeper with a random port. */ public EmbeddedZooKeeper() { clientPort = SocketUtils.findAvailableTcpPort(); } /** * Construct an EmbeddedZooKeeper with the provided port. * * @param clientPort port for ZooKeeper server to bind to */ public EmbeddedZooKeeper(int clientPort, boolean daemon) { this.clientPort = clientPort; this.daemon = daemon; } /** * Returns the port that clients should use to connect to this embedded server. * * @return dynamically determined client port */ public int getClientPort() { return this.clientPort; } /** * Specify whether to start automatically. Default is true. * * @param autoStartup whether to start automatically */ public void setAutoStartup(boolean autoStartup) { this.autoStartup = autoStartup; } /** * {@inheritDoc} */ @Override public boolean isAutoStartup() { return this.autoStartup; } /** * Specify the lifecycle phase for the embedded server. * * @param phase the lifecycle phase */ public void setPhase(int phase) { this.phase = phase; } /** * {@inheritDoc} */ @Override public int getPhase() { return this.phase; } /** * {@inheritDoc} */ @Override public boolean isRunning() { return (zkServerThread != null); } /** * Start the ZooKeeper server in a background thread. *

* Register an error handler via {@link #setErrorHandler} in order to handle * any exceptions thrown during startup or execution. */ @Override public synchronized void start() { if (zkServerThread == null) { zkServerThread = new Thread(new ServerRunnable(), "ZooKeeper Server Starter"); zkServerThread.setDaemon(daemon); zkServerThread.start(); } } /** * Shutdown the ZooKeeper server. */ @Override public synchronized void stop() { if (zkServerThread != null) { // The shutdown method is protected...thus this hack to invoke it. // This will log an exception on shutdown; see // https://issues.apache.org/jira/browse/ZOOKEEPER-1873 for details. try { Method shutdown = ZooKeeperServerMain.class.getDeclaredMethod("shutdown"); shutdown.setAccessible(true); shutdown.invoke(zkServer); } catch (Exception e) { throw new RuntimeException(e); } // It is expected that the thread will exit after // the server is shutdown; this will block until // the shutdown is complete. try { zkServerThread.join(5000); zkServerThread = null; } catch (InterruptedException e) { Thread.currentThread().interrupt(); logger.warn("Interrupted while waiting for embedded ZooKeeper to exit"); // abandoning zk thread zkServerThread = null; } } } /** * Stop the server if running and invoke the callback when complete. */ @Override public void stop(Runnable callback) { stop(); callback.run(); } /** * Provide an {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. If none * is provided, only error-level logging will occur. * * @param errorHandler the {@link ErrorHandler} to be invoked */ public void setErrorHandler(ErrorHandler errorHandler) { this.errorHandler = errorHandler; } /** * Runnable implementation that starts the ZooKeeper server. */ private class ServerRunnable implements Runnable { @Override public void run() { try { Properties properties = new Properties(); File file = new File(System.getProperty("java.io.tmpdir") + File.separator + UUID.randomUUID()); file.deleteOnExit(); properties.setProperty("dataDir", file.getAbsolutePath()); properties.setProperty("clientPort", String.valueOf(clientPort)); QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig(); quorumPeerConfig.parseProperties(properties); zkServer = new ZooKeeperServerMain(); ServerConfig configuration = new ServerConfig(); configuration.readFrom(quorumPeerConfig); zkServer.runFromConfig(configuration); } catch (Exception e) { if (errorHandler != null) { errorHandler.handleError(e); } else { logger.error("Exception running embedded ZooKeeper", e); } } } } }

dubbo-consumer.properties
dubbo.application.name=samples-annotation-consumer
dubbo.registry.address=zookeeper://${zookeeper.address:127.0.0.1}:2181
dubbo.consumer.timeout=1000
dubbo-provider.properties
dubbo.application.name=samples-annotation-provider
dubbo.registry.address=zookeeper://${zookeeper.address:127.0.0.1}:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
log4j.properties
#
#
#   Licensed to the Apache Software Foundation (ASF) under one or more
#   contributor license agreements.  See the NOTICE file distributed with
#   this work for additional information regarding copyright ownership.
#   The ASF licenses this file to You 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.
#  
#

###set log levels###
log4j.rootLogger=info, stdout
###output to the console###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n

你可能感兴趣的:(开发dubbo应用程序(一)入门demo详解)