分布式、微服务与 RPC
什么是分布式?分布式就是将一个应用程序的功能拆分到多个独立的进程中,每个进程都运行在不同的机器上,通过网络连接起来,这样就形成了一个分布式的系统。
什么是微服务架构?微服务架构将应用程序拆分成一组小的服务(微服务),每个服务运行在自己的进程中,服务之间通过轻量级的通信机制互相通信。
什么是 RPC?RPC(Remote Procedure Call)远程过程调用,微服务架构中,服务与服务之间通过网络通信的过程。比如 A 服务调用 B 服务中的方法的过程,就叫 RPC。
什么是 Dubbo
Dubbo 是一款高性能、轻量级的开源 Java RPC 框架。主要解决了微服务之间的通信问题,它提供了一套类似于本地调用的远程调用方式。
Dubbo 架构
角色说明:
- 服务提供者(Provider):服务提供者就是实现了服务接口的类。服务提供者启动时,向注册中心注册自己提供的服务。
- 服务消费者(Consumer):服务消费者就是调用远程服务的类。服务消费者启动时,向注册中心订阅自己所需的服务。
- 注册中心(Registry):注册中心存储服务提供者的地址信息。服务提供者的地址发生变化时,注册中心更新服务提供者地址信息,并通知服务消费者。Dubbo 官方推荐使用 ZooKeeper 作为注册中心。
- 监控中心(Monitor):监控中心主要用于监控服务的运行状态,以便出现问题时,能及时发现和解决。
- 容器(Container):服务运行容器,一般就是 Spring 容器。
交互过程说明:
- 虚线都是异步访问,实线都是同步访问
- 蓝色虚线:在启动时完成的功能
- 红色虚线(实线)都是程序运行过程中执行的功能
调用关系说明:
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
示例
安装并启动 Zookeeper
我们用 Zookeeper 作为注册中心,所以先安装并启动 Zookeeper。
安装 Zookeeper:
- 安装 JDK(略)
- 把 Zookeeper 的压缩包(这里是 zookeeper-3.4.6.tar.gz)上传到 Linux
- 解压缩压缩包:
tar -zxvf zookeeper-3.4.6.tar.gz
,假设解压到/usr/local/zookeeper-3.4.6
- 进入 zookeeper-3.4.6 目录,创建 data 目录:
mkdir data
- 进入 conf 目录,把 zoo_sample.cfg 改名为 zoo.cfg:
mv zoo_sample.cfg zoo.cfg
- 打开 zoo.cfg 文件,修改 dataDir 属性:
dataDir=/usr/local/zookeeper-3.4.6/data
进入 Zookeeper 的 bin 目录,可管理 Zookeeper 服务:
- 启动服务:
./zkServer.sh start
- 停止服务:
./zkServer.sh stop
- 查看服务状态:
./zkServer.sh status
运行./zkServer.sh start
将其启动。
项目结构
下面是示例工程的项目结构。包含父工程dubbo
,接口模块dubbo-api
、服务消费者模块dubbo-consumer
和服务提供者模块dubbo-provider
。
dubbo # 父工程
├─ dubbo-api # 接口模块
│ ├─ src
│ │ └─ main
│ │ └─ java
│ │ └─ com
│ │ └─ ming
│ │ └─ api
│ │ └─ service
│ │ └─ HelloService.java
│ └─ pom.xml
├─ dubbo-consumer # 服务消费者模块
│ ├─ src
│ │ └─ main
│ │ ├─ java
│ │ │ └─ org
│ │ │ └─ ming
│ │ │ └─ consumer
│ │ │ ├─ controller
│ │ │ │ └─ HelloController.java
│ │ │ └─ DubboConsumerApplication.java
│ │ └─ resources
│ │ └─ application.yml
│ └─ pom.xml
├─ dubbo-provider # 服务提供者模块
│ ├─ src
│ │ └─ main
│ │ ├─ java
│ │ │ └─ org
│ │ │ └─ ming
│ │ │ └─ provider
│ │ │ ├─ service
│ │ │ │ └─ HelloServiceImpl.java
│ │ │ └─ DubboProviderApplication.java
│ │ └─ resources
│ │ └─ application.yml
│ └─ pom.xml
└─ pom.xml
父工程
父工程仅包含一个 pom.xml 文件,用于管理子模块的依赖。
<?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>org.ming</groupId>
<artifactId>dubbo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>dubbo-api</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<dubbo.version>2.0.0</dubbo.version>
<dubbo.api.version>1.0-SNAPSHOT</dubbo.api.version>
<zkclient.version>0.11</zkclient.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
</dependencies>
</project>
接口模块
接口模块包含一个接口和一个 pom.xml 文件。
接口模块的作用是给出 API,在服务提供者与服务消费者之间建立契约。后面会看到,服务提供者会实现接口模块中的接口,服务消费者会调用对应接口中的方法。
package com.ming.api.service;
/**
* Hello 服务接口
*/
public interface HelloService {
/**
* 问好
*
* @param name 姓名
* @return 问好
*/
String sayHello(String name);
}
<?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>
<parent>
<groupId>org.ming</groupId>
<artifactId>dubbo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>dubbo-api</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
服务提供者模块
服务提供者模块包含服务实现类、application.yml 和 pom.xml 文件。
服务实现类中使用了@Service
注解,该注解用于标注一个类为一个 Dubbo 服务。
application.yml 中配置了 Zookeeper 地址,pom.xml 中引入了 dubbo、Zookeeper 相关依赖和dubbo-api
。
package org.ming.provider.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.ming.api.service.HelloService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* Hello 服务实现
*/
@Service
@Component
@Slf4j
public class HelloServiceImpl implements HelloService {
/**
* 问好
*
* @param name 姓名
* @return 问好
*/
@Override
public String sayHello(String name) {
log.info("someone is calling me......");
return "say hello to: " + name;
}
}
server:
port: 9090
spring:
dubbo:
application:
name: spring-boot-demo-dubbo-provider
registry: zookeeper://localhost:2181
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.ming</groupId>
<artifactId>dubbo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>dubbo-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dubbo-provider</name>
<description>dubbo-provider</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dubbo-api</artifactId>
<version>${dubbo.api.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>org.ming.provider.DubboProviderApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
服务消费者模块
服务消费者模块包含控制器类、application.yml 和 pom.xml 文件。
控制器类中使用了@Reference
注解,该注解用于将服务提供者的接口实现注入到控制器类中。
application.yml 中配置了 Zookeeper 地址,pom.xml 中引入了 dubbo、Zookeeper 相关依赖和dubbo-api
。
package org.ming.consumer.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.ming.api.service.HelloService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Hello 服务 API
*/
@RestController
@Slf4j
public class HelloController {
@Reference
private HelloService helloService;
@GetMapping("/sayHello")
public String sayHello(@RequestParam(defaultValue = "ming") String name) {
log.info("i'm ready to call someone......");
return helloService.sayHello(name);
}
}
server:
port: 8080
spring:
dubbo:
application:
name: spring-boot-demo-dubbo-consumer
registry: zookeeper://localhost:2181
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.ming</groupId>
<artifactId>dubbo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>dubbo-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dubbo-consumer</name>
<description>dubbo-consumer</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>dubbo-api</artifactId>
<version>${dubbo.api.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>org.ming.consumer.DubboConsumerApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
启动服务并测试
启动服务提供者、服务消费者模块,访问 http://localhost:8080/sayHello?name=ming,收到如下响应说明成功:
say hello to: ming
标签:集成,Dubbo,服务,SpringBoot,dubbo,spring,boot,服务提供者,org From: https://www.cnblogs.com/Higurashi-kagome/p/17936690.html参考:
spring-boot-demo/demo-dubbo at master · xkcoding/spring-boot-demo(代码基本复制自这里)
超详细,新手都能看懂!使用 SpringBoot+Dubbo 搭建一个简单的分布式服务
黑马程序员 Dubbo 快速入门,Java 分布式框架 dubbo 教程
另外使用了“通义灵码”来获取编写建议。