2025年6月17日 星期二

Laravel 後端架構設計:擁抱 IaC,提升維護與擴展性

Laravel 後端架構設計:擁抱 IaC,提升維護與擴展性

這份設計旨在提供一個堅固、可擴展且易於維護的 Laravel 後端架構,並深度整合 Infrastructure as Code (IaC) 的概念。透過將基礎設施的配置視為程式碼,我們能實現環境的一致性、自動化部署、以及更快速的故障恢復。

核心原則

  1. 模組化 (Modularity):將應用程式劃分為獨立、可重用的組件。
  2. 鬆耦合 (Loose Coupling):各組件之間減少直接依賴,提高獨立性。
  3. 單一職責原則 (Single Responsibility Principle - SRP):每個組件或類別只負責一項功能。
  4. 基礎設施即程式碼 (Infrastructure as Code - IaC):利用程式碼管理和佈建基礎設施。
  5. 自動化 (Automation):自動化部署、測試和監控流程。
  6. 可觀測性 (Observability):提供足夠的監控和日誌,以便了解系統運行狀況。

1. 應用程式架構 (Laravel Application Architecture)

1.1. DDD (Domain-Driven Design) 或 Hexagonal Architecture (Ports and Adapters) 模式

建議採用 DDD 或 Hexagonal Architecture 的思想來組織 Laravel 應用程式,這能有效分離業務邏輯與技術細節。

  • 領域層 (Domain Layer)

    • Models (Eloquent Models): 代表核心業務實體,但盡量保持精簡,避免在 Model 中撰寫過多業務邏輯。
    • Entities / Aggregates: 具備業務行為的實體,建議獨立於 Eloquent Models 存在,或讓 Eloquent Models 作為持久化層的適配器。
    • Value Objects: 描述領域概念的不可變對象。
    • Domain Services: 跨多個實體或值對象的業務操作。
    • Repositories Interfaces: 定義資料存取介面,例如 UserRepositoryInterface
    • Events: 領域事件,例如 UserRegistered
  • 應用程式層 (Application Layer)

    • Use Cases / Application Services: 處理應用程式特定的流程,協調領域層的物件來完成特定的用例。例如 RegisterUserUseCase
    • Command Bus / Query Bus: 處理命令和查詢,將請求路由到對應的處理器。
    • DTOs (Data Transfer Objects): 在不同層之間傳遞資料的對象。
  • 基礎設施層 (Infrastructure Layer)

    • Repositories Implementations: 實現領域層定義的 Repository 介面,例如 EloquentUserRepository
    • Services (External): 整合第三方服務,如支付閘道、訊息通知等。
    • Database Migrations & Seeders: 資料庫結構和初始資料。
    • Cache Drivers: 快取實作。
    • Queue Drivers: 佇列實作。
    • File Storage Drivers: 檔案儲存實作。
  • 介面層 (Presentation / Interface Layer)

    • Controllers: 處理 HTTP 請求,將請求轉發給應用程式層的 Use Case。
    • API Resources: 格式化 API 回傳資料。
    • Requests (Form Requests): 處理輸入驗證。
    • Routes: 定義 API 端點。

1.2. 目錄結構建議

app/
├── Console/
├── Exceptions/
├── Http/
│   ├── Controllers/
│   ├── Middleware/
│   ├── Requests/
│   └── Resources/
├── Providers/
├── Domain/              # 領域層
│   ├── Entities/
│   ├── Repositories/     # 介面
│   ├── Services/
│   └── Events/
├── Application/         # 應用程式層
│   ├── UseCases/
│   ├── Commands/
│   ├── Queries/
│   ├── DTOs/
│   └── Services/        # 應用層服務
├── Infrastructure/      # 基礎設施層
│   ├── Persistence/
│   │   ├── Eloquent/    # Eloquent Repository 實作
│   │   ├── Migrations/
│   │   └── Seeders/
│   ├── Services/        # 第三方服務整合
│   ├── Cache/
│   ├── Queue/
│   └── Storage/
└── ... 其他 Laravel 預設目錄

1.3. Laravel 特性應用

  • Service Providers: 用於綁定介面到實作,管理服務容器依賴,例如將 UserRepositoryInterface 綁定到 EloquentUserRepository
  • Events & Listeners: 用於處理領域事件和應用程式事件,實現解耦。
  • Queues: 處理耗時操作,如發送郵件、圖像處理等,提高響應速度。
  • Jobs: 將可執行操作封裝成獨立的 Job,可同步或異步執行。
  • Notifications: 用於發送多種通知,如郵件、簡訊、資料庫通知等。
  • Cache: 利用各種快取驅動提升資料讀取效能。
  • Policies & Gates: 管理應用程式權限。
  • API Resources: 統一 API 回傳格式。
  • Migrations & Seeders: 版本控制資料庫架構和初始資料。

2. 基礎設施即程式碼 (Infrastructure as Code - IaC)

IaC 是維護和擴展性的關鍵。它確保了環境的一致性,並實現了自動化部署。

2.1. 基礎設施供應 (Infrastructure Provisioning) 工具

  • Terraform: 強烈推薦使用 Terraform 來管理雲端基礎設施。它支持多種雲服務商(AWS, GCP, Azure 等),並提供 HCL (HashiCorp Configuration Language) 語法,用於聲明式地定義資源。
    • 範例 Terraform 資源:
      • 網路: VPCs, Subnets, Security Groups, Load Balancers (ALB/NLB)。
      • 計算: EC2 Instances, Auto Scaling Groups, ECS/EKS Clusters (容器服務)。
      • 資料庫: RDS Instances (MySQL, PostgreSQL), DynamoDB。
      • 儲存: S3 Buckets, EFS。
      • CDN: CloudFront。
      • DNS: Route 53。
      • 監控與日誌: CloudWatch Logs, Metrics。
    • Terraform State: 管理基礎設施的狀態,確保部署的一致性。建議將 terraform.tfstate 存儲在遠程後端(如 S3 + DynamoDB Lock),以實現團隊協作。
    • Terraform Modules: 將常用或複雜的基礎設施模式封裝為可重用的模組,提高效率和一致性。

2.2. 配置管理 (Configuration Management) 工具

  • Ansible: 用於在佈建好的伺服器上進行軟體安裝、配置和應用程式部署。Ansible 是無代理的 (agentless),只需 SSH 即可連接伺服器。
    • Ansible Playbooks: 定義一系列任務來配置伺服器,例如:
      • 安裝 PHP, Nginx, Composer。
      • 配置 Nginx 虛擬主機。
      • 設置 PHP-FPM。
      • 配置環境變數。
      • 部署 Laravel 應用程式程式碼(從 Git pull)。
      • 運行 composer install, php artisan migrate, php artisan cache:clear 等。
      • 設置 Supervisor 或 Systemd 服務來運行 Laravel Queue Worker。

2.3. 容器化 (Containerization) - Docker

  • Docker: 將應用程式及其所有依賴項打包成一個獨立、可移植的容器。這消除了“在我機器上能跑”的問題,並確保開發、測試和生產環境的一致性。
    • Dockerfile: 定義如何構建 Laravel 應用程式的 Docker 映像。
      • 基礎映像 (e.g., php:8.2-fpm-alpine)
      • 安裝必要的 PHP 擴展。
      • 複製應用程式程式碼。
      • 安裝 Composer 依賴。
      • 設置權限。
    • Docker Compose: 用於定義和運行多容器 Docker 應用程式。在開發環境中特別有用,可以輕鬆啟動 Laravel 應用程式、Nginx、MySQL、Redis 等服務。
    • 優勢:
      • 環境一致性: 開發、測試、生產環境相同。
      • 隔離性: 應用程式及其依賴項相互隔離。
      • 可移植性: 容器可以在任何支持 Docker 的機器上運行。
      • 快速部署: 容器啟動速度快。

2.4. CI/CD (持續整合/持續部署)

利用 CI/CD 工具自動化程式碼提交到生產環境的過程。

  • 推薦工具:
    • GitHub Actions / GitLab CI/CD / Jenkins / AWS CodePipeline / Google Cloud Build: 選擇一個與你的程式碼倉庫集成良好的 CI/CD 工具。
  • CI/CD 管道 (Pipeline) 流程範例:
    1. 程式碼提交 (Code Commit): 開發者將程式碼推送到版本控制系統 (Git)。
    2. 觸發 CI/CD (Trigger CI/CD): CI/CD 系統監聽到程式碼提交事件。
    3. 單元測試 & 功能測試 (Unit & Feature Tests): 運行自動化測試,確保新程式碼沒有引入回歸。
    4. 程式碼風格檢查 (Code Linting/Static Analysis): 使用 PHPStan, PHP-CS-Fixer 檢查程式碼品質。
    5. Docker 映像構建 (Docker Image Build): 構建新的 Docker 應用程式映像。
    6. 映像推送到容器註冊表 (Push Image to Registry): 將 Docker 映像推送到 Docker Hub, AWS ECR, Google Container Registry 等。
    7. 基礎設施更新 (Infrastructure Update) (IaC 部分):
      • terraform plan (預覽變更)。
      • terraform apply (應用基礎設施變更,例如更新 ECS 服務的任務定義,指向新的 Docker 映像)。
    8. 藍綠部署 / 金絲雀部署 (Blue/Green Deployment / Canary Deployment): 建議採用這些部署策略,以實現零停機部署並降低風險。

3. 監控、日誌與可觀測性

  • 日誌 (Logging):
    • Laravel 日誌: 使用 Monolog 配置日誌輸出到 JSON 格式,便於機器解析。
    • 日誌聚合: 將所有應用程式日誌、Web 伺服器日誌等集中收集到一個中央日誌系統,如 ELK Stack (Elasticsearch, Logstash, Kibana), Grafana Loki, AWS CloudWatch Logs, Google Cloud Logging。
  • 監控 (Monitoring):
    • 應用程式性能監控 (APM): 使用 New Relic, Datadog, Laravel Nova (與 Horizon 結合) 或 Prometheus + Grafana 監控應用程式的性能指標(響應時間、錯誤率、資料庫查詢等)。
    • 基礎設施監控: 監控伺服器資源使用情況(CPU、記憶體、網路、磁碟),利用 CloudWatch Metrics, Google Cloud Monitoring。
    • Alerting: 設置警報,當關鍵指標超出閾值時及時通知團隊。
  • 錯誤追蹤 (Error Tracking):
    • 使用 Sentry, Bugsnag 自動捕獲應用程式錯誤,提供詳細的堆棧追蹤和環境資訊。

4. 資料庫策略

  • 關聯式資料庫: MySQL, PostgreSQL (推薦)。
    • RDS (Relational Database Service): 雲服務商提供的託管資料庫服務,負責資料庫的備份、擴展、安全和高可用性。
    • 資料庫遷移 (Migrations): 使用 Laravel Migrations 管理資料庫結構的變更。
    • 資料庫備份與恢復: 定期自動備份,並測試恢復流程。
  • 非關聯式資料庫 (NoSQL): Redis (用於快取、佇列、Session 儲存), DynamoDB (如果需要高吞吐量的鍵值存儲)。
  • ORM: Eloquent ORM 提供便捷的資料庫操作。對於複雜查詢,考慮使用 DB Facade 或直接 SQL。

5. 安全性考量

  • OWASP Top 10: 遵循 OWASP Top 10 安全準則。
  • 輸入驗證: 嚴格驗證所有使用者輸入。
  • 參數化查詢: 防止 SQL 注入。
  • CSRF 防護: 使用 Laravel 內建的 CSRF 保護。
  • XSS 防護: 對輸出進行適當的轉義。
  • HTTPS: 強制使用 HTTPS。
  • 環境變數: 敏感資訊(如資料庫憑證、API Key)存儲在環境變數中,不要硬編碼在程式碼中。在雲環境中,使用 Secrets Manager (AWS Secrets Manager, Google Secret Manager) 管理。
  • 最小權限原則: 服務、用戶和角色只授予執行其職責所需的最小權限。
  • 定期安全審計和滲透測試

6. 環境區分

  • 開發環境 (Development): 本地開發環境 (Docker Compose)。
  • 測試環境 (Staging/UAT): 盡可能模擬生產環境,用於集成測試和使用者驗收測試。
  • 生產環境 (Production): 運行實際應用程式的環境。

每個環境都應通過 IaC 管理,確保其一致性。

7. 如何用 Laravel 辦到 IaC

Laravel 本身並不直接執行 IaC,但它與 IaC 工具完美結合。

  1. 程式碼分離: Laravel 應用程式程式碼只關注業務邏輯。基礎設施配置則完全交給 IaC 工具。

  2. 環境變數: Laravel 的 .env 檔案是管理環境配置的關鍵。在 IaC 部署時,可以使用工具(如 Terraform)將敏感的環境變數安全地注入到運行時環境中(例如,通過 ECS 任務定義的環境變數,或 Kubernetes 的 Secrets)。

  3. 資料庫遷移:

    • php artisan migrate: Laravel 提供強大的資料庫遷移工具。在 CI/CD 流程中,這一步應在應用程式部署後執行。
    • IaC 協調: IaC 工具(如 Terraform)會負責創建資料庫實例(例如 RDS),而 Laravel Migration 負責管理資料庫內的表結構。這兩者是獨立但協同工作的。
  4. 佇列管理:

    • php artisan queue:work: 運行佇列處理器。在 IaC 中,這會通過配置管理工具(如 Ansible)安裝 Supervisor 或 Systemd 服務來常駐運行。
    • 自動擴展: 如果使用 ECS/EKS,可以配置自動擴展來根據佇列長度自動調整 Worker 數量。
  5. 快取配置:

    • Laravel config/cache.php 定義快取驅動。IaC 工具負責創建快取服務(如 Redis ElastiCache)。
  6. 排程任務:

    • php artisan schedule:run: 在 Laravel 中定義排程任務。這需要在伺服器的 Cron Job 中設置。IaC 工具(如 Ansible)可以自動配置此 Cron Job。

總結流程 (以 AWS 為例)

  1. 開發階段:
    • 開發者在本地使用 Docker Compose 啟動 Laravel 應用程式、MySQL、Redis。
    • 編寫 Laravel 程式碼,包括 API、業務邏輯、Migration。
  2. 版本控制:
    • 程式碼推送到 Git 倉庫 (GitHub/GitLab)。
    • Terraform 配置檔案 (.tf) 和 Ansible Playbook (.yml) 也存儲在 Git 倉庫中。
  3. CI/CD 觸發:
    • GitHub Actions (或類似工具) 監聽 Git 倉庫。
  4. CI 階段:
    • 運行測試、程式碼風格檢查。
    • 構建 Docker 映像 (包含 Laravel 應用程式)。
    • 將 Docker 映像推送到 AWS ECR。
  5. CD 階段 (IaC 主導):
    • Terraform 執行:
      • terraform plan (審查基礎設施變更)。
      • terraform apply (應用變更)。
      • 更新 AWS ECS 服務,將其指向新的 Docker 映像版本。
    • ECS 部署: ECS 服務接收到更新指令,會逐步替換舊的任務實例,啟動新的 Docker 容器。
    • Ansible (可選,對於需要進一步配置的 EC2 實例): 如果不是完全容器化,Ansible 可能在此階段用於更新 Nginx 配置、PHP-FPM 設定、運行 php artisan migrate 等。
    • 後部署任務: 在新容器啟動後,運行 php artisan migrate --force (在生產環境下),以及 php artisan optimize, php artisan view:clear 等命令。

通過上述設計,您將能夠建立一個高效、穩健且高度自動化的 Laravel 後端系統,無論是面對快速變化的需求還是大規模的流量,都能從容應對。關鍵在於將基礎設施視為程式碼,並將其與應用程式的開發和部署流程緊密結合。


與傳統 MVC 架構的差異

您提出的架構設計與傳統的 Laravel MVC 架構在職責劃分複雜度管理上有所不同。傳統的 MVC 在小型專案中表現良好,但隨著專案規模擴大和業務邏輯複雜化,其缺點會逐漸浮現。

以下是主要的差異點:

1. 職責分離 (Separation of Concerns)

  • 傳統 MVC:

    • Model: 通常指 Laravel 的 Eloquent Model,它承擔了資料庫操作(CRUD)、資料驗證,有時甚至包含部分業務邏輯。這容易導致「Anemic Domain Model」(貧血領域模型),即 Model 只是資料的載體,沒有行為;或「Fat Model」,即 Model 包含過多業務邏輯,變得臃腫難以維護。
    • View: 負責資料呈現。
    • Controller: 處理請求、呼叫 Model 執行操作,並將結果傳給 View。在複雜應用中,Controller 容易變得「Fat Controller」,包含過多業務邏輯和協調工作。
  • 您提出的架構 (DDD/Hexagonal 思想):

    • 領域層 (Domain Layer): 這是最大的不同。它獨立於框架和持久化技術,只專注於核心業務邏輯業務規則
      • Entities / Aggregates / Value Objects: 這些是具備行為的業務實體,而不是單純的資料庫表格映射。
      • Domain Services: 處理跨多個實體或值對象的業務操作。
      • Repositories Interfaces: 定義資料存取合約,與具體資料庫實作解耦。
    • 應用程式層 (Application Layer): 專注於應用程式的用例 (Use Cases),協調領域層的對象來完成特定功能,並處理事務、驗證等應用程式層面的需求。它將控制器從繁重的業務邏輯中解放出來。
    • 基礎設施層 (Infrastructure Layer): 負責技術細節的實作,如:
      • Repositories Implementations: 實現領域層定義的介面,例如使用 Eloquent 實際執行資料庫操作。
      • 外部服務整合(支付、簡訊等)。
      • 快取、佇列的具體驅動。
    • 介面層 (Presentation Layer - Controllers): 變得非常,只負責接收 HTTP 請求、驗證輸入、呼叫應用程式層的 Use Case,然後返回結果。它幾乎不包含業務邏輯。

2. 可測試性 (Testability)

  • 傳統 MVC: 業務邏輯散佈在 Model 和 Controller 中,導致單元測試難以進行,往往需要啟動整個 Laravel 環境,進行功能測試。
  • 分層架構: 由於領域層和應用程式層與框架、持久化技術解耦,可以對其進行純粹的單元測試,無需啟動資料庫或 HTTP 環境,大大提高測試效率和可靠性。

3. 可擴展性與可維護性 (Scalability & Maintainability)

  • 傳統 MVC: 隨著業務邏輯增長,單一的 Model 和 Controller 會變得越來越龐大和複雜,修改一個功能可能會影響到其他不相關的部分,難以擴展和維護。
  • 分層架構: 高度的職責分離和模組化使得各層次的功能更加清晰。當需求變更時,通常只需要修改受影響的特定層次或組件,而不會影響整個系統。例如,更換資料庫技術只需修改基礎設施層的 Repository 實作,而無需觸動業務邏輯。

4. 基礎設施即程式碼 (IaC) 的整合

  • 傳統 MVC: 較少提及 IaC 的概念,部署和環境配置更多是手動或腳本化,容易導致環境不一致。
  • 分層架構: 將 IaC 視為設計的核心部分,確保了開發、測試、生產環境的一致性,並提供了自動化部署的能力,這對於大型、高可用性系統至關重要。

如何應用在電子商務系統

電子商務系統通常涉及複雜的業務流程(商品管理、訂單處理、支付、庫存、使用者管理等),非常適合採用您提出的這種分層架構和 IaC 概念。

1. 核心業務邏輯 (領域層)

將電子商務的核心業務規則封裝在領域層

  • Entities / Aggregates:
    • Product: 包含商品資訊、價格、SKU、庫存單位 (Stock Keeping Unit) 等。
    • Order: 包含訂單狀態(待處理、已支付、已發貨)、訂單項、總金額、買家資訊等。
    • OrderItem: 訂單中的具體商品和數量。
    • Customer: 使用者資訊。
    • Cart: 購物車邏輯,包含商品添加、移除、數量更新。
    • Payment: 支付相關資訊。
    • Inventory: 庫存管理。
  • Domain Services:
    • OrderPlacementService: 協調 CartProductOrderInventory,處理訂單創建的複雜邏輯(檢查庫存、計算總價、生成訂單號、鎖定庫存等)。
    • PaymentProcessingService: 處理支付相關邏輯(調用支付網關、更新訂單支付狀態)。
    • InventoryManagementService: 處理庫存扣減、回補等。
  • Domain Events:
    • OrderPlaced: 訂單成功創建事件。
    • PaymentSuccessful: 支付成功事件。
    • ProductStockUpdated: 商品庫存更新事件。
    • UserRegistered: 使用者註冊事件。
  • Repositories Interfaces:
    • ProductRepositoryInterface
    • OrderRepositoryInterface
    • CustomerRepositoryInterface
    • CartRepositoryInterface

2. 應用程式用例 (應用程式層)

定義電子商務的具體操作流程:

  • Use Cases / Application Services:
    • PlaceOrderUseCase: 接收 PlaceOrderCommand (包含購物車ID, 收貨地址等),協調 CartRepository 獲取購物車、呼叫 OrderPlacementService 創建訂單、觸發 OrderPlaced 事件。
    • ProcessPaymentUseCase: 接收支付回調,呼叫 PaymentProcessingService 處理支付結果,更新訂單狀態。
    • AddItemToCartUseCase: 將商品添加到購物車。
    • UpdateProductStockUseCase: 更新商品庫存。
    • RegisterUserUseCase: 註冊使用者。

3. 技術實現 (基礎設施層)

實現領域層和應用程式層的介面,並集成外部服務:

  • Persistence:
    • EloquentProductRepository: 實現 ProductRepositoryInterface,使用 Eloquent 操作 products 表。
    • EloquentOrderRepository: 實現 OrderRepositoryInterface,使用 Eloquent 操作 ordersorder_items 表。
  • External Services:
    • StripePaymentGateway: 實現支付介面,與 Stripe API 交互。
    • SMSNotificationService: 發送簡訊通知。
  • Queue Drivers: 使用 Redis 或 AWS SQS 作為佇列驅動。
  • Cache Drivers: 使用 Redis 作為快取驅動。

4. 介面呈現 (介面層 - Controllers)

精簡控制器:

  • OrderController:
    • store() 方法接收 PlaceOrderRequest,呼叫 PlaceOrderUseCase 執行訂單創建,返回 OrderResource
    • show() 方法呼叫 GetOrderDetailsQuery
  • ProductController:
    • index() 方法呼叫 GetAllProductsQuery
  • PaymentWebhookController: 接收支付網關的 webhook 回調,呼叫 ProcessPaymentUseCase

5. 基礎設施即程式碼 (IaC) 的整合

這對電子商務系統尤其重要,因為高可用性和快速擴展是關鍵:

  • 雲服務: 大量使用 AWS (EC2, ECS, RDS, S3, SQS, ElastiCache, ALB), GCP, Azure 等託管服務。
  • Terraform:
    • 定義整個電商系統的基礎設施,包括 VPC、Subnets、安全組、自動擴展組 (Auto Scaling Group) 或 ECS Cluster (用於 Laravel 容器)。
    • RDS 資料庫實例,配置多可用區、自動備份。
    • ElastiCache (Redis) 用於快取和佇列。
    • S3 用於商品圖片、靜態文件存儲。
    • ALB (Application Load Balancer) 實現流量分發和 SSL 終止。
    • Route 53 管理 DNS 紀錄。
  • Docker:
    • 將 Laravel 應用程式、Nginx 打包成獨立的 Docker 映像。
    • 開發環境使用 docker-compose
    • 生產環境部署到 ECS FargateEKS (Kubernetes),利用容器編排服務實現自動部署、擴展和高可用性。
  • Ansible:
    • 如果使用 EC2 實例,Ansible 可以用於部署 Nginx、PHP-FPM、Composer、Supervisor(運行 Queue Worker)。
    • 配置環境變數,執行 php artisan migrate 等。
  • CI/CD Pipeline:
    • 自動化測試: 確保每次提交的程式碼品質。
    • 藍綠部署 / 金絲雀部署: 實現電商系統的零停機部署,避免服務中斷。
    • 自動化擴展: 根據流量和負載自動調整伺服器或容器的數量,應對購物節等高峰期流量。

6. 監控與日誌

  • 日誌: 收集所有服務的日誌(Nginx 訪問日誌、Laravel 應用程式日誌、PHP-FPM 日誌、資料庫慢查詢日誌等),統一上報到 ELK Stack 或 CloudWatch Logs,便於故障排除和業務分析。
  • 監控:
    • 應用程式: 響應時間、錯誤率、資料庫查詢耗時、佇列處理速度、支付成功率等。
    • 基礎設施: CPU、記憶體、網路 I/O、磁碟使用率、資料庫連接數等。
    • 業務監控: 訂單量、轉化率、庫存預警等。

透過這種分層架構和 IaC 的結合,電子商務系統將具備更好的彈性、可維護性、可擴展性可靠性,能夠更好地應對業務的快速發展和高併發挑戰。


沒有留言:

張貼留言

網誌存檔