@
背景
- 在上篇文章《Spring Cloud Alibaba微服務生態的基礎實踐》中,我們初步瞭解了
Spring Cloud Alibaba
微服務生態體系,並動手實踐了Nacos
與Sentinel
的基本應用。 - 本文將繼續對Spring Cloud Alibaba生態進行探索:研究以
Dubbo
框架作為RPC元件,Nacos
作為服務註冊與發現中心,並整合Sentinel
進行流量控制,搭建微服務的整個過程。
一、專案框架
1.1 採用IDEA和Maven多模組進行專案搭建
1.2 模組管理及版本管理
-父目錄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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>dubbo-api</module>
<module>dubbo-provider</module>
<module>dubbo-consumer</module>
</modules>
<groupId>nacos</groupId>
<artifactId>dubbo</artifactId>
<packaging>pom</packaging>
<version>0.0.1-SNAPSHOT</version>
<description>Dubbo對接Spring Cloud Alibaba專案</description>
<properties>
<java.version>1.8</java.version>
<spring.boot.version>2.2.9.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR1</spring.cloud.version>
<spring.cloud.alibaba.version>2.2.0.RELEASE</spring.cloud.alibaba.version>
<dubbo.version>2.7.6</dubbo.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring cloud Alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
二、微服務公共介面
2.1 定義一個公共介面Api
- 便於微服務提供者與呼叫者共同使用
2.2 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">
<parent>
<artifactId>dubbo</artifactId>
<groupId>nacos</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-api</artifactId>
</project>
2.3 GoodsService介面類
/**
* 商品資訊服務介面-模擬返回商品列表
*/
public interface GoodsService {
// 獲取所有商品資訊
List<Goods> getAllGoods();
}
- Goods商品類
/**
* 商品類
*/
public class Goods implements Serializable {
// 商品名稱
private String name;
// 商品價格
private Integer number;
public Goods(String name, Integer number) {
this.name = name;
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
}
三、微服務提供者
3.1 商品資訊微服務
- 可提供商品資訊及進行獨立部署,供服務消費者進行呼叫
3.2 pom.xml
-
需引入上述定義的微服務公共介面dubbo-api。
-
根據官方文件說明引入
Spring Cloud Alibaba Sentinel
依賴:
-
根據官方文件RPC適配需引入如下依賴:
-
根據官方文件接入
Sentinel
控制檯需引入如下依賴:
<?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">
<parent>
<artifactId>dubbo</artifactId>
<groupId>nacos</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-provider</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- Dubbo api -->
<dependency>
<groupId>nacos</groupId>
<artifactId>dubbo-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Spring Boot dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!-- Dubbo Registry Nacos -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
<!-- Spring Cloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- Sentinel dubbo adapter -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-dubbo-adapter</artifactId>
<version>1.7.1</version>
</dependency>
<!-- dubbo 接入 Sentinel Dashboard -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.3 application.yml專案配置檔案
- 根據官方文件配置
Sentinel
控制檯
- 根據官方文件配置
Nacos
服務註冊地址及Dubbo
協議等(已轉化為yml格式)
server:
port: 9001
spring:
application:
name: nacos-duboo-goods-service
# Spring Cloud Alibaba Sentinel DashBoard
cloud:
sentinel:
transport:
port: 8719
dashboard: 172.16.109.118:8080
dubbo:
# 掃描包地址
scan:
base-packages: nacos.dubbo
# 協議
protocol:
name: dubbo
port: -1
# 註冊地址
registry:
address: nacos://172.16.109.118:8848/
# 版本號
service:
version: 1.0.0
3.4 GoodsServiceImpl商品資訊微服務實現類
/**
* 商品資訊服務實現-模擬返回商品列表
*/
// 注意需使用正確的包 org.apache.dubbo.config.annotation.Service
@Service(version = "${service.version}")
public class GoodsServiceImpl implements GoodsService {
private static final Logger logger = LoggerFactory.getLogger(GoodsServiceImpl.class);
@Override
public List<Goods> getAllGoods() {
List<Goods> goods = new ArrayList<>();
goods.add(new Goods("電腦", 10));
goods.add(new Goods("手機", 20));
goods.add(new Goods("書籍", 30));
logger.info(RpcContext.getContext().getRemoteHost()+"正在呼叫服務..");
return goods;
}
}
- ProviderApplication啟動類
/**
* 啟動類
*/
@SpringBootApplication
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
四、微服務呼叫者
4.1 對外提供Restful介面
- 使用該介面可以通過
Nacos
發現商品資訊微服務並進行呼叫,最終組合形成使用者商品資訊返回。
4.2 pom.xml
- 需引入上述定義的微服務公共介面dubbo-api
<?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">
<parent>
<artifactId>dubbo</artifactId>
<groupId>nacos</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-consumer</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- Dubbo api -->
<dependency>
<groupId>nacos</groupId>
<artifactId>dubbo-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Spring Boot 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.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!-- Dubbo Registry Nacos -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4.3 application.yml專案配置檔案
server:
port: 9002
spring:
application:
name: nacos-dubbo-user-consumer
dubbo:
registry:
address: nacos://172.16.109.118:8848/
service:
version: 1.0.0
4.4 UserConsumer Restful api介面
- 使用者消費者呼叫商品資訊微服務
/**
* Restful api介面:使用者消費者呼叫商品資訊微服務
*/
@RestController
public class UserConsumer {
@Reference(version= "${service.version}")
private GoodsService goodsService;
@GetMapping("/userGoods")
public User getUserGoods() {
User user = new User();
// 通過GoodsService介面呼叫商品微服務
try {
List<Goods> goods = goodsService.getAllGoods();
user.setName("jack");
user.setGoods(goods);
} catch (Exception e){
throw new RuntimeException(e.getMessage());
}
return user;
}
}
- 使用者類
/**
* 使用者類
*/
public class User implements Serializable {
private String name;
private List<Goods> goods;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Goods> getGoods() {
return goods;
}
public void setGoods(List<Goods> goods) {
this.goods = goods;
}
}
- 啟動類
/**
* 啟動類
*/
@SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
五、啟動微服務
- 啟動微服務提供者及微服務呼叫者,通過微服務呼叫者Restful介面訪問,即呼叫一次微服務,並分別使用
Nacos
控制檯與Sentinel
控制檯進監測
-
Nacos
控制檯
-
Sentinel
控制檯
六、使用JMeter
測試微服務
6.1 建立微服務測試專案
- 建立一個執行緒組,設定20個併發請求迴圈執行:
- 建立一個HTTP請求,根據服務呼叫者的Resuful介面設定請求地址:
- 再建立一個聚合報告及表格,便於觀察測試結果:
- 啟動
JMeter
,觀察Sentinel
控制檯
6.2 流量控制
- 通過流控規則配置對
Dubbo
服務進行流量控制
- 將QPS單機上限值設為10,模式設為直接,流控效果設為快速失敗。以上資訊儲存後會在流控規則增加以上設定。
- 再次啟動
JMeter
,並通過Sentinel
控制檯監測
- 在Sentinel控制檯監測到通過的QPS為上限10個,併產生大量的拒絕的QPS
- 在JMeter結果表格中同樣會監測到失敗請求資訊
- 將上述流控規則中的流控效果從快速失敗改為排隊等待,併除低
JMeter
併發執行緒數,再次觀察流控效果
- 通過
Sentinel
控制檯可以監測到QPS被限制在10,且沒有拒絕的QPS
- 通過
JMeter
聚合報告同樣可以監測到吞吐量為10/sec,且沒有異常發生。
小結
- pom檔案引入
Spring Cloud Alibaba
、Dubbo
、Nacos
及Sentinel
相關依賴會遇到很多坑,請大家參考本工程專案的版本進行測試,或仔細閱讀官方文件。 Dubbo
融合Nacos
成為註冊中心的操作步驟非常簡單,可以完美取代ZooKeeper
。- 在
Spring Cloud Alibaba
中Dubbo
微服務使用Sentinel
實現限流,我們只需要通過Sentinel
控制檯中的流控規則等配置即可,Sentinel
會通過這些規則自動保護這些微服務。 - 以上介紹的只是
Sentinel
的一個最簡單的場景 —— 限流。Sentinel
還可以處理更復雜的各種情況,比如降級熔斷、冷啟動、請求勻速等,具體可以參考Sentine
l 文件。