本文将基于 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. 【多服务场景化解决方案】AR虚拟技术助力智能家装

    ​ 1 .介绍 总览 本应用采用了华为图形引擎服务的AR虚拟技术,您可以在手机相机里摆放想要购置的家具家电,交互式体验让您可以轻松操控它们的3D图例,以此来确定这些家具家电是否适合摆放在您的家里. 特 ...

  2. SpringBoot 阶段测试 1

    SpringBoot 阶段测试 1 目录 SpringBoot 阶段测试 1 1.使用JDK8新语法完成下列集合练习: 1.1 List中有1,2,3,4,5,6,7,8,9几个元素要求; (1) 将 ...

  3. cameralink base 接口双通道任意图像数据源模拟

    设备说明 PCIe-CLS2000是基于PCIe 接口的2通道 camera link base接口图像模拟源,适用于图像数据源模拟.接收处理平台测试等场景. PCIe Gen2x4/x8 接口,支持 ...

  4. springMVC实现文件的上传和下载

    文件的下载功能 @RequestMapping("/testDown")public ResponseEntity<byte[]> testResponseEntity ...

  5. Python基础之模块:5、 第三方模块 requests模块 openpyxl模块

    目录 一.第三方模块的下载与使用 1.什么是第三方模块 2.如何安装第三方模块 方式一:pip工具 方式二:pycharm中下载 3.注意事项 1.报错并有警告信息 2.报错,提示关键字 3.报错,无 ...

  6. cordon节点,drain驱逐节点,delete 节点

    目录 一.系统环境 二.前言 三.cordon节点 3.1 cordon节点概览 3.2 cordon节点 3.3 uncordon节点 四.drain节点 4.1 drain节点概览 4.2 dra ...

  7. 还在为数据库事务一致性检测而苦恼?让Elle帮帮你,以TDSQL为例我们测测 | DB·洞见#7

    数据库用户通常依赖隔离级别来确保数据一致性,但很多数据库却并未达到其所表明的级别.主要原因是:一方面,数据库开发者对各个级别的理解有细微差异:另一方面,实现层面没有达到理论上的要求. 用户在使用或开发 ...

  8. java 定时开始执行程序

    package com.zx.ps.web.gzdb; import java.util.Calendar; import java.util.Date; import java.util.Timer ...

  9. React Server Component: 混合式渲染

    作者:谢奇璇 React 官方对 Server Comopnent 是这样介绍的: zero-bundle-size React Server Components. 这是一种实验性探索,但相信该探索 ...

  10. Day30.1:Math的常用方法

    Math 1.1 Math概述 Math类在Java.lang包下,不需要导包 public final class Math extends Object Math含有基本的数字运算方法,没有构造器 ...