koh db9e384c62
Cập nhật README với cấu trúc dự án chi tiết và hướng dẫn sử dụng
- Mô tả chi tiết cấu trúc thư mục và quy tắc đặt tên
- Bổ sung hướng dẫn về kiến trúc ứng dụng và dependency injection
- Thêm thông tin về môi trường phát triển và sản xuất
- Cập nhật các lệnh Make và hướng dẫn cấu hình
- Giải thích chức năng của các thư mục chính trong dự án
2025-03-03 17:50:46 +07:00
2025-03-02 14:59:34 +07:00
2025-03-02 14:59:34 +07:00
2025-03-02 14:59:34 +07:00
2025-03-02 14:59:34 +07:00
2025-03-02 14:59:34 +07:00
2025-03-02 14:59:34 +07:00
2025-03-02 14:59:34 +07:00

Senflow Server

Ứng dụng backend được viết bằng Go, sử dụng MySQL làm cơ sở dữ liệu và Google Wire cho dependency injection.

Yêu cầu hệ thống

  • Go 1.21 hoặc cao hơn
  • Docker và Docker Compose
  • Make

Cấu trúc dự án chi tiết

.
├── cmd/                    # Điểm vào ứng dụng
│   └── api/                # API server
│       └── main.go         # File main khởi động ứng dụng
├── global/                 # Biến toàn cục và cấu trúc cấu hình
│   └── global.go           # Định nghĩa các biến và cấu trúc toàn cục
├── internal/               # Mã nguồn nội bộ
│   ├── controllers/        # Xử lý request và response
│   │   └── user_controller.go  # Controller xử lý các request liên quan đến user
│   ├── initialize/         # Khởi tạo các thành phần của ứng dụng
│   │   ├── loadconfig.go   # Đọc cấu hình từ file .env
│   │   ├── logger.go       # Khởi tạo logger
│   │   ├── mysql.go        # Khởi tạo kết nối MySQL
│   │   └── run.go          # Điểm khởi động chính của ứng dụng
│   ├── models/             # Định nghĩa các model dữ liệu
│   │   └── user.go         # Model User
│   ├── repositories/       # Tương tác với cơ sở dữ liệu
│   │   └── user_repository.go  # Repository xử lý dữ liệu user
│   ├── routers/            # Định nghĩa các router
│   │   ├── router_group.go # Nhóm các router
│   │   └── user/           # Router liên quan đến user
│   │       ├── router_group.go  # Nhóm các router user
│   │       └── user_router.go   # Định nghĩa các endpoint user
│   ├── services/           # Xử lý logic nghiệp vụ
│   │   └── user_service.go # Service xử lý logic liên quan đến user
│   └── wire/               # Dependency injection với Google Wire
│       ├── injector.go     # Định nghĩa các injector
│       ├── wire.go         # Định nghĩa các provider
│       └── wire_gen.go     # File được tạo tự động bởi Wire
├── logs/                   # Thư mục chứa log
├── .air.toml               # Cấu hình cho Air (hot-reload)
├── .env                    # Biến môi trường
├── Dockerfile              # Cấu hình Docker cho môi trường production
├── Dockerfile.dev          # Cấu hình Docker cho môi trường phát triển
├── Makefile                # Các lệnh make
└── docker-compose.yml, docker-compose.dev.yml  # Cấu hình Docker Compose

Quy tắc đặt tên file

Dự án tuân theo các quy tắc đặt tên file sau để đảm bảo tính nhất quán:

  1. Sử dụng dấu gạch dưới (_) để phân tách các từ trong tên file, ví dụ: user_controller.go, user_repository.go.

  2. Tên file mô tả rõ chức năng của file đó:

    • Controllers: <entity>_controller.go (ví dụ: user_controller.go)
    • Services: <entity>_service.go (ví dụ: user_service.go)
    • Repositories: <entity>_repository.go (ví dụ: user_repository.go)
    • Routers: <entity>_router.go (ví dụ: user_router.go)
    • Models: <entity>.go (ví dụ: user.go)
  3. File khởi tạo và cấu hình sử dụng tên mô tả chức năng:

    • loadconfig.go: Đọc cấu hình
    • logger.go: Khởi tạo logger
    • mysql.go: Khởi tạo kết nối MySQL
    • run.go: Điểm khởi động ứng dụng
  4. File Wire tuân theo quy ước của Google Wire:

    • wire.go: Định nghĩa các provider
    • injector.go: Định nghĩa các injector
    • wire_gen.go: File được tạo tự động bởi Wire

Kiến trúc ứng dụng

Ứng dụng được tổ chức theo kiến trúc phân lớp:

  1. Controllers: Xử lý request và response, gọi các service để thực hiện logic nghiệp vụ.
  2. Services: Chứa logic nghiệp vụ, gọi các repository để tương tác với dữ liệu.
  3. Repositories: Tương tác trực tiếp với cơ sở dữ liệu, thực hiện các thao tác CRUD.
  4. Models: Định nghĩa cấu trúc dữ liệu.
  5. Routers: Định nghĩa các endpoint API và kết nối với controllers.
  6. Wire: Quản lý dependency injection, kết nối các thành phần lại với nhau.

Dependency Injection với Google Wire

Dự án sử dụng Google Wire để quản lý dependency injection. Các thành phần chính:

  1. Provider: Định nghĩa cách tạo các dependency (trong wire.go).
  2. Injector: Định nghĩa cách kết nối các dependency (trong injector.go).
  3. Wire Gen: File được tạo tự động bởi Wire, chứa code khởi tạo dependency (trong wire_gen.go).

Để cập nhật file wire_gen.go sau khi thay đổi các provider hoặc injector:

cd internal/wire
go run github.com/google/wire/cmd/wire

Môi trường phát triển (Development)

Phương pháp 1: Sử dụng Docker Compose cho toàn bộ stack

Phương pháp này sử dụng Docker Compose để chạy cả ứng dụng Go và MySQL, với hot-reload được hỗ trợ bởi Air.

# Khởi động môi trường phát triển
docker-compose -f docker-compose.dev.yml up -d

# Xem logs
docker-compose -f docker-compose.dev.yml logs -f

# Dừng môi trường phát triển
docker-compose -f docker-compose.dev.yml down

Phương pháp 2: Chạy ứng dụng Go trực tiếp, MySQL trong Docker

# Khởi động MySQL trong Docker
make docker-run

# Chạy ứng dụng với hot-reload
make watch

# Hoặc chạy ứng dụng thông thường
make run

# Dừng MySQL
make docker-down

Môi trường sản xuất (Production)

Phương pháp 1: Sử dụng Docker Compose

# Khởi động môi trường sản xuất
docker-compose up -d

# Xem logs
docker-compose logs -f

# Dừng môi trường sản xuất
docker-compose down

Phương pháp 2: Triển khai thủ công

# Build ứng dụng
make build

# Hoặc build với Go trực tiếp
go build -o main cmd/api/main.go

# Chạy ứng dụng
./main

Các lệnh Make hữu ích

# Build ứng dụng
make build

# Chạy ứng dụng
make run

# Chạy tests
make test

# Chạy integration tests
make itest

# Dọn dẹp binary
make clean

# Hot-reload trong quá trình phát triển
make watch

# Khởi động container MySQL
make docker-run

# Dừng container MySQL
make docker-down

Biến môi trường

Sao chép file .env.example thành .env và điều chỉnh các giá trị theo nhu cầu của bạn:

# Cấu hình ứng dụng
APP_ENV=development  # development hoặc production
PORT=8080

# Cấu hình database
BLUEPRINT_DB_HOST=mysql_bp
BLUEPRINT_DB_PORT=3306
BLUEPRINT_DB_DATABASE=blueprint
BLUEPRINT_DB_USERNAME=user
BLUEPRINT_DB_PASSWORD=password
BLUEPRINT_DB_ROOT_PASSWORD=root_password
BLUEPRINT_DB_MAX_IDLE_CONNS=10
BLUEPRINT_DB_MAX_OPEN_CONNS=100
BLUEPRINT_DB_CONN_MAX_LIFETIME=3600

# Cấu hình logger
LOGGER_LOG_LEVEL=debug
LOGGER_FILE_LOG_NAME=./logs/app.log
LOGGER_MAX_SIZE=10
LOGGER_MAX_BACKUPS=5
LOGGER_MAX_AGE=30
LOGGER_COMPRESS=true

Graceful Shutdown

Ứng dụng hỗ trợ graceful shutdown để đảm bảo tất cả các request đang xử lý được hoàn thành trước khi ứng dụng dừng lại. Khi nhận tín hiệu SIGINT hoặc SIGTERM (ví dụ: khi nhấn Ctrl+C), ứng dụng sẽ:

  1. Dừng nhận request mới
  2. Đợi các request đang xử lý hoàn thành (tối đa 5 giây)
  3. Đóng kết nối đến cơ sở dữ liệu
  4. Hiển thị thông báo "Graceful shutdown complete."

Thêm tính năng mới

Để thêm một tính năng mới vào ứng dụng, bạn cần:

  1. Tạo model mới trong thư mục internal/models
  2. Tạo repository mới trong thư mục internal/repositories
  3. Tạo service mới trong thư mục internal/services
  4. Tạo controller mới trong thư mục internal/controllers
  5. Tạo router mới trong thư mục internal/routers
  6. Cập nhật các provider trong internal/wire/wire.go
  7. Cập nhật injector trong internal/wire/injector.go
  8. Chạy lệnh wire để cập nhật wire_gen.go
  9. Cập nhật internal/initialize/run.go để khởi tạo router mới

Đóng góp

Vui lòng đảm bảo code của bạn tuân theo các quy tắc đặt tên và cấu trúc dự án đã được mô tả ở trên. Sử dụng gofmt để định dạng code trước khi commit.

Chức năng của các thư mục chính

cmd

Chứa điểm vào của ứng dụng. Thư mục api chứa file main.go - nơi khởi động ứng dụng.

global

Chứa các biến và cấu hình toàn cục được sử dụng trong toàn bộ ứng dụng:

  • global.go: Định nghĩa các biến toàn cục như DB, Logger
  • config.go: Định nghĩa cấu trúc cấu hình ứng dụng

internal

Chứa mã nguồn nội bộ của ứng dụng, được tổ chức theo kiến trúc phân lớp:

controllers

Xử lý HTTP request và response, gọi đến services để thực hiện logic nghiệp vụ:

  • interfaces.go: Định nghĩa các interface cho controllers
  • controllers.go: Struct chứa tất cả controllers để sử dụng với dependency injection
  • Các file controller cụ thể: user_controller.go, product_controller.go, ...

services

Chứa logic nghiệp vụ của ứng dụng:

  • interfaces.go: Định nghĩa các interface cho services
  • Các file service cụ thể: user_service.go, product_service.go, ...

repositories

Tương tác với cơ sở dữ liệu, thực hiện các thao tác CRUD:

  • interfaces.go: Định nghĩa các interface cho repositories
  • Các file repository cụ thể: user_repository.go, product_repository.go, ...

models

Định nghĩa cấu trúc dữ liệu và các phương thức liên quan:

  • Các file model cụ thể: user.go, product.go, ...

routers

Định nghĩa các routes của ứng dụng:

  • router_group.go: Khởi tạo tất cả routes
  • Các thư mục route cụ thể: user/, product/, ...

middleware

Chứa các middleware được sử dụng trong ứng dụng như authentication, logging, ...

initialize

Khởi tạo các thành phần của ứng dụng:

  • loadconfig.go: Tải cấu hình từ file .env
  • logger.go: Khởi tạo logger
  • mysql.go: Khởi tạo kết nối MySQL
  • run.go: Khởi động ứng dụng

wire

Quản lý dependency injection với Google Wire:

  • wire.go: Định nghĩa các providers
  • injector.go: Định nghĩa các injectors
  • wire_gen.go: File được tạo tự động bởi Wire

pkg

Chứa các thư viện và tiện ích có thể được sử dụng bởi các ứng dụng khác:

  • utils/: Các hàm tiện ích

configs

Chứa các file cấu hình của ứng dụng.

Kiến trúc ứng dụng

Ứng dụng được thiết kế theo kiến trúc phân lớp:

  1. Controller Layer: Xử lý HTTP request và response
  2. Service Layer: Xử lý logic nghiệp vụ
  3. Repository Layer: Tương tác với cơ sở dữ liệu
  4. Model Layer: Định nghĩa cấu trúc dữ liệu

Mỗi lớp chỉ giao tiếp với lớp liền kề, giúp giảm sự phụ thuộc và dễ dàng thay đổi implementation mà không ảnh hưởng đến các lớp khác.

Dependency Injection với Google Wire

Ứng dụng sử dụng Google Wire để quản lý dependency injection. Các thành phần được định nghĩa trong wire.go và được kết nối tự động bởi Wire.

Cấu trúc Wire:

  • RepositorySet: Providers cho repositories
  • ServiceSet: Providers cho services
  • ControllerSet: Providers cho controllers
  • AppSet: Tập hợp tất cả providers

Khi thêm một thành phần mới (ví dụ: Product, Gift), bạn cần:

  1. Tạo model, repository, service, controller tương ứng
  2. Thêm interface vào các file interfaces.go
  3. Cập nhật struct Controllers trong controllers.go
  4. Thêm providers vào wire.go
  5. Chạy lệnh wire để cập nhật wire_gen.go

Môi trường phát triển

Môi Trường Development

Cấu Hình

  1. Tạo file .env.dev:
PORT=8080
APP_ENV=development
BLUEPRINT_DB_HOST=mysql_bp
BLUEPRINT_DB_PORT=3306
BLUEPRINT_DB_DATABASE=blueprint
BLUEPRINT_DB_USERNAME=root
BLUEPRINT_DB_PASSWORD=root
BLUEPRINT_DB_ROOT_PASSWORD=root
BLUEPRINT_DB_MAX_IDLE_CONNS=10
BLUEPRINT_DB_MAX_OPEN_CONNS=100
BLUEPRINT_DB_CONN_MAX_LIFETIME=1h
LOGGER_LOG_LEVEL=debug
LOGGER_FILE_LOG_NAME=logs/app.log
LOGGER_MAX_SIZE=100
LOGGER_MAX_BACKUPS=3
LOGGER_MAX_AGE=28
LOGGER_COMPRESS=true

Chạy Ứng Dụng

# Build và chạy
docker-compose -f docker-compose.dev.yml up --build

# Chạy ở chế độ detached
docker-compose -f docker-compose.dev.yml up -d

# Xem logs
docker-compose -f docker-compose.dev.yml logs -f

# Dừng ứng dụng
docker-compose -f docker-compose.dev.yml down

Môi Trường Production

Cấu Hình

  1. Tạo file .env.prod:
PORT=8080
APP_ENV=production
BLUEPRINT_DB_HOST=mysql_bp
BLUEPRINT_DB_PORT=3306
BLUEPRINT_DB_DATABASE=blueprint
BLUEPRINT_DB_USERNAME=root
BLUEPRINT_DB_PASSWORD=your_secure_password
BLUEPRINT_DB_ROOT_PASSWORD=your_secure_root_password
BLUEPRINT_DB_MAX_IDLE_CONNS=10
BLUEPRINT_DB_MAX_OPEN_CONNS=100
BLUEPRINT_DB_CONN_MAX_LIFETIME=1h
LOGGER_LOG_LEVEL=info
LOGGER_FILE_LOG_NAME=logs/app.log
LOGGER_MAX_SIZE=1000
LOGGER_MAX_BACKUPS=7
LOGGER_MAX_AGE=30
LOGGER_COMPRESS=true
GRAFANA_ADMIN_PASSWORD=your_secure_grafana_password

Tính Năng Production

  1. Load Balancing

    • Nginx làm load balancer
    • 3 instance của ứng dụng
    • Health check tự động
    • SSL/TLS support
  2. Monitoring

    • Prometheus cho metrics collection
    • Grafana cho visualization
    • Metrics từ app và MySQL
    • Persistent storage cho dữ liệu monitoring
  3. Backup

    • Backup MySQL tự động hàng ngày
    • Nén backup với gzip
    • Giữ backup trong 7 ngày
    • Volume riêng cho backups
  4. High Availability

    • Health checks cho tất cả services
    • Auto-restart policy
    • Network isolation
    • Replica management

Chạy Production

# Build và chạy
docker-compose -f docker-compose.prod.yml --env-file .env.prod up --build -d

# Xem logs
docker-compose -f docker-compose.prod.yml logs -f

# Dừng services
docker-compose -f docker-compose.prod.yml down

Endpoints

Bảo Mật

  1. SSL/TLS

    • Thêm certificates vào nginx/ssl/
    • Cấu hình SSL trong Nginx
  2. Mật Khẩu

    • Thay đổi mật khẩu trong .env.prod
    • Sử dụng mật khẩu mạnh
    • Không commit file .env
  3. Network

    • Cấu hình firewall
    • Giới hạn ports
    • Sử dụng internal networks

Monitoring

  1. Grafana Dashboards

    • App metrics
    • MySQL metrics
    • System metrics
  2. Alerts

    • Cấu hình trong Prometheus
    • Thông báo qua email/Slack

Backup & Recovery

  1. Backup

    • Tự động hàng ngày
    • Nén với gzip
    • Giữ 7 ngày
  2. Recovery

    # Restore từ backup
    gunzip -c backup_YYYYMMDD_HHMMSS.sql.gz | mysql -h mysql_bp -u root -p blueprint
    

Troubleshooting

  1. Logs

    # App logs
    docker-compose -f docker-compose.prod.yml logs app
    
    # MySQL logs
    docker-compose -f docker-compose.prod.yml logs mysql_bp
    
    # Nginx logs
    docker-compose -f docker-compose.prod.yml logs nginx
    
  2. Health Checks

Maintenance

  1. Update

    # Pull latest images
    docker-compose -f docker-compose.prod.yml pull
    
    # Rebuild và restart
    docker-compose -f docker-compose.prod.yml up -d --build
    
  2. Cleanup

    # Xóa unused volumes
    docker volume prune
    
    # Xóa old images
    docker image prune
    
Description
Migrated from GitHub: gin_template
Readme 73 KiB
Languages
Go 94%
Makefile 4.5%
Shell 1.5%