关于后端:Dubbo-入门系列之快速部署一个微服务应用

29次阅读

共计 8218 个字符,预计需要花费 21 分钟才能阅读完成。

本文将基于 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 技能

正文完
 0