更新时间: 2018-08-17 17:16:53       分类: 学习笔记


前言

在了解什么是分布式框架之后,我们需要上手实践一下,来了解整个系统是如何运作起来的。

本文抱着学习的目的来尝试使用dubbo搭建一个简单的分布式服务,并且使用dubbokeeper来进行服务的监控。

参考自:聊聊dubbo最简单的dubbo教程

准备工作

在正式使用dubbo之前,需要准备两样东西:

1. 服务注册中心(ZooKeeper)

dubbo的消费方和服务方都需要在一个统一的注册中心进行注册才能使用,搭建一个zookeeper即可,当然你也可以使用其他的注册中心并集成进去。

zookeeper的搭建流程很简单,参考此文即可(仅仅是最简单的单机版,并不复杂)。

2. 服务监控中心(dubbokeeper)

为了监控整个分布式服务的运行情况,最好能够有一个可视化的管理和监控应用,这里选用由dubboclub团队开发的dubbokeeper,当然也可以使用dubbo官方的dubboadmin项目。

由于dubbokeeper的部署有些复杂,在这里还是简要的描述一下,注意监控软件并不是必要的,但是为了能够看到服务运行的效果,建议还是部署一个。

部署流程参考此文

下载源码

首先需要获取dubbokeeper的源码,可以从github上获取,git地址:

https://github.com/dubboclub/dubbokeeper

下面我们假设将dubbokeeper克隆到了~/dubbokeeper这个目录下。

修改配置

在此之前,首先需要确定你要使用何种数据库,dubbokeeper目前支持MySQL,MongoDB和Lucene三种数据储存方案,我们以MySQL为例进行部署。

首先要填写~/dubbokeeper/conf/dubbo-mysql.properties配置文件,下面给出比较重要的配置项说明:

dubbo.registry.address=zookeeper://localhost:2181 #注册中心地址
dubbo.protocol.name=dubbo
dubbo.protocol.port=20884 #dubbo服务端口
dubbo.monitor.mysql.url=jdbc:mysql://localhost:3306/dubbo-monitor #mysql服务地址
dubbo.monitor.mysql.username=root
dubbo.monitor.mysql.password=secret #用户名及密码

接下来要填写~/dubbokeeper/dubbokeeper-ui/src/main/resources/dubbo.properties配置文件中的注册中心和网络服务器类型等参数。

初始化数据库

创建一个mysql数据库,并运行~/dubbokeeper/doc/storage/mysql/sql/application.sql创建表结构。

编译打包

执行~/dubbokeeper/install-mysql.sh进行打包,最终会生成target输出目录。

启动部署

这一步要启动几个服务后才能去部署应用,注意顺序

首先需要启动zookeeper服务,注意端口的配置要和配置文件一致。

接下来执行target目录下的mysql-dubbokeeper-server/bin/start-mysql.sh启动储存服务。

最后将target目录下的mysql-dubbokeeper-ui中的war包复制到tomcat(自己部署)的webapps目录下,启动tomcat便会自动进行解压和安装,之后访问http://localhost:8080/dubbokeeper-ui-1.0.1看到如下界面,即为安装成功。

创建API

现在正式开始编程。我们将使用dubbo创建一个非常简单的、只有一个消费者和一个服务提供方的例子。

首先第一步是创建双方都需要依赖的数据交换定义,通过一个interface来实现。

创建maven项目msa-demo-apipom.xml文件内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.marklux</groupId>
    <artifactId>msa-demo-api</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <motan.version>0.3.0</motan.version>
        <!-- 在阿里巴巴内部广泛使用的GA版本为:2.4.9,强烈推荐此版本 -->
        <dubbo.version>2.5.3</dubbo.version>
        <dubbox.version>2.8.4</dubbox.version>
        <spring.version>4.3.6.RELEASE</spring.version>
        <java.version>1.7</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
        <!-- spring相关 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.11</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.11</version>
        </dependency>
    </dependencies>
</project>

然后在com.marklux.dubbo.demo包中添加DemoService接口,代码如下:

package com.marklux.dubbo.demo;

/**
 * Created by lumin on 18/5/15.
 */
public interface DemoService {
    String sayHello(String name);
}

之后的服务提供方根据这个接口实现服务,消费者根据接口调用服务。(有点类似Thrift里的IDL文件)

创建服务提供者

创建一个新的maven模块msa-demo-provider,用于实现DemoService服务。模块结构如下:

项目的pom.xml中需要添加对msa-demo-api模块的依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.marklux</groupId>
    <artifactId>msa-demo-provider</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>com.marklux</groupId>
            <artifactId>msa-demo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

首先编写DemoServiceImpl实现服务内容,代码如下:

package com.marklux.dubbo.demo.impl;

import com.marklux.dubbo.demo.DemoService;
import org.springframework.stereotype.Service;

/**
 * Created by lumin on 18/5/15.
 */
@Service("demoService")
public class DemoServiceImpl implements DemoService {

    public String sayHello(String name) {
        return "Hello, " + name;
    }
}

接下来填写msa-demo-provider.xml配置文件,配置服务接入注册中心,以及暴露端口号:

<?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:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://code.alibabatech.com/schema/dubbo
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="dubbo_provider"  />

    <!-- 使用zookeeper注册中心暴露服务地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.marklux.dubbo.demo.DemoService" ref="demoService" />
</beans>

然后填写springmvc.xml,用于给入口类提供Spring服务容器的配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-4.0.xsd"
       default-autowire="byName">

    <aop:aspectj-autoproxy />
    <context:component-scan base-package="com.marklux.dubbo.demo" />
    <import resource="classpath:msa-demo-provider.xml" />
</beans>

最后在com.marklux.dubbo.demo.test包中添加测试启动类,用于启动服务:

package com.marklux.dubbo.demo.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * Created by lumin on 18/5/15.
 */
public class DemoServiceImplTest  {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-mvc.xml");
        context.start();
        System.out.println("Dubbo Service started....");
        try {
            System.in.read();   // 按任意键退出
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

启动DemoServiceImplTest类后服务就会注册并启动,这时候可以在dubbokeeper中看到服务的状态:

创建消费者

最后来创建一个调用服务的消费者,添加一个maven模块msa-demo-clientpom.xml同上,添加对msa-demo-api模块的依赖,注意并不需要msa-demo-provider的依赖。

模块的结构如下:

只有一个测试的启动类,代码如下:

package com.marklux.dubbo.demo.test;

import com.marklux.dubbo.demo.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * Created by lumin on 18/5/15.
 */
public class DemoServiceConsumerTest {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:springmvc.xml"});

        context.start();
        DemoService demoService = (DemoService) context.getBean("demoService");

        System.out.println(demoService.sayHello("哈哈哈"));
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

记得补充dubbo的配置文件msa-demo-client.xml和spring的配置文件springmvc.xml,如下:

<?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:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd ">
    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="dubbo_consumer" />
    <!-- 使用multicast广播注册中心暴露发现服务地址 -->
    <dubbo:registry  protocol="zookeeper" address="zookeeper://127.0.0.1:2181" />
    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="demoService" interface="com.marklux.dubbo.demo.DemoService" />
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-4.0.xsd"
       default-autowire="byName">

    <aop:aspectj-autoproxy />
    <context:component-scan base-package="com.marklux.dubbo.demo" />
    <import resource="classpath:msa-demo-consumer.xml" />
</beans>

万事俱备,现在启动DemoServiceConsumerTest,可以看到成功调用了DemoService

在dubbokeeper中同样可以查看到其相关状态:

小结

至此,一个最简单的使用dubbo协议进行服务-调用的demo就完成了。可以看到最显著的特点是,在消费者中调用服务方提供的服务无需添加额外代码,整个调用过程完全透明。

另外借助dubbokeeper这样的监控端,也更能够直观的理解整个应用服务的分布和运行情况。


评论

还没有评论