# 服务应用部署
# Laravel 微服务架构的 GitHub 最佳实践项目
以下是 Laravel 微服务架构的 **GitHub 最佳实践项目** 和关键实现方案,涵盖服务拆分、通信、部署和监控等核心环节:
---
### 一、微服务核心架构模式
#### 1. **服务拆分原则**
- **按业务域划分**(如用户服务、订单服务、支付服务)
- **独立数据库**(每个服务拥有自己的数据库)
- **API 网关**(统一入口,路由到不同服务)
#### 2. **技术栈组合**
组件 | 推荐方案 |
---|
通信协议 | HTTP/REST、gRPC、消息队列(RabbitMQ) |
服务发现 | Consul、Nacos、Eureka |
部署 | Docker + Kubernetes |
监控 | Prometheus + Grafana |
---
### 二、GitHub 最佳实践项目案例
#### 1. [Laravel Microservice Boilerplate](https://github.com/mateusjunges/laravel-microservices)
- **Stars**: 800+
- **特点**:
- 使用 **API 网关**(Kong)统一路由
- 服务间通过 **gRPC** 通信
- 集成 **JWT 认证**
- Docker Compose 本地开发环境
- **目录结构**: ```markdown
/api-gateway # 网关服务
/user-service # 用户微服务
/order-service # 订单微服务
/docker # 容器化配置
```
#### 2. [Laravel + DDD + CQRS 微服务示例](https://github.com/renoki-co/laravel-microservices)
- **Stars**: 1k+
- **亮点**:
- 领域驱动设计(DDD)分层
- CQRS 模式(命令与查询分离)
- 事件溯源(Event Sourcing)
- 使用 **Laravel Octane** 提升性能
#### 3. [Lumen 微服务框架示例](https://github.com/liyu001989/lumen-api-demo)
- **Stars**: 500+
- **适用场景**:
- 轻量级 API 服务(基于 Lumen)
- 集成 **Swagger 文档**
- JWT + OAuth2 认证
---
### 三、关键实现方案
#### 1. **服务间通信**
- **同步通信(HTTP/gRPC)**: ```php
// 使用 Guzzle 调用其他服务
$response = Http::post('http://user-service/api/users', [
'name' => 'John Doe'
]);
```
- **异步通信(消息队列)**: ```php
// 在订单服务中发布事件
event(new OrderCreated($order));
// 在支付服务中监听事件
class ProcessPayment implements ShouldQueue
{
public function handle(OrderCreated $event)
{
// 处理支付逻辑
}
}
```
#### 2. **API 网关实现**
- **Kong 配置示例**: ```yaml
# 路由规则
routes:
- name: user-service
paths: /users/*
service: user-service
- name: order-service
paths: /orders/*
service: order-service
```
#### 3. **数据一致性**
- **Saga 模式**(分布式事务): ```php
// 使用 Saga 协调多个服务
$saga = new CreateOrderSaga();
$saga->addStep(new ReserveProductStep());
$saga->addStep(new ProcessPaymentStep());
$saga->execute();
```
#### 4. **服务发现与负载均衡**
- **Consul 集成**: ```php
// 注册服务
Consul::agent()->service()->register([
'Name' => 'user-service',
'Address' => '192.168.1.100',
'Port' => 8000
]);
// 发现服务
$services = Consul::catalog()->services();
```
---
### 四、部署与 DevOps
#### 1. **容器化(Docker)**
- **docker-compose.yml 示例**: ```yaml
version: '3'
services:
user-service:
build: ./user-service
ports: ["8001:80"]
order-service:
build: ./order-service
ports: ["8002:80"]
api-gateway:
image: kong:latest
ports: ["8000:8000"]
```
#### 2. **Kubernetes 部署**
- **Deployment 示例**: ```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
containers:
- name: user-service
image: user-service:latest
ports:
- containerPort: 80
```
#### 3. **监控与日志**
- **Prometheus 指标收集**: ```php
// 在 Laravel 中暴露指标
Route::get('/metrics', function () {
return response(Prometheus::export());
});
```
- **集中式日志(ELK Stack)**: ```bash
# Logstash 配置
input {
beats {
port => 5044
}
}
```
---
### 五、安全实践
1. **服务间认证**:
- 使用 **JWT** 或 **mTLS(双向 TLS)**
2. **API 网关防护**:
- 限流、IP 白名单、请求签名
3. **数据库隔离**:
- 每个服务使用独立数据库用户
---
### 六、学习资源
1. **官方文档**:
- [Laravel Queue](https://laravel.com/docs/queues)
- [Lumen 微服务框架](https://lumen.laravel.com/)
2. **书籍**:
- 《微服务架构设计模式》(Chris Richardson)
3. **视频课程**:
- [Udemy: Laravel Microservices](https://www.udemy.com/course/laravel-microservices/)
---
### 总结对比
方案 | 适用场景 | 技术栈 |
---|
**Lumen 轻量级** | 简单 API 服务 | Lumen + JWT + Swagger |
**DDD + CQRS** | 复杂业务系统 | Laravel + Event Sourcing |
**Kubernetes 集群** | 高可用生产环境 | Docker + K8s + Istio |
选择时需权衡团队技能和业务复杂度。建议从简单 HTTP 通信开始,逐步引入消息队列和复杂事务模式。
# 使用 Docker 搭建 Laravel 集群指南
本指南将介绍如何使用 Docker 和 Docker Compose 搭建一个 Laravel 应用集群,包含 Web 服务器、MySQL 数据库、Redis 缓存和负载均衡。
(通过GitHub和DockerHub的集成实现自动化构建流程。包括设置GitHub组织、配置DockerHub访问权限、创建仓库及使用webhook触发构建过程。)
## 1. 准备工作
确保已安装:
- Docker (>= 20.10)
- Docker Compose (>= 2.0)
- Git
## 2. 项目结构
```
laravel-cluster/
├── docker/
│ ├── nginx/
│ │ ├── Dockerfile
│ │ └── default.conf
│ ├── php/
│ │ └── Dockerfile
│ └── haproxy/
│ └── haproxy.cfg
├── src/ (Laravel 项目)
├── docker-compose.yml
└── .env
```
## 3. 配置 Docker 环境
### docker-compose.yml
```yaml
version: '3.8'
services:
# MySQL 数据库
mysql:
image: mysql:8.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
networks:
- laravel-network
# Redis 缓存
redis:
image: redis:alpine
container_name: redis
ports:
- "6379:6379"
networks:
- laravel-network
# PHP-FPM 服务 (多个实例)
php1:
build:
context: ./docker/php
container_name: php1
volumes:
- ./src:/var/www/html
environment:
- DB_HOST=mysql
- REDIS_HOST=redis
networks:
- laravel-network
depends_on:
- mysql
- redis
php2:
build:
context: ./docker/php
container_name: php2
volumes:
- ./src:/var/www/html
environment:
- DB_HOST=mysql
- REDIS_HOST=redis
networks:
- laravel-network
depends_on:
- mysql
- redis
# Nginx Web 服务器 (多个实例)
nginx1:
build:
context: ./docker/nginx
container_name: nginx1
ports:
- "8081:80"
volumes:
- ./src:/var/www/html
depends_on:
- php1
networks:
- laravel-network
nginx2:
build:
context: ./docker/nginx
container_name: nginx2
ports:
- "8082:80"
volumes:
- ./src:/var/www/html
depends_on:
- php2
networks:
- laravel-network
# HAProxy 负载均衡
haproxy:
image: haproxy:2.4
container_name: haproxy
ports:
- "80:80"
- "8404:8404" # 统计页面
volumes:
- ./docker/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
depends_on:
- nginx1
- nginx2
networks:
- laravel-network
volumes:
mysql_data:
networks:
laravel-network:
driver: bridge
```
### docker/php/Dockerfile
```dockerfile
FROM php:8.1-fpm
# 安装依赖
RUN apt-get update && apt-get install -y \
libzip-dev \
zip \
unzip \
libpq-dev \
libonig-dev \
libxml2-dev
# 安装 PHP 扩展
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath zip
# 安装 Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# 设置工作目录
WORKDIR /var/www/html
```
### docker/nginx/default.conf
```nginx
server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php1:9000; # 修改为对应的 PHP 容器名
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
```
### docker/haproxy/haproxy.cfg
```cfg
global
stats socket /var/run/api.sock user haproxy group haproxy mode 660 level admin expose-fd listeners
log stdout format raw local0 info
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http_front
bind *:80
stats uri /stats
default_backend http_back
backend http_back
balance roundrobin
server nginx1 nginx1:80 check
server nginx2 nginx2:80 check
listen stats
bind *:8404
stats enable
stats uri /
stats refresh 5s
```
## 4. 部署步骤
1. 克隆 Laravel 项目到 `src` 目录:
```bash
git clone https://github.com/laravel/laravel.git src
```
2. 创建 `.env` 文件:
```bash
cp src/.env.example src/.env
```
3. 修改 `src/.env` 数据库配置:
```env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret
```
4. 创建项目 `.env` 文件:
```bash
cat > .env < [
'read' => [
'host' => [
env('DB_READ_HOST_1', 'read1.db.cluster'),
env('DB_READ_HOST_2', 'read2.db.cluster'),
],
],
'write' => [
'host' => env('DB_WRITE_HOST', 'write.db.cluster'),
],
'sticky' => true,
'driver' => 'mysql',
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
// ...
],
```
### 2. Redis 集群配置
```php
// config/database.php
'redis' => [
'cluster' => env('REDIS_CLUSTER', true),
'default' => [
[
'host' => env('REDIS_HOST_1', 'redis1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],
[
'host' => env('REDIS_HOST_2', 'redis2'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],
],
'cache' => [
// 单独配置缓存Redis
],
],
```
## 四、性能优化
### 1. 缓存策略
```php
// 使用多级缓存
$value = Cache::remember('key', $seconds, function () {
return DB::table(...)->get();
});
// 标签缓存
Cache::tags(['people', 'authors'])->put('John', $john, $seconds);
```
### 2. 队列优化
```php
// 配置多个队列连接
'connections' => [
'default' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
'processing' => [
'driver' => 'sqs',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'prefix' => env('SQS_PREFIX'),
'queue' => env('SQS_QUEUE'),
'region' => env('AWS_DEFAULT_REGION'),
],
],
```
## 五、监控与日志
### 1. Prometheus 监控配置
```yaml
# prometheus.yml
scrape_configs:
- job_name: 'laravel'
metrics_path: '/metrics'
static_configs:
- targets: ['laravel-app:9000']
relabel_configs:
- source_labels: [__meta_kubernetes_pod_name]
target_label: pod
```
### 2. 集中式日志 (ELK)
```php
// config/logging.php
'stacks' => [
'elastic' => [
'driver' => 'custom',
'via' => \App\Logging\ElasticsearchLogger::class,
'level' => 'debug',
'hosts' => [
[
'host' => env('ELASTICSEARCH_HOST', 'elasticsearch'),
'port' => env('ELASTICSEARCH_PORT', 9200),
'scheme' => env('ELASTICSEARCH_SCHEME', 'https'),
]
],
],
],
```
## 六、CI/CD 流程
### 1. GitLab CI 示例
```yaml
stages:
- test
- build
- deploy
unit_tests:
stage: test
image: php:8.1
script:
- apt-get update && apt-get install -y git unzip
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
- composer install --prefer-dist --no-ansi --no-interaction --no-progress --no-scripts
- vendor/bin/phpunit
build_image:
stage: build
image: docker:latest
services:
- docker:dind
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:latest .
- docker push $CI_REGISTRY_IMAGE:latest
deploy_production:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl apply -f kubernetes/deployment.yaml
- kubectl rollout status deployment/laravel-app
environment:
name: production
url: https://yourdomain.com
when: manual
```
## 七、安全最佳实践
1. **网络安全**:
- 使用 WAF (Web Application Firewall)
- 配置 VPC 网络隔离
- 启用 DDoS 防护
2. **应用安全**:
```php
// 强制 HTTPS
URL::forceScheme('https');
// CSP 头
header("Content-Security-Policy: default-src 'self'");
```
3. **密钥管理**:
- 使用 Vault 或 KMS 管理密钥
- 定期轮换数据库凭证
## 八、扩展策略
1. **水平扩展**:
- 无状态应用层自动扩展
- 数据库读写分离
2. **垂直扩展**:
- 数据库优化 (索引、分表)
- 查询缓存
3. **功能解耦**:
```php
// 使用事件驱动架构
event(new OrderShipped($order));
// 微服务通信
Http::post('inventory-service/api/update', [...]);
```
这套架构可以支持日 PV 千万级的大型 Laravel 应用,根据实际业务需求可进一步调整优化。
# Nginx + PHP 8 + PHP-FPM 性能优化指南
## 1. PHP-FPM 配置优化
### 主配置文件优化 (`/etc/php/8.x/fpm/php-fpm.conf`)
```ini
emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 10s
```
### 进程池优化 (`/etc/php/8.x/fpm/pool.d/www.conf`)
```ini
[www]
user = www-data
group = www-data
; 动态进程管理 - 根据服务器内存调整
pm = dynamic
pm.max_children = 100 ; 最大子进程数 = (总内存 - 其他服务内存) / 单个PHP进程内存
pm.start_servers = 20 ; 启动时的子进程数 = CPU核心数 × 2
pm.min_spare_servers = 10 ; 最小空闲进程数 ≈ CPU核心数
pm.max_spare_servers = 30 ; 最大空闲进程数 ≈ CPU核心数 × 2
pm.max_requests = 500 ; 每个子进程处理多少请求后重启
; 提高进程优先级
process.priority = -10
; 优化进程通信
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
; 启用慢日志
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s
; 限制单个请求资源
request_terminate_timeout = 30s
rlimit_files = 65535
rlimit_core = unlimited
```
## 2. PHP 8 配置优化 (`/etc/php/8.x/fpm/php.ini`)
```ini
; 基础优化
max_execution_time = 30 ; 减少脚本执行时间
memory_limit = 128M ; 根据应用需求调整
upload_max_filesize = 16M
post_max_size = 18M
; OPcache 配置 (PHP 8 内置)
opcache.enable=1
opcache.memory_consumption=256 ; 根据应用大小调整
opcache.interned_strings_buffer=20
opcache.max_accelerated_files=20000
opcache.revalidate_freq=60 ; 检查文件更改间隔(秒)
opcache.fast_shutdown=1
opcache.enable_cli=1 ; CLI也启用OPcache
opcache.jit_buffer_size=256M ; PHP 8 JIT 缓冲区大小
opcache.jit=1235 ; JIT模式 (4级优化)
; 禁用不必要功能
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
expose_php = Off
```
## 3. Nginx 配置优化
### 主配置文件 (`/etc/nginx/nginx.conf`)
```nginx
user www-data;
worker_processes auto; # 自动设置为CPU核心数
worker_rlimit_nofile 65535; # 每个worker能打开的文件描述符数量
events {
worker_connections 4096; # 每个worker最大连接数
multi_accept on; # 同时接受多个连接
use epoll; # Linux高性能事件模型
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 15;
keepalive_requests 1000;
types_hash_max_size 2048;
server_tokens off;
# 缓冲区优化
client_body_buffer_size 16K;
client_header_buffer_size 1k;
client_max_body_size 18m;
large_client_header_buffers 4 16k;
# 文件缓存
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# MIME类型
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
access_log off; # 生产环境可关闭或缓冲
error_log /var/log/nginx/error.log crit;
# Gzip压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 包含站点配置
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
```
### PHP站点配置示例
```nginx
server {
listen 80;
server_name example.com;
root /var/www/html;
index index.php index.html;
# 安全头
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 365d;
access_log off;
add_header Cache-Control "public";
}
# PHP处理
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 优化FastCGI
fastcgi_buffer_size 128k;
fastcgi_buffers 256 16k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_read_timeout 60s;
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 限制上传目录执行PHP
location ~* /uploads/.*\.php$ {
deny all;
}
}
```
## 4. 系统级优化
### 内核参数调整 (`/etc/sysctl.conf`)
```conf
# 增加网络性能
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_max_syn_backlog = 262144
# 减少TCP连接时间
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
# 增加文件描述符限制
fs.file-max = 2097152
# 内存分配
vm.swappiness = 10
vm.vfs_cache_pressure = 50
```
应用修改:
```bash
sysctl -p
```
### 增加文件描述符限制 (`/etc/security/limits.conf`)
```
* soft nofile 65535
* hard nofile 65535
www-data soft nofile 65535
www-data hard nofile 65535
```
## 5. 监控与调优工具
### 实时监控命令
```bash
# 查看PHP-FPM状态
sudo systemctl status php8.2-fpm
sudo journalctl -u php8.2-fpm -f
# 查看PHP-FPM进程
ps -ylC php-fpm8.2 --sort:rss
# Nginx状态
sudo systemctl status nginx
sudo tail -f /var/log/nginx/error.log
# 系统资源监控
htop
iftop -n
iotop -o
```
### 性能测试工具
```bash
# 安装基准测试工具
sudo apt install apache2-utils siege
# 压力测试
ab -n 10000 -c 100 http://example.com/
siege -b -c100 -t60S http://example.com/
```
## 6. 高级优化技巧
### 使用最新版本
```bash
# 升级到最新PHP 8.2/8.3
sudo apt install php8.3-fpm php8.3-opcache
# 使用最新Nginx主线版
sudo add-apt-repository ppa:nginx/development
sudo apt update
sudo apt install nginx
```
### 使用Unix Socket替代TCP
```nginx
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
```
### 启用HTTP/2
```nginx
listen 443 ssl http2;
```
### 使用 Brotli 压缩
```nginx
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
```
## 7. 优化效果验证
优化前后对比指标:
1. 请求响应时间 (使用 `ab` 或 `siege`)
2. 并发处理能力
3. 内存占用情况
4. CPU利用率
5. 吞吐量 (Requests/sec)
通过以上优化,Nginx + PHP 8 + PHP-FPM 的性能通常可以提高3-5倍,特别是在高并发场景下效果更为显著。建议每次修改配置后都进行压力测试,观察系统资源使用情况,逐步调整到最佳状态。
# PHP 微服务架构下的用户认证与权限系统设计
## 1. 整体架构设计
### 架构图
```
┌───────────────────────────────────────────────────────┐
│ 客户端层 (Client) │
│ (Web/App/API调用方) │
└───────────────┬───────────────────┬───────────────────┘
│ │
┌───────────────▼───────┐ ┌────────▼───────────────────┐
│ API 网关 │ │ 认证服务 │
│ (身份验证/路由转发) │ │ (登录/注册/令牌签发) │
└───────────────┬───────┘ └────────┬───────────────────┘
│ │
┌───────────────▼───────────────────▼───────────────┐
│ 微服务集群 │
│ (各业务服务通过JWT验证权限) │
└───────────────┬───────────────────┬───────────────┘
│ │
┌───────────────▼───────┐ ┌────────▼───────────────────┐
│ 用户服务 │ │ 权限服务 │
│ (用户数据管理) │ │ (角色/权限分配/验证) │
└───────────────────────┘ └───────────────────────────┘
```
## 2. 核心组件实现
### 2.1 JWT 认证服务
**安装依赖**:
```bash
composer require firebase/php-jwt lcobucci/jwt
```
**JWT 服务类**:
```php
secretKey = $secretKey;
}
public function generateToken(array $payload, int $expire = 3600): string
{
$issuedAt = time();
$payload += [
'iat' => $issuedAt,
'exp' => $issuedAt + $expire,
'iss' => 'your-auth-service',
'aud' => 'your-microservices'
];
return JWT::encode($payload, $this->secretKey, $this->algorithm);
}
public function validateToken(string $token): ?array
{
try {
$decoded = JWT::decode($token, new Key($this->secretKey, $this->algorithm));
return (array)$decoded;
} catch (\Exception $e) {
return null;
}
}
}
```
### 2.2 权限服务设计
**RBAC (基于角色的访问控制) 数据库结构**:
```sql
CREATE TABLE `users` (
`id` bigint PRIMARY KEY AUTO_INCREMENT,
`username` varchar(255) UNIQUE NOT NULL,
`password_hash` varchar(255) NOT NULL
);
CREATE TABLE `roles` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`name` varchar(255) UNIQUE NOT NULL,
`description` varchar(255)
);
CREATE TABLE `user_roles` (
`user_id` bigint,
`role_id` int,
PRIMARY KEY (`user_id`, `role_id`)
);
CREATE TABLE `permissions` (
`id` int PRIMARY KEY AUTO_INCREMENT,
`name` varchar(255) UNIQUE NOT NULL,
`description` varchar(255)
);
CREATE TABLE `role_permissions` (
`role_id` int,
`permission_id` int,
PRIMARY KEY (`role_id`, `permission_id`)
);
```
**权限检查服务**:
```php
pdo = $pdo;
}
public function userHasPermission(int $userId, string $permission): bool
{
$stmt = $this->pdo->prepare("
SELECT COUNT(*)
FROM user_roles ur
JOIN role_permissions rp ON ur.role_id = rp.role_id
JOIN permissions p ON rp.permission_id = p.id
WHERE ur.user_id = :userId AND p.name = :permission
");
$stmt->execute([
':userId' => $userId,
':permission' => $permission
]);
return $stmt->fetchColumn() > 0;
}
public function getUserPermissions(int $userId): array
{
$stmt = $this->pdo->prepare("
SELECT p.name
FROM user_roles ur
JOIN role_permissions rp ON ur.role_id = rp.role_id
JOIN permissions p ON rp.permission_id = p.id
WHERE ur.user_id = :userId
");
$stmt->execute([':userId' => $userId]);
return $stmt->fetchAll(\PDO::FETCH_COLUMN, 0);
}
}
```
## 3. API 网关实现
### 3.1 统一认证中间件
```php
jwtService = $jwtService;
$this->permissionService = $permissionService;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// 1. 获取Token
$token = $this->getTokenFromRequest($request);
if (!$token) {
return new JsonResponse(['error' => 'Token missing'], 401);
}
// 2. 验证Token
$payload = $this->jwtService->validateToken($token);
if (!$payload) {
return new JsonResponse(['error' => 'Invalid token'], 401);
}
// 3. 检查权限 (从路由获取所需权限)
$requiredPermission = $request->getAttribute('route')->getArgument('permission');
if ($requiredPermission &&
!$this->permissionService->userHasPermission($payload['user_id'], $requiredPermission)) {
return new JsonResponse(['error' => 'Forbidden'], 403);
}
// 4. 将用户信息添加到请求属性
$request = $request->withAttribute('auth_user', $payload);
return $handler->handle($request);
}
private function getTokenFromRequest(ServerRequestInterface $request): ?string
{
$header = $request->getHeaderLine('Authorization');
if (preg_match('/Bearer\s(\S+)/', $header, $matches)) {
return $matches[1];
}
return $request->getQueryParams()['token'] ?? null;
}
}
```
## 4. 登录流程实现
### 4.1 登录控制器
```php
userRepository = $userRepository;
$this->jwtService = $jwtService;
}
public function login(ServerRequestInterface $request): ResponseInterface
{
$data = json_decode($request->getBody()->getContents(), true);
// 1. 验证输入
if (empty($data['username']) || empty($data['password'])) {
return new JsonResponse(['error' => 'Invalid credentials'], 400);
}
// 2. 查找用户
$user = $this->userRepository->findByUsername($data['username']);
if (!$user || !password_verify($data['password'], $user['password_hash'])) {
return new JsonResponse(['error' => 'Invalid credentials'], 401);
}
// 3. 生成JWT
$token = $this->jwtService->generateToken([
'user_id' => $user['id'],
'username' => $user['username']
]);
// 4. 返回响应
return new JsonResponse([
'token' => $token,
'expires_in' => 3600,
'token_type' => 'Bearer'
]);
}
}
```
## 5. 微服务集成方案
### 5.1 服务间认证
**使用服务账户**:
```php
// 在服务启动时获取服务令牌
$serviceToken = $jwtService->generateToken([
'service_name' => 'order-service',
'scope' => ['internal']
], 86400 * 365); // 长期有效的服务令牌
// 在服务间调用时携带
$response = $httpClient->request('GET', 'http://user-service/api/users', [
'headers' => [
'Authorization' => 'Bearer ' . $serviceToken,
'X-Service-Auth' => 'order-service'
]
]);
```
### 5.2 权限缓存优化
**Redis缓存权限**:
```php
class CachedPermissionService extends PermissionService
{
private $redis;
private $ttl = 3600;
public function __construct(\PDO $pdo, \Redis $redis) {
parent::__construct($pdo);
$this->redis = $redis;
}
public function getUserPermissions(int $userId): array
{
$cacheKey = "user_permissions:$userId";
if ($this->redis->exists($cacheKey)) {
return json_decode($this->redis->get($cacheKey), true);
}
$permissions = parent::getUserPermissions($userId);
$this->redis->setex($cacheKey, $this->ttl, json_encode($permissions));
return $permissions;
}
}
```
## 6. 安全增强措施
### 6.1 令牌黑名单
```php
class JwtServiceWithBlacklist extends JwtService
{
private $redis;
public function __construct(string $secretKey, \Redis $redis) {
parent::__construct($secretKey);
$this->redis = $redis;
}
public function invalidateToken(string $token, int $expire): void
{
$payload = $this->validateToken($token);
if ($payload) {
$jti = $payload['jti'] ?? md5($token);
$this->redis->setex("jwt_blacklist:$jti", $expire, '1');
}
}
public function validateToken(string $token): ?array
{
$payload = parent::validateToken($token);
if ($payload) {
$jti = $payload['jti'] ?? md5($token);
if ($this->redis->exists("jwt_blacklist:$jti")) {
return null;
}
}
return $payload;
}
}
```
### 6.2 速率限制
```php
class RateLimitMiddleware implements MiddlewareInterface
{
private $redis;
public function __construct(\Redis $redis) {
$this->redis = $redis;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$ip = $request->getServerParams()['REMOTE_ADDR'];
$key = "rate_limit:$ip";
$current = $this->redis->incr($key);
if ($current === 1) {
$this->redis->expire($key, 60);
}
if ($current > 100) {
return new JsonResponse(['error' => 'Too many requests'], 429);
}
return $handler->handle($request);
}
}
```
## 7. 部署建议
1. **认证服务独立部署**:将认证服务部署为独立微服务
2. **多区域部署**:在多个区域部署认证服务以减少延迟
3. **数据库分片**:用户数据按地区或ID范围分片
4. **监控**:监控认证服务的成功率、延迟和错误率
5. **灾备**:建立多活数据中心,确保认证服务高可用
## 8. 性能优化
1. **使用OPcache**:PHP配置中启用OPcache
2. **连接池**:数据库和Redis使用连接池
3. **异步日志**:使用异步方式记录审计日志
4. **热点缓存**:缓存频繁访问的用户权限数据
5. **JWT预验证**:在API网关层先验证JWT有效性
这种架构设计提供了灵活的认证和授权机制,能够支持高并发的微服务系统,同时保持了良好的安全性和可扩展性。