服务应用部署

Laravel 微服务架构的 GitHub 最佳实践项目

以下是 Laravel 微服务架构的 GitHub 最佳实践项目 和关键实现方案,涵盖服务拆分、通信、部署和监控等核心环节:


一、微服务核心架构模式

1. 服务拆分原则

2. 技术栈组合

组件 推荐方案
通信协议 HTTP/REST、gRPC、消息队列(RabbitMQ)
服务发现 Consul、Nacos、Eureka
部署 Docker + Kubernetes
监控 Prometheus + Grafana

二、GitHub 最佳实践项目案例

1. Laravel Microservice Boilerplate

2. Laravel + DDD + CQRS 微服务示例

3. Lumen 微服务框架示例


三、关键实现方案

1. 服务间通信

2. API 网关实现

3. 数据一致性

4. 服务发现与负载均衡


四、部署与 DevOps

1. 容器化(Docker)

2. Kubernetes 部署

3. 监控与日志


五、安全实践

  1. 服务间认证
    • 使用 JWTmTLS(双向 TLS)
  2. API 网关防护
    • 限流、IP 白名单、请求签名
  3. 数据库隔离
    • 每个服务使用独立数据库用户

六、学习资源

  1. 官方文档
  2. 书籍
    • 《微服务架构设计模式》(Chris Richardson)
  3. 视频课程

总结对比

方案 适用场景 技术栈
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. 准备工作

确保已安装:

2. 项目结构

laravel-cluster/
├── docker/
│   ├── nginx/
│   │   ├── Dockerfile
│   │   └── default.conf
│   ├── php/
│   │   └── Dockerfile
│   └── haproxy/
│       └── haproxy.cfg
├── src/ (Laravel 项目)
├── docker-compose.yml
└── .env

3. 配置 Docker 环境

docker-compose.yml

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

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

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

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 目录:

    git clone https://github.com/laravel/laravel.git src
    
  2. 创建 .env 文件:

    cp src/.env.example src/.env
    
  3. 修改 src/.env 数据库配置:

    DB_CONNECTION=mysql
    DB_HOST=mysql
    DB_PORT=3306
    DB_DATABASE=laravel
    DB_USERNAME=laravel
    DB_PASSWORD=secret
    
  4. 创建项目 .env 文件:

    cat > .env <<EOF
    DB_ROOT_PASSWORD=root
    DB_DATABASE=laravel
    DB_USERNAME=laravel
    DB_PASSWORD=secret
    EOF
    
  5. 构建并启动容器:

    docker-compose up -d --build
    
  6. 安装 Laravel 依赖:

    docker-compose exec php1 composer install
    
  7. 生成应用密钥:

    docker-compose exec php1 php artisan key:generate
    
  8. 运行数据库迁移:

    docker-compose exec php1 php artisan migrate
    

5. 访问应用

6. 扩展集群

要增加更多 PHP 和 Nginx 实例:

  1. docker-compose.yml 中添加 php3nginx3 服务
  2. 更新 HAProxy 配置添加新服务器
  3. 重新部署:
    docker-compose up -d --scale php=3 --scale nginx=3
    

7. 监控与管理

这个配置提供了基本的 Laravel 集群环境,您可以根据需要添加更多服务如队列 worker、Horizon 监控等。

Laravel 大型应用架构部署指南

构建大型 Laravel 应用需要精心设计的架构和部署策略。以下是针对高流量、高可用性 Laravel 应用的完整架构方案。

一、架构设计

1. 分层架构

┌─────────────────────────────────────────────────┐
│                   客户端层                      │
│  (Web/移动端/API消费者)                        │
└───────────────┬─────────────────┬───────────────┘
                │                 │
┌───────────────▼─────┐ ┌─────────▼───────────────┐
│     负载均衡层       │ │        CDN             │
│ (Nginx/Haproxy/ALB) │ │ (CloudFront/Cloudflare) │
└───────────────┬─────┘ └─────────┬───────────────┘
                │                 │
┌───────────────▼─────────────────▼───────────────┐
│                应用服务器层                     │
│  (多节点Laravel应用+PHP-FPM集群)               │
└───────────────┬─────────────────────────────────┘
                │
┌───────────────▼─────────────────────────────────┐
│                 服务层                          │
│  (Redis集群/Elasticsearch/消息队列/微服务)      │
└───────────────┬─────────────────────────────────┘
                │
┌───────────────▼─────────────────────────────────┐
│                 数据层                          │
│  (MySQL集群/读写分离/分库分表)                  │
└─────────────────────────────────────────────────┘

二、基础设施部署

1. 容器化部署 (Kubernetes)

# deployment.yaml 示例
apiVersion: apps/v1
kind: Deployment
metadata:
  name: laravel-app
spec:
  replicas: 6
  selector:
    matchLabels:
      app: laravel
  template:
    metadata:
      labels:
        app: laravel
    spec:
      containers:
      - name: app
        image: your-registry/laravel-app:1.0.0
        ports:
        - containerPort: 9000
        envFrom:
        - configMapRef:
            name: laravel-config
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
          limits:
            cpu: "1000m"
            memory: "1024Mi"
        livenessProbe:
          httpGet:
            path: /health
            port: 9000
          initialDelaySeconds: 30
          periodSeconds: 10
---
# Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: laravel-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: laravel-app
  minReplicas: 4
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

2. 服务网格集成 (Istio)

# 虚拟服务配置
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: laravel-vs
spec:
  hosts:
  - "yourdomain.com"
  gateways:
  - laravel-gateway
  http:
  - route:
    - destination:
        host: laravel-app
        port:
          number: 9000
      weight: 100
    retries:
      attempts: 3
      perTryTimeout: 2s
    timeout: 5s

三、关键组件配置

1. 数据库架构

// config/database.php
'mysql' => [
    '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 集群配置

// 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. 缓存策略

// 使用多级缓存
$value = Cache::remember('key', $seconds, function () {
    return DB::table(...)->get();
});

// 标签缓存
Cache::tags(['people', 'authors'])->put('John', $john, $seconds);

2. 队列优化

// 配置多个队列连接
'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 监控配置

# 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)

// 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 示例

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. 应用安全

    // 强制 HTTPS
    URL::forceScheme('https');
    
    // CSP 头
    header("Content-Security-Policy: default-src 'self'");
    
  3. 密钥管理

    • 使用 Vault 或 KMS 管理密钥
    • 定期轮换数据库凭证

八、扩展策略

  1. 水平扩展

    • 无状态应用层自动扩展
    • 数据库读写分离
  2. 垂直扩展

    • 数据库优化 (索引、分表)
    • 查询缓存
  3. 功能解耦

    // 使用事件驱动架构
    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)

emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 10s

进程池优化 (/etc/php/8.x/fpm/pool.d/www.conf)

[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)

; 基础优化
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)

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站点配置示例

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)

# 增加网络性能
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

应用修改:

sysctl -p

增加文件描述符限制 (/etc/security/limits.conf)

* soft nofile 65535
* hard nofile 65535
www-data soft nofile 65535
www-data hard nofile 65535

5. 监控与调优工具

实时监控命令

# 查看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

性能测试工具

# 安装基准测试工具
sudo apt install apache2-utils siege

# 压力测试
ab -n 10000 -c 100 http://example.com/
siege -b -c100 -t60S http://example.com/

6. 高级优化技巧

使用最新版本

# 升级到最新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

fastcgi_pass unix:/run/php/php8.2-fpm.sock;

启用HTTP/2

listen 443 ssl http2;

使用 Brotli 压缩

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. 请求响应时间 (使用 absiege)
  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 认证服务

安装依赖:

composer require firebase/php-jwt lcobucci/jwt

JWT 服务类:

<?php
namespace App\Services\Auth;

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class JwtService
{
    private $secretKey;
    private $algorithm = 'HS256';
    
    public function __construct(string $secretKey) {
        $this->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 (基于角色的访问控制) 数据库结构:

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
namespace App\Services\Auth;

class PermissionService
{
    private $pdo;
    
    public function __construct(\PDO $pdo) {
        $this->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
namespace App\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class AuthMiddleware implements MiddlewareInterface
{
    private $jwtService;
    private $permissionService;
    
    public function __construct(JwtService $jwtService, PermissionService $permissionService) {
        $this->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
namespace App\Controller\Auth;

use App\Services\Auth\JwtService;
use App\Repository\UserRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class LoginController
{
    private $userRepository;
    private $jwtService;
    
    public function __construct(UserRepository $userRepository, JwtService $jwtService) {
        $this->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 服务间认证

使用服务账户:

// 在服务启动时获取服务令牌
$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缓存权限:

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 令牌黑名单

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 速率限制

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有效性

这种架构设计提供了灵活的认证和授权机制,能够支持高并发的微服务系统,同时保持了良好的安全性和可扩展性。