Laravel 生产环境部署与性能优化完全指南
Orion K Lv6

在 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
# .env 文件配置
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 配置
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;
}

# PHP 处理
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 压缩
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;

# 其他配置同上...
}

# HTTP 重定向到 HTTPS
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

# 安装 PHP 扩展
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd

# 安装 Composer
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
// 错误示例:会产生 N+1 查询
$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
// 使用 simplePaginate 替代 paginate(当不需要总数时)
$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
// config/cache.php
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
'lock_connection' => 'default',
],

// config/database.php
'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
// webpack.mix.js
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
// config/app.php
'asset_url' => env('ASSET_URL', null),

// .env
ASSET_URL=https://cdn.your-domain.com

// 使用 CDN
<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
; php.ini
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
; /etc/php/8.1/fpm/pool.d/www.conf
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
// 大数据处理时使用 chunk
Book::chunk(1000, function ($books) {
foreach ($books as $book) {
// 处理每本书
}
});

// 使用 lazy 集合
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
// 配置日志驱动
// config/logging.php
'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) { // 超过1秒记录日志
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

# Laravel 自动部署脚本
set -e

APP_DIR="/var/www/laravel-app"
BACKUP_DIR="/var/backups/laravel"

echo "开始部署 Laravel 应用..."

# 1. 备份当前版本
echo "备份当前版本..."
cp -r $APP_DIR $BACKUP_DIR/backup-$(date +%Y%m%d-%H%M%S)

# 2. 拉取最新代码
echo "拉取最新代码..."
cd $APP_DIR
git pull origin main

# 3. 安装依赖
echo "安装 Composer 依赖..."
composer install --prefer-dist --no-dev -o

# 4. 运行迁移
echo "运行数据库迁移..."
php artisan migrate --force

# 5. 清除并重建缓存
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

# 6. 优化自动加载
echo "优化自动加载..."
composer dump-autoload -o

# 7. 重启服务
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:*

# 清理旧版本(保留最近5个版本)
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
// 安装 Laravel Telescope(开发环境)
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate

// 生产环境使用 Laravel Horizon(队列监控)
composer require laravel/horizon
php artisan horizon:install

总结

Laravel 生产环境部署和性能优化是一个系统性工程,需要从多个维度进行考虑:

  1. 部署配置:正确的 Nginx/Apache 配置、SSL 证书、防火墙设置
  2. 性能优化:缓存策略、数据库优化、队列处理、资源压缩
  3. 监控维护:日志管理、性能监控、健康检查、自动化部署
  4. 安全防护:环境变量保护、文件权限、访问控制

通过实施这些最佳实践,你的 Laravel 应用将能够在生产环境中稳定、高效地运行,为用户提供优质的服务体验。记住,性能优化是一个持续的过程,需要根据实际的业务需求和用户反馈不断调整和改进。

本站由 提供部署服务