这可能是最手把手的dubbo框架入门

Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC实现服务的输出和输入功能,可以和Spring框架无缝集成。
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
对于Dubbo框架中,首先要了解其中涉及的三个基本的概念:provider(服务提供方),consumer(服务消费方)和注册中心。接下来,本文从这几个角色的角度,分别实现一个小的demo,以便尽快对于dubbo框架有一个简单的入门。

0、准备

这里们采用的IDE是macOS下的IDEA。我们新健一个名为DubboDemoProj的空Java工程,只选JDK就行,别的都不用选。


new empty project

我们将在这个工程中,新建各个Module来实现Dubbo框架中的各个角色。

1、接口依赖模块dubbo-api

dubbo-api模块提供统一的接口,最终会打为jar包,供consumer和provider引用。
这里dubbo-api模块新建的时候,要选Maven,但是不要勾选任何archetype,只需要建一个空的Maven项目就行。建好之后,结构如下图。

dubbo-api structure

dubbo-api/pom.xml是Maven的配置文件。其中,定义了该Module依赖了dubbo框架,同时为了避免Dubbo自带的Spring框架过低,我们排除掉了dubbo自带的spring框架,并显示指定了spring依赖的版本。如下。



    4.0.0

    com.spacecat.dubbo
    dubbo-api
    1.0-SNAPSHOT
    
        
            com.alibaba
            dubbo
            2.5.3
            
                
                    org.springframework
                    spring
                
            
            provided
        
        
            org.springframework
            spring-beans
            4.2.5.RELEASE
            provided
        
    


user-references.xml文件是该Module的classpath路径下提供了一个xml配置,该配置文件其实就是dubbo消费者的相关配置,后边消费者项目引入api之后可以直接使用该文件。内容如下。




    
    

UserService.java是一个接口,他定义了统一的接口让provider和consumer来引用,内容如下。

package com.dubbo.api;

/**
 * Created by chengxia on 2019/5/3.
 */
public interface UserService {
    String sayHi(String name);
}

编辑完上述源码文件之后,执行mvn install命令,将这个module装到mvn的本地仓库。这样,后面的项目就能够通过这个module的坐标在Maven的pom文件中,引用到这个模块。

$ mvn install
[INFO] Scanning for projects...
[INFO] 
[INFO] --------------------< com.spacecat.dubbo:dubbo-api >--------------------
[INFO] Building dubbo-api 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ dubbo-api ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ dubbo-api ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/chengxia/Developer/Java/DubboDemoProj/dubbo-api/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ dubbo-api ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/chengxia/Developer/Java/DubboDemoProj/dubbo-api/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ dubbo-api ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ dubbo-api ---
[INFO] No tests to run.
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ dubbo-api ---
[INFO] Building jar: /Users/chengxia/Developer/Java/DubboDemoProj/dubbo-api/target/dubbo-api-1.0-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ dubbo-api ---
[INFO] Installing /Users/chengxia/Developer/Java/DubboDemoProj/dubbo-api/target/dubbo-api-1.0-SNAPSHOT.jar to /Users/chengxia/Developer/Java/tools/apache-maven-3.6.0/repository/com/spacecat/dubbo/dubbo-api/1.0-SNAPSHOT/dubbo-api-1.0-SNAPSHOT.jar
[INFO] Installing /Users/chengxia/Developer/Java/DubboDemoProj/dubbo-api/pom.xml to /Users/chengxia/Developer/Java/tools/apache-maven-3.6.0/repository/com/spacecat/dubbo/dubbo-api/1.0-SNAPSHOT/dubbo-api-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.537 s
[INFO] Finished at: 2019-05-05T00:45:01+08:00
[INFO] ------------------------------------------------------------------------
ChengdeMacBook-Pro:dubbo-api chengxia$ 

2、服务提供方模块dubbo-provider

同样是一个在DubboDemoProj中的空Maven模块,建好之后,结构如下图。


dubbo-provider structure

pom.xml文件,其中,针对上面dubbo-api模块的依赖,具体如下。



    4.0.0

    com.spacecat.dubbo
    dubbo-provider
    1.0-SNAPSHOT
    
        
            com.alibaba
            dubbo
            2.5.3
            
                
                    org.springframework
                    spring
                
            
        
        
            org.springframework
            spring-beans
            4.2.5.RELEASE
        
        
            org.springframework
            spring-context-support
            4.2.5.RELEASE
        
        
            com.spacecat.dubbo
            dubbo-api
            1.0-SNAPSHOT
        
        
            org.apache.zookeeper
            zookeeper
            3.4.10
        
        
            com.github.sgroschupf
            zkclient
            0.1
        
    


UserServiceImpl.java是服务的实现类,如下。

package com.dubbo.provider;

import com.dubbo.api.UserService;

/**
 * Created by chengxia on 2019/5/3.
 */
public class UserServiceImpl implements UserService {
    public String sayHi(String s) {
        return "hello " + s + "!";
    }
}

com.dubbo.provider.Main是启动dubbo服务的,内容如下。

package com.dubbo.provider;

/**
 * Created by chengxia on 2019/5/3.
 */
public class Main {
    public static void main(String[] args) {
        com.alibaba.dubbo.container.Main.main(args);
    }
}

这个类调是dubbo框架提供的方法来启动dubbo服务。dubbo会在启动服务时,会读取classpath下一个名为dubbo.properties文件的属性配置。这里我们只要按照dubbo的规则配置相关参数即可,如下:
dubbo.properties

dubbo.container=spring
#set dubbo Sping load setting xmls
dubbo.spring.config=classpath:dubbo-provider.xml
dubbo.protocol.name=dubbo
dubbo.protocol.port=28511

dubbo.container指定了dubbo的容器使用spring,dubbo内部有四种容器实现,SpringContainer是其中一种,也是默认的容器。dubbo.spring.config指定了dubbo在启动服务时加载的spring配置文件。dubbo.protocol.name和dubbo.protocol.port分别指定使用的协议名和端口。


dubbo source example

上图是Spring源码的截图。SpringContainer类中定义了两个常量,SPRING_CONFIG和DEFAULT_SPRING_CONFIG,大概读一下代码就可以知道,start方法在执行时,会读取dubbo.spring.config属性值,该值指定的就是spring的配置文件,如果没读到,则使用默认的配置。默认配置为classpath*;META-INF/spring/*.xml,意思是读取classpath下META-INF文件夹下的spring文件夹中的所有xml文件。所以,我们也可以不配置dubbo.spring.config,但是要遵循dubbo默认的读取路径,将spring配置文件放置在META-INF/spring文件夹下。
dubbo-provider.xml是一个spring配置文件,只不过引入了dubbo相关的配置:



    
    
    
    
    

其中:

  • 指定了程序名称,我们可以在dubbo管理后台中通过该名称更清晰的区分服务
  • 指定了注册中心的地址,这里用的是本地的zookeeper。
  • 指定了集群容错模式,此处为快速失败
  • 普通的spring依赖注入
  • 服务导出,引用标签注入的类

3、注册中心

这里的注册中心,我们使用的是zookeeper。

3.1 zookeeper安装

$ brew info zookeeper
zookeeper: stable 3.4.13 (bottled), HEAD
Centralized server for distributed coordination of services
https://zookeeper.apache.org/
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/zookeeper.rb
==> Options
--HEAD
    Install HEAD version
==> Caveats
To have launchd start zookeeper now and restart at login:
  brew services start zookeeper
Or, if you don't want/need a background service you can just run:
  zkServer start
==> Analytics
install: 5,018 (30 days), 14,429 (90 days), 58,577 (365 days)
install_on_request: 1,733 (30 days), 4,463 (90 days), 19,783 (365 days)
build_error: 0 (30 days)
$ 

执行brew安装命令:

$ brew install zookeeper
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).

... ...

==> Deleted Formulae
safe

==> Downloading https://homebrew.bintray.com/bottles/zookeeper-3.4.13.mojave.bottle.tar.gz
==> Downloading from https://akamai.bintray.com/d1/d1e4e7738cd147dceb3d91b32480c20ac5da27d129905f336ba51c0c01b8a476?__gda__=exp=1556685597~hmac=2a06d1cd6581464fdc9510af3179137ee9754a2d28f1fe423eafaebf5fb6aec9&re
######################################################################## 100.0%
==> Pouring zookeeper-3.4.13.mojave.bottle.tar.gz
==> Caveats
To have launchd start zookeeper now and restart at login:
  brew services start zookeeper
Or, if you don't want/need a background service you can just run:
  zkServer start
==> Summary
  /usr/local/Cellar/zookeeper/3.4.13: 244 files, 33.4MB
==> `brew cleanup` has not been run in 30 days, running now...
Removing: /Users/chengxia/Library/Caches/Homebrew/fontconfig--2.13.1.mojave.bottle.tar.gz... (1.2MB)
Removing: /Users/chengxia/Library/Caches/Homebrew/freetype--2.9.1.mojave.bottle.tar.gz... (874.5KB)
Removing: /Users/chengxia/Library/Caches/Homebrew/gd--2.2.5.mojave.bottle.tar.gz... (290KB)
Removing: /Users/chengxia/Library/Caches/Homebrew/jpeg--9c.mojave.bottle.tar.gz... (300.8KB)
Removing: /Users/chengxia/Library/Caches/Homebrew/libtool--2.4.6_1.mojave.bottle.tar.gz... (1003.4KB)
Removing: /Users/chengxia/Library/Logs/Homebrew/tree... (64B)
$ 

安装后,在/usr/local/etc/zookeeper/目录下,已经有了缺省的配置文件。查看zookeeper配置文件:

$ ls /usr/local/etc/zookeeper
defaults        log4j.properties    zoo.cfg         zoo_sample.cfg
$ 

缺省配置/usr/local/etc/zookeeper/zoo.cfg 内容如下:

$ cat /usr/local/etc/zookeeper/zoo.cfg 
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/usr/local/var/run/zookeeper/data
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
$ 

3.2 zookeeper启动

启动zookeeper:

$ zkServer
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Usage: ./zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}
ChengdeMacBook-Pro:~ chengxia$ zkServer status
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Error contacting service. It is probably not running.
$ zkServer start
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Starting zookeeper ... STARTED
$ zkServer status
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Mode: standalone
$ 

3.3 zookeeper简单操作

查看zookeeper的运行状态:

$ zkCli
Connecting to localhost:2181
Welcome to ZooKeeper!
JLine support is enabled

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] ls
[zk: localhost:2181(CONNECTED) 1] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls /zookeeper
[quota]
[zk: localhost:2181(CONNECTED) 3] ls /zookeeper/quota 
[]
[zk: localhost:2181(CONNECTED) 4] quit
Quitting...
$ 

停止运行zookeeper:

$ zkServer stop
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Stopping zookeeper ... STOPPED
$ 

4、服务消费方

到这里,我们在本地启动zookeeper,然后,在IDEA中运行上面的com.dubbo.provider.Main,我们就将上面的服务注册到了本机的注册中心(zookeeper)。接下来,可以调用这个服务。

4.1 写一个简单的Spring项目来当做服务消费方

项目结构如下图。


spring-consumer structure

dubbo-consumer/pom.xml




    4.0.0
    com.spacecat.dubbo
    dubbo-consumer
    1.0-SNAPSHOT

    
        
        
        
            org.springframework
            spring-core
            4.1.4.RELEASE
        
        
        
        
            org.springframework
            spring-context
            4.1.4.RELEASE
        
        
            com.alibaba
            dubbo
            2.5.3
            
                
                    org.springframework
                    spring
                
            
        
        
            com.spacecat.dubbo
            dubbo-api
            1.0-SNAPSHOT
        

        
            org.apache.zookeeper
            zookeeper
            3.4.10
        
        
            com.github.sgroschupf
            zkclient
            0.1
        
    


这个Module中,依赖了dubbo-api。
dubbo-consumer.xml




    
    
    

    
    

这个文件中,直接引用了dubbo-api模块打包后自带的配置文件user-references.xml
com.dubbo.consumer.UserServiceCaller

package com.dubbo.consumer;

import com.dubbo.api.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by chengxia on 2019/5/5.
 */
public class UserServiceCaller {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("dubbo-consumer.xml");
        UserService service = (UserService) context.getBean("userService");
        System.out.print("Got service bean:");
        System.out.println(service);
        System.out.println("RPC call output:");
        System.out.println(service.sayHi("Kobe"));
    }
}

该文件完成了对服务的调用,可见dubbo框架已经把服务注入到一个本地可以直接调用的bean中了。直接调用bean的方法即可完成对于服务的远程调用(其实,已经和调本地一样了)。
启动zookeeper,运行前面的dubbo-provider模块中的启动类,然后再运行com.dubbo.consumer.UserServiceCaller,可以得到如下输出。

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Got service bean:com.alibaba.dubbo.common.bytecode.proxy0@49dc7102
RPC call output:
hello Kobe!

Process finished with exit code 0

4.2 通过命令行调用服务

通过命令行调用服务适用于对dubbo服务做个简单的测试的情况。可以直接在命令行通过telnet的方式来查看和调用dubbo服务。
新版本的MacOS默认没有telnet,可以通过如下步骤安装。

4.2.1 MacOS安装telnet

$ telnet
-bash: telnet: command not found
$ brew install telnet
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> New Formulae
pipx
==> Updated Formulae
allureofthestars     bluepill             dovecot              glib-networking      gupnp                mercurial            [email protected]              pulumi               qt                   translate-shell
bettercap            bzt                  faas-cli             gmic                 hugo                 pdftoipe             poppler              pumba                taskell
bit                  diff-pdf             ghq                  gssdp                imagemagick@6        php                  prototool            pushpin              tmux
==> Deleted Formulae
node@6

==> Downloading https://homebrew.bintray.com/bottles/telnet-60.mojave.bottle.tar.gz
######################################################################## 100.0%
==> Pouring telnet-60.mojave.bottle.tar.gz
  /usr/local/Cellar/telnet/60: 4 files, 138.2KB
ChengdeMacBook-Pro:~ chengxia$ telnet
telnet> quit
$ 

4.2.2 通过telnet查看和调用dubbo服务。

方法如下示例,这里的端口就是前面dubbo-provider模块中dubbo.properties文件中配置的端口,这个端口应该就是服务提供方的端口。

$ telnet 127.0.0.1 28511
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
ls
com.dubbo.api.UserService
dubbo>invoke com.dubbo.api.UserService.sayHi("Kobe")
"hello Kobe!"
elapsed: 1 ms.
dubbo>

参考资料

  • Mac OSX安装启动 zookeeper
  • Dubbo (开源分布式服务框架)
  • dubbo入门示例
  • 命令行调用远程dubbo服务
  • Dubbo入门---搭建一个最简单的Demo框架

你可能感兴趣的:(这可能是最手把手的dubbo框架入门)