本文将基于 Dubbo Samples 示例演示如何快速搭建并部署一个微服务应用。

背景

Dubbo 作为一款微服务框架,最重要的是向用户提供跨进程的 RPC 远程调用能力。如上图所示,Dubbo 的服务消费者(Consumer)通过一系列的工作将请求发送给服务提供者(Provider)。

为了实现这样一个目标,Dubbo 引入了注册中心(Registry)组件,通过注册中心,服务消费者可以感知到服务提供者的连接方式,从而将请求发送给正确的服务提供者。

目标

了解微服务调用的方式以及 Dubbo 的能力

难度

环境要求

  • 系统:Windows、Linux、MacOS

  • JDK 8 及以上(推荐使用 JDK17)

  • Git

  • Docker (可选)

动手实践

本章将通过几个简单的命令,一步一步教你如何部署并运行一个最简单的 Dubbo 用例。

1. 获取测试工程

在开始整个教程之前,我们需要先获取测试工程的代码。Dubbo 的所有测试用例代码都存储在 apache/dubbo-samples 这个仓库中,以下这个命令可以帮你获取 Samples 仓库的所有代码。

git clone --depth=1 --branch master git@github.com:apache/dubbo-samples.git

2. 认识 Dubbo Samples 项目结构

在将 apache/dubbo-samples 这个仓库 clone 到本地以后,本小节将就仓库的具体组织方式做说明。

.
├── codestyle // 开发使用的 style 配置文件 ├── 1-basic // 基础的入门用例
├── 2-advanced // 高级用法
├── 3-extensions // 扩展使用示例
├── 4-governance // 服务治理用例
├── 10-task // Dubbo 学习系列示例 ├── 99-integration // 集成测试使用
├── test // 集成测试使用
└── tools // 三方组件快速启动工具

如上表所示,apache/dubbo-samples 主要由三个部分组成:代码风格文件、测试代码、集成测试。

  1. 代码风格文件是开发 Dubbo 代码的时候可以使用,其中包括了 IntelliJ IDEA 的配置文件。

  2. 测试代码即本教材所需要的核心内容。目前包括了 5 个部分的内容:面向初学者的 basic 入门用例、面向开发人员的 advanced 高级用法、面向中间件维护者的 extensions Dubbo 周边扩展使用示例、面向生产的 governance 服务治理用例以及 Dubbo 学习系列。本文将基于 basic 入门用例中最简单的 Dubbo API 使用方式进行讲解。

  3. 集成测试是 Dubbo 的质量保证体系中重要的一环,Dubbo 的每个版本都会对所有的 samples 进行回归验证,保证 Dubbo 的所有变更都不会影响 samples 的使用。

3. 启动一个简易的注册中心

从这一小节开始,将正式通过三个命令部署一个微服务应用。

背景 一节中可知,运行起 Dubbo 应用的一个大前提是部署一个注册中心,为了让本教程更易于上手,我们提供了一个基于 Apache Zookeeper 注册中心的简易启动器,如果您需要在生产环境部署注册中心,请参考生产环境初始化一文部署高可用的注册中心。

Windows:
./mvnw.cmd clean compile exec:java -pl tools/embedded-zookeeper Linux / MacOS:
./mvnw clean compile exec:java -pl tools/embedded-zookeeper 注:需要开一个独立的 terminal 运行,命令将会保持一直执行的状态。 Docker:
docker run --name some-zookeeper --restart always -d zookeeper

在执行完上述命令以后,等待一会出现如下图所示的日志即代表注册中心启动完毕,可以继续执行后续任务。

4. 启动服务提供者

在启动了注册中心之后,下一步是启动一个对外提供服务的服务提供者。在 dubbo-samples 中也提供了对应的示例,可以通过以下命令快速拉起。

Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.provider.Application" Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.provider.Application" 注:需要开一个独立的 terminal 运行,命令将会保持一直执行的状态。

在执行完上述命令以后,等待一会出现如下图所示的日志(DubboBootstrap awaiting)即代表服务提供者启动完毕,标志着该服务提供者可以对外提供服务了。

[19/01/23 03:55:49:049 CST] org.apache.dubbo.samples.provider.Application.main()  INFO bootstrap.DubboBootstrap:  [DUBBO] DubboBootstrap awaiting ..., dubbo version: 3.2.0-beta.3, current host: 169.254.44.42

5. 启动服务消费者

最后一步是启动一个服务消费者来调用服务提供者,也即是 RPC 调用的核心,为服务消费者提供调用服务提供者的桥梁。

Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.client.Application" Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.client.Application"

在执行完上述命令以后,等待一会出现如下图所示的日志(hi, dubbo),打印出的数据就是服务提供者处理之后返回的,标志着一次服务调用的成功。

Receive result ======> hi, dubbo

延伸阅读

1. 消费端是怎么找到服务端的?

在本用例中的步骤 3 启动了一个 Zookeeper 的注册中心,服务提供者会向注册中心中写入自己的地址,供服务消费者获取。

Dubbo 会在 Zookeeper 的 /dubbo/interfaceName/services/appName 下写入服务提供者的连接信息。

如下所示是 Zookeeper 上的数据示例:

[zk: localhost:2181(CONNECTED) 5] ls /dubbo/org.apache.dubbo.samples.api.GreetingsService/providers
[dubbo%3A%2F%2F30.221.146.35%3A20880%2Forg.apache.dubbo.samples.api.GreetingsService%3Fanyhost%3Dtrue%26application%3Dfirst-dubbo-provider%26background%3Dfalse%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26environment%3Dproduct%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.samples.api.GreetingsService%26ipv6%3Dfd00%3A1%3A5%3A5200%3A3218%3A774a%3A4f67%3A2341%26methods%3DsayHi%26pid%3D85639%26release%3D3.1.4%26service-name-mapping%3Dtrue%26side%3Dprovider%26timestamp%3D1674960780647] [zk: localhost:2181(CONNECTED) 2] ls /services/first-dubbo-provider
[30.221.146.35:20880]
[zk: localhost:2181(CONNECTED) 3] get /services/first-dubbo-provider/30.221.146.35:20880
{"name":"first-dubbo-provider","id":"30.221.146.35:20880","address":"30.221.146.35","port":20880,"sslPort":null,"payload":{"@class":"org.apache.dubbo.registry.zookeeper.ZookeeperInstance","id":"30.221.146.35:20880","name":"first-dubbo-provider","metadata":{"dubbo.endpoints":"[{\"port\":20880,\"protocol\":\"dubbo\"}]","dubbo.metadata-service.url-params":"{\"connections\":\"1\",\"version\":\"1.0.0\",\"dubbo\":\"2.0.2\",\"release\":\"3.1.4\",\"side\":\"provider\",\"ipv6\":\"fd00:1:5:5200:3218:774a:4f67:2341\",\"port\":\"20880\",\"protocol\":\"dubbo\"}","dubbo.metadata.revision":"871fbc9cb2730caea9b0d858852d5ede","dubbo.metadata.storage-type":"local","ipv6":"fd00:1:5:5200:3218:774a:4f67:2341","timestamp":"1674960780647"}},"registrationTimeUTC":1674960781893,"serviceType":"DYNAMIC","uriSpec":null}

更多关于 Dubbo 服务发现模型的细节,可以参考服务发现一文。

2. 消费端是如何发起请求的?

在 Dubbo 的调用模型中,起到连接服务消费者和服务提供者的桥梁是接口。

服务提供者通过对指定接口进行实现,服务消费者通过 Dubbo 去订阅这个接口。服务消费者调用接口的过程中 Dubbo 会将请求封装成网络请求,然后发送到服务提供者进行实际的调用。

在本用例中,定义了一个 GreetingsService 的接口,这个接口有一个名为 sayHi 的方法。

// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java

package org.apache.dubbo.samples.api;

public interface GreetingsService {

    String sayHi(String name);

}

服务消费者通过 Dubbo 的 API 可以获取这个 GreetingsService 接口的代理,然后就可以按照普通的接口调用方式进行调用。得益于 Dubbo 的动态代理机制,这一切都像本地调用一样。

// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java

// 获取订阅到的 Stub
GreetingsService service = reference.get();
// 像普通的 java 接口一样调用
String message = service.sayHi("dubbo");

3. 服务端可以部署多个吗?

可以,本小节将演示如何启动一个服务端集群

1)启动一个注册中心,可以参考动手实践中第 3 小节的教程

2)修改服务提供者返回的数据,让第一个启动的服务提供者返回 hi, dubbo. I am provider 1.

修改 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java 文件的第 25 行如下所示。

// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java

package org.apache.dubbo.samples.provider;

import org.apache.dubbo.samples.api.GreetingsService;

public class GreetingsServiceImpl implements GreetingsService {
@Override
public String sayHi(String name) {
return "hi, " + name + ". I am provider 1.";
}
}

3)启动第一个服务提供者,可以参考动手实践中第 4 小节的教程

4)修改服务提供者返回的数据,让第二个启动的服务提供者返回 hi, dubbo. I am provider 2.

修改 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java 文件的第 25 行如下所示。

// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java

package org.apache.dubbo.samples.provider;

import org.apache.dubbo.samples.api.GreetingsService;

public class GreetingsServiceImpl implements GreetingsService {
@Override
public String sayHi(String name) {
return "hi, " + name + ". I am provider 2.";
}
}

4)启动第二个服务提供者,可以参考动手实践中第 4 小节的教程

5)启动服务消费者,可以参考动手实践中第 5 小节的教程。多次启动消费者可以看到返回的结果是不一样的。

在 dubbo-samples 中也提供了一个会定时发起调用的消费端应用org.apache.dubbo.samples.client.AlwaysApplication,可以通过以下命令启动。

Windows:
./mvnw.cmd clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.client.AlwaysApplication" Linux / MacOS:
./mvnw clean compile exec:java -pl 1-basic/dubbo-samples-api -Dexec.mainClass="org.apache.dubbo.samples.client.AlwaysApplication"

启动后可以看到类似以下的日志,消费端会随机调用到不同的服务提供者,返回的结果也是远端的服务提供者觉得其结果。

Sun Jan 29 11:23:37 CST 2023 Receive result ======> hi, dubbo. I am provider 1.
Sun Jan 29 11:23:38 CST 2023 Receive result ======> hi, dubbo. I am provider 2.
Sun Jan 29 11:23:39 CST 2023 Receive result ======> hi, dubbo. I am provider 2.
Sun Jan 29 11:23:40 CST 2023 Receive result ======> hi, dubbo. I am provider 1.
Sun Jan 29 11:23:41 CST 2023 Receive result ======> hi, dubbo. I am provider 1.

4. 这个用例复杂吗?

不,Dubbo 只需要简单的配置就可以实现稳定、高效的远程调用。

以下是一个服务提供者的简单示例,通过定义若干个配置就可以启动。

// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/Application.java

// 定义所有的服务
ServiceConfig<GreetingsService> service = new ServiceConfig<>();
service.setInterface(GreetingsService.class);
service.setRef(new GreetingsServiceImpl()); // 启动 Dubbo
DubboBootstrap.getInstance()
.application("first-dubbo-provider")
.registry(new RegistryConfig(ZOOKEEPER_ADDRESS))
.protocol(new ProtocolConfig("dubbo", -1))
.service(service)
.start();

以下是一个服务消费者的简单示例,通过定义若干个配置启动后就可以获取到对应的代理对象,之后用户完全不需要感知这个对象背后的复杂实现,一切只需要和本地调用一样就行了

// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java

// 定义所有的订阅
ReferenceConfig<GreetingsService> reference = new ReferenceConfig<>();
reference.setInterface(GreetingsService.class); // 启动 Dubbo
DubboBootstrap.getInstance()
.application("first-dubbo-consumer")
.registry(new RegistryConfig(ZOOKEEPER_ADDRESS))
.reference(reference)
.start(); // 获取订阅到的 Stub
GreetingsService service = reference.get();
// 像普通的 java 接口一样调用
String message = service.sayHi("dubbo");

更多

本用例介绍了一个 RPC 远程调用的基础流程,通过启动注册中心、服务提供者、服务消费者三个节点来模拟一个微服务的部署架构。

下一个教程中,将就服务提供者和服务消费者分别都做了什么配置进行讲解,从零告诉你如何搭建一个微服务应用。

欢迎在 https://github.com/apache/dubbo 给 Dubbo Star。

搜索关注官方微信公众号:Apache Dubbo,了解更多业界最新动态,掌握大厂面试必备 Dubbo 技能

Dubbo 入门系列之快速部署一个微服务应用的更多相关文章

  1. spring cloud 入门,看一个微服务框架的「五脏六腑」

    Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件. 注:Spring Boot 简单理解就是简化 Spring 项目的搭建.配置.组 ...

  2. webpack快速入门——webpack3.X 快速上手一个Demo

    1.进入根目录,建两个文件夹,分别为src和dist 1).src文件夹:用来存放我们编写的javascript代码,可以简单的理解为用JavaScript编写的模块. 2).dist文件夹:用来存放 ...

  3. 使用 Sealos 在 3 分钟内快速部署一个生产级别的 Kubernetes 高可用集群

    本文首发于:微信公众号「运维之美」,公众号 ID:Hi-Linux. 「运维之美」是一个有情怀.有态度,专注于 Linux 运维相关技术文章分享的公众号.公众号致力于为广大运维工作者分享各类技术文章和 ...

  4. Knative 实战:一个微服务应用的部署

    作者 | 元毅 阿里云智能事业群高级开发工程师 在 Istio 中提供了一个 Bookinfo 的示例,用于演示微服务之间的调用,那么如何在 Knative 中部署这个示例呢?本文将会给大家介绍一下在 ...

  5. 快速搭建 SpringCloud 微服务开发环境的脚手架

    本文适合有 SpringBoot 和 SpringCloud 基础知识的人群,跟着本文可使用和快速搭建 SpringCloud 项目. 本文作者:HelloGitHub-秦人 HelloGitHub ...

  6. CODING DevOps 系列第五课:微服务测试——微服务下展开体系化的微服务测试

    微服务测试的痛点与挑战 这张图可以形象地展示单体服务和微服务的对比,单体应用就像左边巨大的集装箱,软件模块和应用都包括其中:而微服务就像是由一个小集装箱组成,微小的服务组成一个庞大.完整的系统.单体服 ...

  7. 从 Spring Cloud 看一个微服务框架的「五脏六腑」

    原文:https://webfe.kujiale.com/spring-could-heart/ Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构 ...

  8. Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务

    Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具:Spr ...

  9. 一个微服务+DDD(领域驱动设计)的代码结构示例

    前有幸拜读过诸多大神关于DDD的实现落地等文章,学习较多,受益匪浅,在此推荐 : https://www.cnblogs.com/hafiz/p/9388334.htmlhttps://blog.cs ...

  10. 从 Spring Cloud 看一个微服务框架的「五脏六腑」(转)

    Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件. 本文将从 Spring Cloud 出发,分两小节讲述微服务框架的「五脏六腑」: ...

随机推荐

  1. SpringBoot 解决跨域问题代码

    package com.example.demo.gs; import org.springframework.context.annotation.Configuration; import jav ...

  2. PyCharm配置远程Docker环境

    1. docker 配置 使用-p参数暴露一个端口用于ssh连接. docker run -itd --name wangchao_paddle --gpus all -p 8899:8888 -p ...

  3. disk磁盘分区软件使用教程,磁盘扩容无损备份

    前几天,因为我的笔记本电脑C盘D盘全红了,趁着双11固态降价,赶紧买了一张三星980 500g 给我的拯救者插上了,加上原来的500g,总共1T,已经够用了. 不得不说拯救者系列预留的1个M.2固态插 ...

  4. Spring Boot 应用的热部署配置

    前言 所谓热部署,简单来说,就是代码修改后不需重启项目就可自动加载出新的内容. 注意:热部署在 debug 调试模式下才生效! IDEA 配置 在 IDE(IDEA)中开启相关项目自动构建选项 开启编 ...

  5. Hexo多台电脑同步

    如果换了电脑该如何同步Hexo的源文件?把hexo文件从一个电脑cope到另外一个电脑吗?答案肯定不是这样的,因为这里面有好多依赖包,好几万个文件呢,这样显然不合理. 本文提供一种多台电脑同步源文件的 ...

  6. 死磕面试系列,Java到底是值传递还是引用传递?

    Java到底是值传递还是引用传递? 这虽然是一个老生常谈的问题,但是对于没有深入研究过这块,或者Java基础不牢的同学,还是很难回答得让人满意. 可能很多同学能够很轻松的背出JVM.分布式事务.高并发 ...

  7. JavaWeb4

    1. Filter 1.1 概述 Filter:过滤器 Servlet.Filter和Listener称为Web的三大组件 生活中的过滤器:净水器.空气净化器.土匪 web中的过滤器:当访问服务器的资 ...

  8. Oracle数据库的导出和导入

    本次数据库的导入导出操作是导出公司环境的Oracle数据库,再导入本地数据库,采用impdp和expdp命令进行导入导出操作. 一.导出52数据库 1.用system用户登录到数据库,查看是否有创建d ...

  9. mycat搭建

    搭建mycat 一.准备工作 1.确保jdk已安装成功,并且jdk版本选用1.7以上版本 2.准备一台新的主机mysql_mycat放到master的前面做代理 mycat ip 192.168.23 ...

  10. 【网络】内网穿透方案&FRP内网穿透实战(基础版)

    目录 前言 方案 方案1:公网 方案2:第三方内网穿透软件 花生壳 cpolar 方案3:云服务器做反向代理 FRP简介 FRP资源 FRP原理 FRP配置教程之SSH 前期准备 服务器配置 下载FR ...