SpringBoot中使用Docker、Zipkin構建模組化

banq發表於2024-04-26

這篇博文深入探討了如何構建Spring Boot應用程式、利用Docker一致的本地環境、Zipkin進行跟蹤以及實現 100% 程式碼覆蓋率的策略。

我們將探討設定基於功能的模組化bookstore應用程式作為示例。我們將利用JPA資料永續性、SwaggerAPI 文件、Postgres資料庫、Jacoco程式碼覆蓋率以及Spring Modulith來記錄應用程式結構。

先決條件:

  1. 您的系統上安裝了 Java 21。您可以使用sdkman安裝,並選擇 Java 21 https://sdkman.io/usage
  2. Docker並Docker Compose安裝用於設定本地環境。

克隆https://github.com/dmakariev/examples儲存庫

應用程式的結構
在構建複雜系統時,結構良好的方法對於管理可擴充套件性和可維護性至關重要。我們的bookstore應用程式分為幾個不同的模組,每個模組都經過精心設計,用於處理業務的特定方面。這種分段有利於獨立開發並簡化維護,從而增強整體系統的穩健性。

高層結構
bookstore應用程式包括:

  • 庫存模組Inventory :該模組的任務是管理庫存水平以及與書籍庫存的互動,確保系統地處理庫存變化的實時更新。它是跟蹤書店內庫存情況的支柱。
  • 通知模組Notification :設計用於處理事件處理,該模組響應StockAddedEvent和StockRemovedEvent等事件。它向系統發出警報並通知相關利益相關者,從而促進跨應用程式的有效溝通。
  • 訂單模組Order :該模組管理訂單處理的所有方面,從最初的下單到最終的履行。它與庫存模組無縫整合,確保庫存水平實時準確調整,保持訂單需求和庫存供應之間的平衡。
  • 產品模組Product :負責維護產品的全面記錄,包括書籍和作者的詳細資訊。該模組向其他模組提供關鍵資料,確保整個平臺的一致性和準確性。
  • 使用者模組User :該模組專注於所有使用者與系統的互動,管理從身份驗證到配置檔案管理的任務。它保護使用者資訊,同時確保無縫、高效的使用者體驗。

這種結構化的模組方法不僅簡化了開發和除錯,還增強了應用程式對不斷變化的業務需求和技術進步的適應性。每個模組都能獨立執行,但又能與其他模組有效通訊,從而確保應用程式架構的內聚性和穩健性。

最佳實踐是遵循DDD 不同模組代表不同界限上下文 

應用程式的資料夾結構
應用程式採用結構化的層次結構,以便於明確劃分關注點和提高可維護性:

├── Dockerfile
├── compose.yaml
├── lombok.config
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
    ├── main
    │   ├── asciidoc
    │   │   └── index.adoc
    │   ├── java
    │   │   └── com
    │   │       └── makariev
    │   │           └── examples
    │   │               └── spring
    │   │                   └── bookstore
    │   │                       ├── BookstoreApplication.java
    │   │                       ├── config
    │   │                       │   ├── GlobalRestControllerAdvice.java
    │   │                       │   └── SpringdocConfig.java
    │   │                       ├── inventory
    │   │                       │   ├── Inventory.java
    │   │                       │   ├── InventoryController.java
    │   │                       │   ├── InventoryRepository.java
    │   │                       │   ├── InventoryService.java
    │   │                       │   ├── StockAddedEvent.java
    │   │                       │   └── StockRemovedEvent.java
    │   │                       ├── notification
    │   │                       │   └── NotificationService.java
    │   │                       ├── order
    │   │                       │   ├── Order.java
    │   │                       │   ├── OrderController.java
    │   │                       │   ├── OrderItem.java
    │   │                       │   ├── OrderRepository.java
    │   │                       │   └── OrderService.java
    │   │                       ├── product
    │   │                       │   ├── Author.java
    │   │                       │   ├── AuthorController.java
    │   │                       │   ├── AuthorRepository.java
    │   │                       │   ├── AuthorService.java
    │   │                       │   ├── Book.java
    │   │                       │   ├── BookController.java
    │   │                       │   ├── BookRepository.java
    │   │                       │   ├── BookService.java
    │   │                       │   └── BookSummary.java
    │   │                       └── user
    │   │                           ├── Customer.java
    │   │                           ├── CustomerController.java
    │   │                           ├── User.java
    │   │                           ├── UserController.java
    │   │                           ├── UserRepository.java
    │   │                           └── UserService.java
    │   └── resources
    │       ├── application.properties
    │       ├── data.sql
    │       ├── schema.sql
    │       └── static
    │           └── index.html
    └── test
        ├── java
        │   └── com
        │       └── makariev
        │           └── examples
        │               └── spring
        │                   └── bookstore
        │                       ├── BookstoreApplicationTests.java
        │                       ├── ModularityTests.java
        │                       ├── inventory
        │                       │   ├── InventoryControllerIT.java
        │                       │   ├── InventoryControllerTest.java
        │                       │   ├── InventoryRepositoryTest.java
        │                       │   └── InventoryServiceTest.java
        │                       ├── order
        │                       │   ├── OrderControllerIT.java
        │                       │   ├── OrderControllerTest.java
        │                       │   ├── OrderRepositoryTest.java
        │                       │   └── OrderServiceTest.java
        │                       ├── product
        │                       │   ├── AuthorControllerIT.java
        │                       │   ├── AuthorControllerTest.java
        │                       │   ├── AuthorRepositoryTest.java
        │                       │   ├── AuthorServiceTest.java
        │                       │   ├── BookControllerIT.java
        │                       │   ├── BookControllerTest.java
        │                       │   ├── BookRepositoryTest.java
        │                       │   └── BookServiceTest.java
        │                       └── user
        │                           ├── CustomerControllerIT.java
        │                           ├── CustomerControllerTest.java
        │                           ├── UserControllerIT.java
        │                           ├── UserControllerTest.java
        │                           ├── UserRepositoryTest.java
        │                           └── UserServiceTest.java
        └── resources
            ├── application-integration-test.properties
            └── application-test.properties


關鍵資料夾和檔案說明

  • /src/main/java/:包含應用程式的所有 Java 原始檔,按模組(庫存、通知、訂單、產品、使用者)分類。每個模組包括各自的控制器、服務、儲存庫和實體。
  • /src/main/resources/:包含配置檔案(如 application.properties)、資料庫初始化指令碼(data.sql 和 schema.sql)以及靜態資源(index.html)。
  • /src/test/:包含應用程式的所有測試用例,結構與主 Java 原始碼目錄類似。其中包括單元測試、整合測試和測試環境的配置檔案。
  • Dockerfile 和 compose.yaml:定義用於構建應用程式映象和使用 Docker Compose 設定多容器環境的 Docker 配置。
  • pom.xml:Maven 配置檔案,用於管理依賴關係、外掛以及構建應用程式所需的其他配置細節。
  • lombok.config:Lombok 庫的配置檔案,該庫可幫助減少 Java 應用程式中的模板程式碼。

這種資料夾結構支援簡潔有序的開發環境,便於導航和維護應用程式程式碼庫。每個元件都按邏輯放置,以提高可理解性和可管理性,促進軟體開發的最佳實踐。

構建應用程式
構建 Spring Boot 應用程式涉及幾個關鍵步驟和工具,旨在簡化開發和測試流程。應用程式的核心是利用 Spring Boot Maven 外掛,它簡化了應用程式的打包和執行。對於整合測試,我們使用 Maven Failsafe 外掛,確保在構建生命週期的整合測試階段進行整合測試,而不會影響 Surefire 外掛執行的早期單元測試。

標準構建命令
為了有效管理構建生命週期,我們使用了幾個針對不同開發階段定製的 Maven 命令:

單元測試:執行所有單元測試,同時跳過整合測試:
$ ./mvnw clean test

打包:建立一個可執行的 jar 檔案,而不執行整合測試:
$ ./mvnw clean package

整合測試:包括整合測試的徹底驗證:
$ ./mvnw verify

完整構建:執行包含文件和程式碼覆蓋率分析的完整構建:
$ ./mvnw clean install -Pdocs,coverage


執行應用程式
出於開發目的,應用程式可以直接使用 Spring Boot 的嵌入式伺服器執行:
$ ./mvnw spring-boot:run

或者,構建後,可以執行打包的應用程式:
$ java -jar ./target/bookstore-0.0.1-SNAPSHOT.jar

您還可以為不同的資料庫指定執行時配置:

  • Postgres,它需要 Postgres 的 localhost 例項
    $ java -jar \ -Dspring.datasource.url=jdbc:postgresql:<font>//localhost:5432/example \ -Dspring.datasource.username=postgres \ -Dspring.datasource.password=postgres \ -Dspring.jpa.hibernate.ddl-auto=update \ ./target/bookstore-0.0.1-SNAPSHOT.jar<i>
  • 記憶體中的 H2 資料庫
    $ java -jar \ -Dspring.datasource.url=jdbc:h2:mem:example \ ./target/bookstore-0.0.1-SNAPSHOT.jar
  • H2 資料庫檔案系統 - 資料庫資料儲存在檔案中
    $ java -jar \ -Dspring.datasource.url=jdbc:h2:file:./example-db-data \ -Dspring.jpa.hibernate.ddl-auto=update \ ./target/bookstore-0.0.1-SNAPSHOT.jar

其他 Maven 配置檔案

  • docs簡介

docs配置檔案利用asciidoctor-maven-plugin.asciiDoc 檔案生成全面的 HTML 文件src/main/asciidoc。該文件包括詳細的模組描述、互動以及自動生成的 PlantUML 圖以說明應用程式結構。
輸出:文件被編譯為 HTML 並儲存在 中./target/generated-docs/index.html,提供應用程式架構的可訪問且詳細的概述。
  • coverage簡介

該coverage配置檔案在 的幫助下jacoco-maven-plugin,生成有關程式碼覆蓋率的詳細報告,確保跨單元和整合測試的廣泛測試覆蓋率。
輸出:覆蓋率報告放置在 中./target/site/jacoco/index.html,提供一個互動式介面來審查程式碼覆蓋率指標並識別未測試的區域。

配置檔案執行的示例命令

$ ./mvnw clean install -Pdocs
$ ./mvnw clean install -Pcoverage
$ ./mvnw clean install -Pdocs,coverage

這些命令確保我們的開發過程不僅高效而且徹底,提供所有必要的工具和報告以維持高標準的質量和文件。透過整合這些實踐,我們增強了 Spring Boot 應用程式的健壯性和可讀性,使其更易於管理、擴充套件和理解。

將 Docker Compose 整合到 Spring Boot 應用程式中
我們的 Spring Boot 應用程式利用 Docker Compose 來編排多個服務,確保它們部署在一致且可靠的環境中。 Docker Compose的使用方便了服務依賴關係的管理,並簡化了我們本地開發環境中執行的服務的配置。下面簡要概述了 Docker Compose 的配置方式及其管理的服務:

1、Docker Compose 配置
docker-compose.yaml檔案定義了多個服務,包括後端應用程式、PostgreSQL 資料庫、用於資料庫管理的 pgAdmin 以及用於分散式跟蹤的 Zipkin。以下是這些服務的編排方式:

  • 後端服務:配置為從 Dockerfile 構建,該服務在埠 8088 上執行書店後端,該埠對映到主機上的埠 8080。它使用環境變數中指定的憑據和配置連線到 PostgreSQL。資料庫 (db):使用官方 PostgreSQL 映像並將資料儲存在命名卷中,以便在容器重新啟動時保留資料。
  • pgAdmin:提供基於 Web 的資料庫管理介面,可透過埠 5050 訪問。
  • Zipkin:提供跟蹤功能來監視和排除分散式系統中的請求,可透過埠 9411 訪問。

2、部署後訪問服務
一旦docker compose up --build執行,它就會啟動所有配置的服務。以下是可以在本地訪問這些服務的 URL:

  • 應用程式主頁:http://localhost:8080 - 顯示書店應用程式的index.html。
  • Swagger UI:http://localhost:8080/swagger-ui/index.html - 提供所有 RESTful 端點及其操作的詳細檢視,使 API 的開發和測試變得更加容易。
  • pgAdmin : http://localhost:5050 - 透過使用者友好的 Web 介面管理和視覺化資料庫方面。
  • Zipkin UI:http://localhost:9411/zipkin/?serviceName=bookstore - 允許檢視和查詢跟蹤資料,提供對分散式事務的效能和行為的見解。

此 Docker Compose 設定不僅確保應用程式的每個元件都正確配置和互連,而且還提供了一個強大的平臺,用於在模擬生產環境中開發、測試和監控應用程式的效能。

結論
在這篇博文中,我們探討了如何詳細設定和配置基於功能的 Spring Boot 應用程式,以滿足現代應用程式和微服務的複雜要求。

  • 我們的方法強調簡潔的程式碼和簡潔的架構,促進了元件之間的低耦合和高內聚
  • 透過使用 Docker Compose,我們簡化了 PostgreSQL、pgAdmin 和 Zipkin 等基本服務的部署,增強了我們的開發和可觀察性環境。
  • 詳細的文件和高程式碼覆蓋率不僅是我們的理想目標,也是我們勤奮使用 Maven 配置檔案所取得的實際成果。

這種系統化的方法不僅提高了開發效率,還為開發人員提供了有效監控和管理應用程式的強大工具。

這些實踐體現了構建可擴充套件、可維護和高質量軟體的必要標準,確保每個元件既能獨立又能作為整個系統的一部分高效執行。
 

相關文章