在 Laravel 应用从开发环境迁移到生产环境的过程中,部署配置和性能优化是确保应用稳定运行的关键环节。本文将详细介绍 Laravel 生产环境部署的最佳实践,以及 18 个必备的性能优化技巧,帮助你构建高性能、高可用的 Laravel 应用。
一、生产环境部署准备
1.1 环境配置检查清单
在部署前,确保以下配置项已正确设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| APP_ENV=production APP_DEBUG=false APP_KEY=your-32-character-secret-key
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=your_database DB_USERNAME=your_username DB_PASSWORD=your_password
CACHE_DRIVER=redis SESSION_DRIVER=redis QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379
|
1.2 依赖管理优化
使用 Composer 优化自动加载和移除开发依赖:
1 2 3 4 5
| composer install --prefer-dist --no-dev -o
composer dump-autoload -o
|
二、Nginx 部署配置
2.1 Nginx 虚拟主机配置
创建 Nginx 配置文件 /etc/nginx/sites-available/laravel-app:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| server { listen 80; listen [::]:80; server_name your-domain.com www.your-domain.com; root /var/www/laravel-app/public; add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; index index.php; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ /\. { deny all; } location ~ \.php$ { fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; fastcgi_hide_header X-Powered-By; } location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control "public, immutable"; access_log off; } gzip on; gzip_vary on; gzip_min_length 1024; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml; }
|
2.2 SSL/HTTPS 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name your-domain.com; ssl_certificate /path/to/your/certificate.crt; ssl_certificate_key /path/to/your/private.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512; ssl_prefer_server_ciphers off; }
server { listen 80; server_name your-domain.com; return 301 https://$server_name$request_uri; }
|
三、Docker 容器化部署
3.1 Dockerfile 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| FROM php:8.1-fpm
RUN apt-get update && apt-get install -y \ git \ curl \ libpng-dev \ libonig-dev \ libxml2-dev \ zip \ unzip \ nginx
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
COPY . /var/www
RUN composer install --prefer-dist --no-dev -o
RUN chown -R www-data:www-data /var/www \ && chmod -R 755 /var/www/storage \ && chmod -R 755 /var/www/bootstrap/cache
EXPOSE 9000 CMD ["php-fpm"]
|
3.2 Docker Compose 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| version: '3.8'
services: app: build: context: . dockerfile: Dockerfile container_name: laravel-app restart: unless-stopped working_dir: /var/www volumes: - ./:/var/www networks: - laravel
nginx: image: nginx:alpine container_name: laravel-nginx restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./:/var/www - ./docker/nginx:/etc/nginx/conf.d networks: - laravel
mysql: image: mysql:8.0 container_name: laravel-mysql restart: unless-stopped environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: secret MYSQL_PASSWORD: secret MYSQL_USER: laravel volumes: - mysql_data:/var/lib/mysql networks: - laravel
redis: image: redis:alpine container_name: laravel-redis restart: unless-stopped networks: - laravel
volumes: mysql_data: driver: local
networks: laravel: driver: bridge
|
四、18个性能优化技巧
4.1 基础优化(立即生效)
1. 路由缓存
1 2 3 4 5
| php artisan route:cache
php artisan route:clear
|
2. 配置缓存
1 2 3 4 5
| php artisan config:cache
php artisan config:clear
|
3. 视图缓存
1 2 3 4 5
| php artisan view:cache
php artisan view:clear
|
4. 事件缓存
1 2 3 4 5
| php artisan event:cache
php artisan event:clear
|
4.2 数据库优化
5. 预加载关联数据(解决 N+1 问题)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $books = Book::all(); foreach ($books as $book) { echo $book->author->name; }
$books = Book::with('author')->get(); foreach ($books as $book) { echo $book->author->name; }
$books = Book::with(['author', 'publisher', 'reviews.user'])->get();
$books = Book::with(['reviews' => function ($query) { $query->where('rating', '>', 4); }])->get();
|
6. 查询结果缓存
1 2 3 4 5 6 7 8 9 10 11 12
| $topBooks = Cache::remember('top_books', 3600, function () { return Book::orderBy('rating', 'desc') ->limit(10) ->get(); });
Cache::tags(['books', 'popular'])->put('top_books', $books, 3600);
Cache::tags(['books'])->flush();
|
7. 数据库索引优化
1 2 3 4 5 6 7 8 9
| Schema::table('books', function (Blueprint $table) { $table->index('author_id'); $table->index(['category_id', 'published_at']); $table->unique(['isbn']); });
$table->index(['user_id', 'created_at'], 'user_created_index');
|
8. 分页优化
1 2 3 4 5 6 7 8 9 10
| $books = Book::simplePaginate(15);
$books = Book::cursorPaginate(15);
$books = Book::select(['id', 'title', 'author_id']) ->with('author:id,name') ->paginate(15);
|
4.3 缓存策略优化
9. Redis 缓存配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 'redis' => [ 'driver' => 'redis', 'connection' => 'cache', 'lock_connection' => 'default', ],
'redis' => [ 'cache' => [ 'url' => env('REDIS_URL'), 'host' => env('REDIS_HOST', '127.0.0.1'), 'password' => env('REDIS_PASSWORD', null), 'port' => env('REDIS_PORT', '6379'), 'database' => env('REDIS_CACHE_DB', '1'), ], ],
|
10. 模型缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Book extends Model { protected $cacheMinutes = 60; public function getCachedBooks() { return Cache::remember( 'books_all_' . $this->cacheMinutes, $this->cacheMinutes, function () { return $this->all(); } ); } protected static function boot() { parent::boot(); static::saved(function () { Cache::forget('books_all_60'); }); } }
|
4.4 队列和异步处理
11. 队列配置优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class SendWelcomeEmail implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $tries = 3; public $timeout = 120; public function handle() { } public function failed(Exception $exception) { } }
SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(5));
|
12. Supervisor 进程管理
创建 /etc/supervisor/conf.d/laravel-worker.conf:
1 2 3 4 5 6 7 8 9 10
| [program:laravel-worker] process_name=%(program_name)s_%(process_num)02d command=php /var/www/laravel-app/artisan queue:work --sleep=3 --tries=3 --max-time=3600 autostart=true autorestart=true user=www-data numprocs=8 redirect_stderr=true stdout_logfile=/var/www/laravel-app/storage/logs/worker.log stopwaitsecs=3600
|
启动 Supervisor:
1 2 3 4 5 6 7 8 9
| sudo supervisorctl reread sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
sudo supervisorctl status
|
4.5 前端资源优化
13. 资源压缩和合并
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js') .sass('resources/sass/app.scss', 'public/css') .options({ processCssUrls: false }) .version();
if (mix.inProduction()) { mix.version(); }
|
14. CDN 配置
1 2 3 4 5 6 7 8 9
| 'asset_url' => env('ASSET_URL', null),
ASSET_URL=https:
<link href="{{ mix('css/app.css') }}" rel="stylesheet"> <script src="{{ mix('js/app.js') }}"></script>
|
4.6 服务器级优化
15. OPcache 配置
1 2 3 4 5 6 7 8
| opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=256 opcache.interned_strings_buffer=16 opcache.max_accelerated_files=10000 opcache.revalidate_freq=2 opcache.fast_shutdown=1
|
16. PHP-FPM 优化
1 2 3 4 5 6 7 8 9 10 11
| pm = dynamic pm.max_children = 50 pm.start_servers = 10 pm.min_spare_servers = 5 pm.max_spare_servers = 20 pm.max_requests = 1000
request_terminate_timeout = 300 rlimit_files = 65536
|
17. 内存使用优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Book::chunk(1000, function ($books) { foreach ($books as $book) { } });
Book::lazy()->each(function ($book) { });
unset($largeArray); gc_collect_cycles();
|
18. 监控和日志优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['daily', 'slack'], 'ignore_exceptions' => false, ], 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'days' => 14, ], ],
class PerformanceMonitor { public function handle($request, Closure $next) { $start = microtime(true); $response = $next($request); $duration = microtime(true) - $start; if ($duration > 1.0) { Log::warning('Slow request detected', [ 'url' => $request->fullUrl(), 'duration' => $duration, 'memory' => memory_get_peak_usage(true), ]); } return $response; } }
|
五、部署脚本自动化
5.1 部署脚本示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #!/bin/bash
set -e
APP_DIR="/var/www/laravel-app" BACKUP_DIR="/var/backups/laravel"
echo "开始部署 Laravel 应用..."
echo "备份当前版本..." cp -r $APP_DIR $BACKUP_DIR/backup-$(date +%Y%m%d-%H%M%S)
echo "拉取最新代码..." cd $APP_DIR git pull origin main
echo "安装 Composer 依赖..." composer install --prefer-dist --no-dev -o
echo "运行数据库迁移..." php artisan migrate --force
echo "重建缓存..." php artisan config:clear php artisan route:clear php artisan view:clear php artisan cache:clear
php artisan config:cache php artisan route:cache php artisan view:cache php artisan event:cache
echo "优化自动加载..." composer dump-autoload -o
echo "重启服务..." sudo systemctl reload php8.1-fpm sudo systemctl reload nginx sudo supervisorctl restart laravel-worker:*
echo "部署完成!"
|
5.2 零停机部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #!/bin/bash
APP_NAME="laravel-app" DEPLOY_DIR="/var/www/deployments" CURRENT_DIR="/var/www/current" RELEASE_DIR="$DEPLOY_DIR/$(date +%Y%m%d-%H%M%S)"
mkdir -p $RELEASE_DIR
git clone https://github.com/your-repo/laravel-app.git $RELEASE_DIR
ln -nfs /var/www/shared/.env $RELEASE_DIR/.env ln -nfs /var/www/shared/storage $RELEASE_DIR/storage
cd $RELEASE_DIR composer install --prefer-dist --no-dev -o php artisan migrate --force php artisan config:cache php artisan route:cache php artisan view:cache
ln -nfs $RELEASE_DIR $CURRENT_DIR
sudo systemctl reload php8.1-fpm sudo supervisorctl restart laravel-worker:*
ls -t $DEPLOY_DIR | tail -n +6 | xargs -I {} rm -rf $DEPLOY_DIR/{}
|
六、监控和维护
6.1 应用监控
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Route::get('/health', function () { $checks = [ 'database' => DB::connection()->getPdo() ? 'ok' : 'failed', 'cache' => Cache::store()->getStore()->connection()->ping() ? 'ok' : 'failed', 'queue' => Queue::size() < 1000 ? 'ok' : 'warning', 'storage' => Storage::disk('local')->exists('test') ? 'ok' : 'failed', ]; $status = in_array('failed', $checks) ? 500 : 200; return response()->json([ 'status' => $status === 200 ? 'healthy' : 'unhealthy', 'checks' => $checks, 'timestamp' => now()->toISOString(), ], $status); });
|
6.2 性能监控
1 2 3 4 5 6 7 8
| composer require laravel/telescope --dev php artisan telescope:install php artisan migrate
composer require laravel/horizon php artisan horizon:install
|
总结
Laravel 生产环境部署和性能优化是一个系统性工程,需要从多个维度进行考虑:
- 部署配置:正确的 Nginx/Apache 配置、SSL 证书、防火墙设置
- 性能优化:缓存策略、数据库优化、队列处理、资源压缩
- 监控维护:日志管理、性能监控、健康检查、自动化部署
- 安全防护:环境变量保护、文件权限、访问控制
通过实施这些最佳实践,你的 Laravel 应用将能够在生产环境中稳定、高效地运行,为用户提供优质的服务体验。记住,性能优化是一个持续的过程,需要根据实际的业务需求和用户反馈不断调整和改进。