作者: 不洗碗工作室 - Marklux
出处: Dubbo 入门 (2) - 简单实践 http://marklux.cn/blog/83
在了解什么是分布式框架之后, 我们需要上手实践一下, 来了解整个系统是如何运作起来的.
本文抱着学习的目的来尝试使用 dubbo 搭建一个简单的分布式服务, 并且使用 dubbokeeper 来进行服务的监控.
参考自: 聊聊 dubbo 和最简单的 dubbo 教程 https://blog.csdn.net/jingyangV587/article/details/78901937
准备工作
在正式使用 dubbo 之前, 需要准备两样东西:
1. 服务注册中心 (ZooKeeper)
dubbo 的消费方和服务方都需要在一个统一的注册中心进行注册才能使用, 搭建一个 zookeeper 即可, 当然你也可以使用其他的注册中心并集成进去.
zookeeper 的搭建流程很简单, 参考此文 https://blog.csdn.net/jingyangv587/article/details/78901508 即可 (仅仅是最简单的单机版, 并不复杂).
2. 服务监控中心 (dubbokeeper)
为了监控整个分布式服务的运行情况, 最好能够有一个可视化的管理和监控应用, 这里选用由 dubboclub 团队开发的 https://github.com/dubboclub/dubbokeeper , 当然也可以使用 dubbo 官方的 dubboadmin 项目.
由于 dubbokeeper 的部署有些复杂, 在这里还是简要的描述一下, 注意监控软件并不是必要的, 但是为了能够看到服务运行的效果, 建议还是部署一个.
部署流程参考此文 https://blog.csdn.net/ws_flying/article/details/71239690
下载源码
首先需要获取 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-api,pom.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-client,pom.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 这样的监控端, 也更能够直观的理解整个应用服务的分布和运行情况.
来源: https://juejin.im/post/5afeb697f265da0b7b362783