本博客的例子代碼可以在github找到下載鏈接:代碼下載
SpringBoot、SpringCloud Alibaba系列博客專欄:鏈接
1、分布式理論
1.1、分布式基本定義
《分布式系統原理與范型》定義:
“分布式系統是若干獨立計算機的集合,這些計算機對於用戶來說就像單個相關系統”
分布式系統(distributed system)是建立在網絡之上的軟件系統。
1.2、架構發展演變
架構的發展是由最初的單一應用架構構建的,一般就是ORM框架方便數據庫操作。
不過隨着系統越來越復雜,單一應用架構會變得難以維護,所以架構逐漸演變出了垂直應用架構,所謂垂直應用架構其實就是安裝業務模板進行拆分,比如可以安裝業務將一個電商系統分為訂單模塊,用戶信息管理模塊,商品管理模塊等等,這時候MVC框架就派上用場,MVC框架可以協助系統更好的按業務拆分,不過業務拆分后雖然是比單一應用架構更好維護了。
不過隨着系統越來約復雜,發現很多共用的模塊很難復用起來,這時候分布式服務架構登場了,分布式架構是將一些核心業務抽取出來,作為獨立的服務,逐漸形成穩定的服務中心,當應用需要時,就去服務中心調服務就可以,而實現這種服務注冊的肯定是RPC框架了。
當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增加一個調度中心基於訪問壓力實時管理集群容量,提高集群利用率,這時候就需要流動計算架構(SOA)[ Service Oriented Architecture],用於提高機器利用率的資源調度,SOA是一個治理中心,綜上所述,到目前,軟件系統架構演變經歷了:單一應用架構->垂直應用架構->分布式應用架構->流動計算架構,下面Dubbo官網的圖片可以很好的描述
1.3、什么是RPC?
RPC概念
RPC【Remote Procedure Call】是指遠程過程調用,是一種進程間通信方式,他是一種技術的思想,而不是規范。它允許程序調用另一個地址空間(通常是共享網絡的另一台機器上)的過程或函數,而不用程序員顯式編碼這個遠程調用的細節。
RPC核心模塊
RPC有兩個核心模塊:通信和序列化
2、什么是Dubbo框架?
2.1、Apache Dubbo 定義
Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動注冊和發現。
2.2、Dubbo角色
-
Provider:暴露服務的服務提供者
-
Container:服務運行的容器
-
Consumer:調用遠程服務的消費者
-
Registry:服務注冊和發現的注冊中心
-
Minitor:統計服務調用次數和時間的監控中心
2.3、Apache Dubbo原理
Dubbo的服務治理:
Dubbo原理圖片,圖片來自Dubbo官網:
調用過程:
下面根據我的理解說明一下
-
0:服務器容器負責啟動、加載、運行服務提供者
-
1:服務提供者在啟動后就可以向注冊中心暴露服務
-
2:服務消費者在啟動后就可以向注冊中心訂閱想要的服務
-
3:注冊中心向服務消費者返回服務調用列表
-
4:服務消費者基於軟負載均衡算法調用服務提供者的服務,這個服務提供者有可能是一個服務提供者列表,調用那個服務提供者就是根據負載均衡來調用了
-
5:服務提供者和服務消費者定時將保存在內存中的服務調用次數和服務調用時間推送給監控中心
3、Dubbo Spring Cloud
3.1 概念定義
Spring Cloud Alibaba Dubbo是Spring Cloud Alibaba項目中的一個,擴展了分布式服務調用能力,不僅能使 Apache Dubbo 和 OpenFeign 共存,還允許 Spring Cloud 標准調用底層通過 Dubbo 支持的通訊協議傳輸
3.2、功能特性對比
功能特征直接引用官網的歸納:
4、實驗環境准備
- 環境准備:
- 64bit JDK 1.8
- SpringBoot2.3.7.RELEASE
- SpringCloud(Hoxton.SR9)
- SpringCloudAlibaba2.2.2.RELEASE
- Maven 3.2+
- 開發工具
- IntelliJ IDEA
- smartGit
5、API工程創建
使用maven命令
mvn archetype:generate -DgroupId=com.example.springcloud -DartifactId=dubbo-sample-api -Dversion=0.0.1-SNAPSHOT -DinteractiveMode=false
也可以自己創建一個maven項目
創建好的pom配置文件參考:
<?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>
<groupId>com.example.springcloud</groupId>
<artifactId>artifact-dubbo-sample-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>artifact-dubbo-sample-api</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
寫個api接口:
package com.example.springcloud.api.service;
/**
* <pre>
* ApiService
* </pre>
*
* <pre>
* @author mazq
* 修改記錄
* 修改后版本: 修改人: 修改日期: 2021/01/19 14:57 修改內容:
* </pre>
*/
public interface ApiService {
String echo(String message);
}
6、啟動Nacos服務中心
詳情可以參考官網:https://nacos.io/zh-cn/docs/quick-start.html,需要先下載nacos服務端源碼,下載源碼后編譯啟動項目:
window+R啟動cmd窗口,cd到nacos server的bin目錄,linux系統直接使用cd ${nacos_server_home}/bin
./startup.sh -m standalone
window系統使用命令startup.cmd -m standalone
啟動成功,訪問:http://127.0.0.1:8848/nacos,賬號密碼都是nacos
登錄成功,來到主頁:
7、服務提供者工程創建
新建項目,使用阿里的service url:
選擇jdk版本,打包方式:
選擇組件:
自動生成項目:加上@EnableDiscoveryClient
支持服務注冊到nacos
package com.example.springcloud.provider.nacosdiscovery;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Configuration;
@EnableDiscoveryClient
@Configuration
public class NacosDiscoveryConfiguration {
}
使用@DubboService
提供dubbo服務:
package com.example.springcloud.provider.service;
import com.example.springcloud.api.service.ApiService;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.annotation.Service;
/**
* <pre>
* EchoServiceImpl
* </pre>
*
* <pre>
* @author mazq
* 修改記錄
* 修改后版本: 修改人: 修改日期: 2021/01/19 15:13 修改內容:
* </pre>
*/
@DubboService
public class EchoServiceImpl implements ApiService {
@Override
public String echo(String message) {
return String.format("echo:%s",message);
}
}
application.properties配置:
# 應用名稱
spring.application.name=dubbo-provider-sample
# dubbo 協議
dubbo.protocol.id=dubbo
dubbo.protocol.name=dubbo
# dubbo 協議端口( -1 表示自增端口,從 20880 開始)
dubbo.protocol.port=-1
# Dubbo 消費端訂閱服務端的應用名,多個服務提供者用逗號分隔
# 這里訂閱"自己",會被忽略掉,請根據實際情況添加
dubbo.cloud.subscribed-services=dubbo-provider-sample
# dubbo 服務掃描基准包
dubbo.scan.base-packages=com.example.springcloud.provider
# Actuator Web 訪問端口
management.server.port=8082
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
# 應用服務 WEB 訪問端口
server.port=8080
# Nacos幫助文檔: https://nacos.io/zh-cn/docs/concepts.html
# Nacos認證信息
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
# Nacos 服務發現與注冊配置,其中子屬性 server-addr 指定 Nacos 服務器主機和端口
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
# 注冊到 nacos 的指定 namespace,默認為 public
spring.cloud.nacos.discovery.namespace=public
啟動項目,到nacos服務查看服務
8、服務消費者工程創建
新建一個dubbo-consumer-sample服務消費者工程,創建過程和服務提供者工程一樣,不過配置需要進行修改,避免端口沖突
# 應用名稱
spring.application.name=dubbo-consumer-sample
# 應用服務 WEB 訪問端口
server.port=9090
# Actuator Web 訪問端口
management.server.port=9091
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
# Nacos幫助文檔: https://nacos.io/zh-cn/docs/concepts.html
# Nacos認證信息
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
# Nacos 服務發現與注冊配置,其中子屬性 server-addr 指定 Nacos 服務器主機和端口
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
# 注冊到 nacos 的指定 namespace,默認為 public
spring.cloud.nacos.discovery.namespace=public
# Dubbo服務配置
# dubbo 協議
dubbo.protocol.id=dubbo
dubbo.protocol.name=dubbo
# dubbo 協議端口( -1 表示自增端口,從 20880 開始)
dubbo.protocol.port=-1
# Dubbo 消費端訂閱服務端的應用名,多個服務提供者用逗號分隔
dubbo.cloud.subscribed-services=dubbo-provider-sample
使用@DubboReference
訂閱服務:
package com.example.springcloud.consumer;
import com.example.springcloud.api.service.ApiService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class DubboConsumerSampleApplication {
@DubboReference
private ApiService echoService;
@GetMapping("/echo")
public String echo(String message) {
return echoService.echo(message);
}
public static void main(String[] args) {
SpringApplication.run(DubboConsumerSampleApplication.class, args);
}
}
linux測試接口使用命令curl,window直接到瀏覽器或者postman測試:
curl http://127.0.0.1:9090/echo?message=nacos
echo:nacos