Files
Siro/docs/30-siro-port-plan.md

39 lines
3.9 KiB
Markdown

# Siro Backend Migration Plan & Docker Architecture (Docs/30)
## 1. Overview
This document outlines the architectural decisions made for migrating the Siro backend to a containerized Docker environment. It addresses questions regarding performance overhead, container granularity, and technology stack choices (PHP vs Node.js).
## 2. Docker Overhead vs Bare Metal
- **Finding:** Docker on Linux is not a virtual machine. It utilizes Linux namespaces and cgroups to isolate processes.
- **CPU & Memory:** The CPU and Memory overhead of running PHP inside Docker is effectively **zero** compared to bare metal. The processes run natively on the host kernel.
- **Disk I/O:** The only measurable overhead comes from writing to the container's overlayfs (file system).
- **Solution:** We mitigate this by using **named volumes** for MySQL data (`mysql-data`), which bypasses overlayfs and provides near-native disk performance.
- **Conclusion:** Docker is heavily recommended. It gives you instant reproducibility (clone -> `.env` -> up) with a negligible performance difference (0-3%). The real performance factors are PHP opcache, MySQL indexes, and fpm pool sizes, all of which are properly tuned in the container configurations.
## 3. Container Strategy: Single vs Multiple Containers
- **Finding:** Grouping everything (Nginx, PHP-FPM, MySQL, Redis, Node/Workerman) into a single container is considered a Docker anti-pattern.
- **Decision:** The architecture uses **6 specialized containers** running within a single server using Docker Compose:
1. `nginx`: Handles incoming HTTP traffic and reverse proxies.
2. `php`: A single PHP-FPM container that handles all HTTP API requests (backend + payment).
3. `socket_driver`: PHP CLI container running Workerman for driver WebSockets (Port 2020).
4. `socket_passenger`: PHP CLI container running Workerman for passenger WebSockets (Port 3030).
5. `mysql`: Database container.
6. `redis`: Caching container.
- **Why?** Performance is identical to a monolithic single-container setup because all processes still run on the same server/kernel. However, this split gives critical operational advantages: independent service restarts, individual memory limits (e.g., preventing MySQL from consuming all RAM and crashing PHP), and separated logs. Over-segmenting beyond this (microservices) would be overkill.
## 4. WebSockets: PHP (Workerman) vs Node.js
- **Finding:** Node.js uses an event-loop and is natively non-blocking, making it extremely lightweight for massive WebSocket concurrency. PHP-FPM allocates a process per request, which is bad for WebSockets.
- **However,** the current implementation uses **Workerman** for PHP WebSockets. Workerman implements the exact same event-loop model as Node.js within PHP.
- **Scale:** At a target of 10,000 to 20,000 trips per hour, the system experiences roughly 3 to 6 trips per second. This load is well within the capabilities of both Workerman and Node.js.
- **Conclusion:** There is no need to rewrite the WebSockets in Node.js. Workerman handles the event-driven load efficiently. The real bottleneck will be the database and complex business logic, not the socket engine.
## 5. Environment Variables (.env)
- The architecture mounts the `backend` directory directly into the `php` container.
- The `.env` file can safely reside in the root `backend` or project directory on the server as it currently does.
- By passing `env_file: .env` to the containers in `docker-compose.yml`, Docker injects the environment variables natively, making them available via PHP's `getenv()`. This requires zero code changes to the PHP application.
## 6. Stress Testing
- A continuous stress test script (`rate_test.js`) is used instead of a batch load tester.
- It generates JWTs natively in Node to avoid blocking on PHP processes.
- The success criteria for 10,000 trips/hour is less than 1% failure rate and a p95 response time under 500ms.