Laravel 後端架構設計:擁抱 IaC,提升維護與擴展性
這份設計旨在提供一個堅固、可擴展且易於維護的 Laravel 後端架構,並深度整合 Infrastructure as Code (IaC) 的概念。透過將基礎設施的配置視為程式碼,我們能實現環境的一致性、自動化部署、以及更快速的故障恢復。
核心原則
- 模組化 (Modularity):將應用程式劃分為獨立、可重用的組件。
- 鬆耦合 (Loose Coupling):各組件之間減少直接依賴,提高獨立性。
- 單一職責原則 (Single Responsibility Principle - SRP):每個組件或類別只負責一項功能。
- 基礎設施即程式碼 (Infrastructure as Code - IaC):利用程式碼管理和佈建基礎設施。
- 自動化 (Automation):自動化部署、測試和監控流程。
- 可觀測性 (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): 在不同層之間傳遞資料的對象。
- Use Cases / Application Services: 處理應用程式特定的流程,協調領域層的物件來完成特定的用例。例如
-
基礎設施層 (Infrastructure Layer):
- Repositories Implementations: 實現領域層定義的 Repository 介面,例如
EloquentUserRepository
。 - Services (External): 整合第三方服務,如支付閘道、訊息通知等。
- Database Migrations & Seeders: 資料庫結構和初始資料。
- Cache Drivers: 快取實作。
- Queue Drivers: 佇列實作。
- File Storage Drivers: 檔案儲存實作。
- Repositories Implementations: 實現領域層定義的 Repository 介面,例如
-
介面層 (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: 將常用或複雜的基礎設施模式封裝為可重用的模組,提高效率和一致性。
- 範例 Terraform 資源:
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。
- Ansible Playbooks: 定義一系列任務來配置伺服器,例如:
2.3. 容器化 (Containerization) - Docker
- Docker: 將應用程式及其所有依賴項打包成一個獨立、可移植的容器。這消除了“在我機器上能跑”的問題,並確保開發、測試和生產環境的一致性。
- Dockerfile: 定義如何構建 Laravel 應用程式的 Docker 映像。
- 基礎映像 (e.g.,
php:8.2-fpm-alpine
) - 安裝必要的 PHP 擴展。
- 複製應用程式程式碼。
- 安裝 Composer 依賴。
- 設置權限。
- 基礎映像 (e.g.,
- Docker Compose: 用於定義和運行多容器 Docker 應用程式。在開發環境中特別有用,可以輕鬆啟動 Laravel 應用程式、Nginx、MySQL、Redis 等服務。
- 優勢:
- 環境一致性: 開發、測試、生產環境相同。
- 隔離性: 應用程式及其依賴項相互隔離。
- 可移植性: 容器可以在任何支持 Docker 的機器上運行。
- 快速部署: 容器啟動速度快。
- Dockerfile: 定義如何構建 Laravel 應用程式的 Docker 映像。
2.4. CI/CD (持續整合/持續部署)
利用 CI/CD 工具自動化程式碼提交到生產環境的過程。
- 推薦工具:
- GitHub Actions / GitLab CI/CD / Jenkins / AWS CodePipeline / Google Cloud Build: 選擇一個與你的程式碼倉庫集成良好的 CI/CD 工具。
- CI/CD 管道 (Pipeline) 流程範例:
- 程式碼提交 (Code Commit): 開發者將程式碼推送到版本控制系統 (Git)。
- 觸發 CI/CD (Trigger CI/CD): CI/CD 系統監聽到程式碼提交事件。
- 單元測試 & 功能測試 (Unit & Feature Tests): 運行自動化測試,確保新程式碼沒有引入回歸。
- 程式碼風格檢查 (Code Linting/Static Analysis): 使用 PHPStan, PHP-CS-Fixer 檢查程式碼品質。
- Docker 映像構建 (Docker Image Build): 構建新的 Docker 應用程式映像。
- 映像推送到容器註冊表 (Push Image to Registry): 將 Docker 映像推送到 Docker Hub, AWS ECR, Google Container Registry 等。
- 基礎設施更新 (Infrastructure Update) (IaC 部分):
terraform plan
(預覽變更)。terraform apply
(應用基礎設施變更,例如更新 ECS 服務的任務定義,指向新的 Docker 映像)。
- 藍綠部署 / 金絲雀部署 (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 工具完美結合。
-
程式碼分離: Laravel 應用程式程式碼只關注業務邏輯。基礎設施配置則完全交給 IaC 工具。
-
環境變數: Laravel 的
.env
檔案是管理環境配置的關鍵。在 IaC 部署時,可以使用工具(如 Terraform)將敏感的環境變數安全地注入到運行時環境中(例如,通過 ECS 任務定義的環境變數,或 Kubernetes 的 Secrets)。 -
資料庫遷移:
php artisan migrate
: Laravel 提供強大的資料庫遷移工具。在 CI/CD 流程中,這一步應在應用程式部署後執行。- IaC 協調: IaC 工具(如 Terraform)會負責創建資料庫實例(例如 RDS),而 Laravel Migration 負責管理資料庫內的表結構。這兩者是獨立但協同工作的。
-
佇列管理:
php artisan queue:work
: 運行佇列處理器。在 IaC 中,這會通過配置管理工具(如 Ansible)安裝 Supervisor 或 Systemd 服務來常駐運行。- 自動擴展: 如果使用 ECS/EKS,可以配置自動擴展來根據佇列長度自動調整 Worker 數量。
-
快取配置:
- Laravel
config/cache.php
定義快取驅動。IaC 工具負責創建快取服務(如 Redis ElastiCache)。
- Laravel
-
排程任務:
php artisan schedule:run
: 在 Laravel 中定義排程任務。這需要在伺服器的 Cron Job 中設置。IaC 工具(如 Ansible)可以自動配置此 Cron Job。
總結流程 (以 AWS 為例)
- 開發階段:
- 開發者在本地使用 Docker Compose 啟動 Laravel 應用程式、MySQL、Redis。
- 編寫 Laravel 程式碼,包括 API、業務邏輯、Migration。
- 版本控制:
- 程式碼推送到 Git 倉庫 (GitHub/GitLab)。
- Terraform 配置檔案 (
.tf
) 和 Ansible Playbook (.yml
) 也存儲在 Git 倉庫中。
- CI/CD 觸發:
- GitHub Actions (或類似工具) 監聽 Git 倉庫。
- CI 階段:
- 運行測試、程式碼風格檢查。
- 構建 Docker 映像 (包含 Laravel 應用程式)。
- 將 Docker 映像推送到 AWS ECR。
- 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
等命令。
- Terraform 執行:
通過上述設計,您將能夠建立一個高效、穩健且高度自動化的 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,然後返回結果。它幾乎不包含業務邏輯。
- 領域層 (Domain Layer): 這是最大的不同。它獨立於框架和持久化技術,只專注於核心業務邏輯和業務規則。
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
: 協調Cart
、Product
、Order
、Inventory
,處理訂單創建的複雜邏輯(檢查庫存、計算總價、生成訂單號、鎖定庫存等)。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 操作orders
和order_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 Fargate 或 EKS (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 的結合,電子商務系統將具備更好的彈性、可維護性、可擴展性和可靠性,能夠更好地應對業務的快速發展和高併發挑戰。
沒有留言:
張貼留言