- 最近正好在弄升级
PHP
版本的事情, 然后顺便把 https://github.com/seth-shi/monday-shop 的版本给升级了
已有方案
- 如果愿意花钱处理可以考虑使用 https://laravelshift.com/
- 也可以用这个项目快速比较需要改动的地方 https://laravel-upgrade-helper.github.io/
升级过程
项目准备
- 假设我现在的项目名为
/var/www/monday-shop
- 在
monday-shop
项目内创建一新的laravel
项目(同一个项目内方便复制粘贴文件)composer create-project laravel/laravel=10.* laravel10
- 这时候项目内多了一个
/var/www/monday-shop/laravel10
依赖处理
- 更新依赖
- 把
/var/www/monday-shop/laravel10/composer.json
的require
和require-dev
部分更新到/var/www/monday-shop/composer.json
(注意删除旧版本的部分) - 删除
/var/www/monday-shop/composer.lock
- 把
- 安装依赖
- 运行
composer install
, 这时候会出现很多错误, 只能照着报错不断更新依赖 - 如果报错类似下面的问题, 就去
github
找到ramsey/uuid
设配的版本, 然后修改composer.json
文件, 重复执行1, 2步骤
- 运行
composer install
No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- laravel/framework[v10.10.0, ..., v10.48.4] require ramsey/uuid ^4.7 -> found ramsey/uuid[4.7.0, ..., 4.7.5] but it conflicts with your root composer.json require (^3.8).
- 升级之后, 如果不确定这个依赖是否有用, 执行
composer depends xxx/xxxx
来查看是否有用, 如果不用到删除即可
文件更改
- 复制
/var/www/monday-shop/laravel10
的基础文件到/var/www/monday-shop/
├─app
│ ├─Console
│ ├─Exceptions
│ ├─Http
│ │ ├─Controllers
│ │ └─Middleware
│ ├─Models
│ └─Providers
├─bootstrap
│ └─cache
├─config
├─database
│ ├─factories
│ ├─migrations
│ └─seeders
├─public
├─resources
│ ├─css
│ ├─js
│ └─views
├─routes
├─storage
│ ├─app
│ ├─framework
│ └─logs
├─tests
│ ├─Feature
│ └─Unit
- 例如
app/Exceptions/Handler.php
,app/Http/Kernel.php
等等, 这些文件复制内容的时候需要仔细对比是否自己修改过
- 我处理的时候一般一个文件夹一个文件夹处理, 比如从
app/Console
开始处理 - 处理完之后删除
app/Console
目录(删除目录是/var/www/monday-shop/laravel10
) - 下一个目录是
app/Exceptions
, 重复1, 2 步骤, 直至/var/www/monday-shop/laravel10
目录为空
处理报错
- 运行服务:
php artisan serve
- 运行之后如果有报错按需解决, 服务启动之后, 查看
storage/logs
下的目录错误, 按需解决 - 可能遇到的
laravel
的helpers
函数不存在执行composer require laravel/helpers
容器化
- 升级完成之后, 就不需要https://github.com/hhxsv5/laravel-s的运行方案了
- 换成官方https://github.com/laravel/octane的常住内存方案
composer require laravel/octane
-
容器化方案操作https://github.com/exaco/laravel-octane-dockerfile
- 通过
supervisorctl
管理进程 - 支持队列运行
- 支持定时任务
- 通过
-
文件参考内容
.rr.yaml
- 如果出现: RoadRunner can’t communicate with the worker
- 请修改
.rr.yaml
为下面的配置, 主要是logs.channels
的配置为标准输出(把level
开启debug
)
version: '3'
rpc:
listen: 'tcp://127.0.0.1:6001'
server:
command: ""
relay: pipes
http:
middleware: [ "static", "gzip", "headers" ]
max_request_size: 20
access_logs: false
static:
dir: "public"
forbid: [ ".php", ".htaccess" ]
uploads:
forbid: [".php", ".exe", ".bat", ".sh"]
address: "0.0.0.0:2114"
pool:
allocate_timeout: 10s
destroy_timeout: 10s
supervisor:
max_worker_memory: 256
exec_ttl: 60s
## 这里注意如果要输出标准输出必须在 channels 才会写 stdout
logs:
mode: production
level: debug
encoding: console
output: stderr
err_output: stderr
channels:
http:
mode: production
level: panic
encoding: console
output: stdout
err_output: stderr
server:
mode: production
level: info
encoding: json
output: stdout
err_output: stdout
rpc:
mode: production
level: debug
encoding: console
output: stderr
err_output: stdout
status:
address: localhost:2114
Dockerfile
FROM composer:latest AS vendor
FROM php:8.2-cli-bookworm AS base
ARG TZ=PRC
ENV DEBIAN_FRONTEND=noninteractive \
TERM=xterm-color \
OCTANE_SERVER=roadrunner \
ROOT=/var/www \
COMPOSER_FUND=0 \
COMPOSER_MAX_PARALLEL_HTTP=24
WORKDIR ${ROOT}
SHELL ["/bin/bash", "-eou", "pipefail", "-c"]
RUN ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone
################################################################################################
## 安装依赖
################################################################################################
ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN apt-get update; \
apt-get upgrade -yqq; \
apt-get install -yqq --no-install-recommends --show-progress \
apt-utils \
curl \
wget \
nano \
ncdu \
ca-certificates \
supervisor \
libsodium-dev \
# Install PHP extensions
&& install-php-extensions \
bz2 \
pcntl \
mbstring \
bcmath \
sockets \
pgsql \
pdo_pgsql \
opcache \
exif \
pdo_mysql \
zip \
intl \
gd \
redis \
rdkafka \
memcached \
igbinary \
ldap \
&& apt-get -y autoremove \
&& apt-get clean \
&& docker-php-source delete \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
&& rm /var/log/lastlog /var/log/faillog
################################################################################################
## 这一步很重要, 为了缓存 composer 依赖
################################################################################################
COPY --from=vendor /usr/bin/composer /usr/bin/composer
COPY composer.json composer.lock ./
RUN composer install \
--no-dev \
--no-interaction \
--no-autoloader \
--no-ansi \
--no-scripts \
--audit
################################################################################################
## 复制代码文件和部署文件
################################################################################################
COPY . .
COPY deployment/supervisord.*.conf /etc/supervisor/conf.d/
COPY deployment/php.ini ${PHP_INI_DIR}/conf.d/99-octane.ini
COPY deployment/start-container /usr/local/bin/start-container
################################################################################################
## 再次 composer install 生成映射类
################################################################################################
RUN composer install \
--classmap-authoritative \
--no-interaction \
--no-ansi \
&& composer clear-cache
RUN if composer show | grep spiral/roadrunner-cli >/dev/null; then \
./vendor/bin/rr get-binary; else \
echo "`spiral/roadrunner-cli` package is not installed. Exiting..."; exit 1; \
fi
################################################################################################
## 权限目录设置
################################################################################################
RUN chmod +x rr /usr/local/bin/start-container
RUN mkdir -p \
storage/framework/{sessions,views,cache,testing} \
storage/logs \
bootstrap/cache && chmod -R a+rw storage
ENTRYPOINT ["start-container"]
HEALTHCHECK --start-period=5s --interval=2s --timeout=5s --retries=8 CMD php artisan octane:status || exit 1
php.ini
[PHP]
post_max_size = 100M
upload_max_filesize = 100M
expose_php = 0
realpath_cache_size = 16M
realpath_cache_ttl = 360
;; 使用 roadrunner 开不开 opcache 影响不大
[Opcache]
opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 128M
opcache.use_cwd = 0
opcache.max_file_size = 0
opcache.max_accelerated_files = 32531
opcache.validate_timestamps = 0
opcache.file_update_protection = 0
opcache.interned_strings_buffer = 16
opcache.file_cache = 60
[JIT]
opcache.jit_buffer_size = 64M
opcache.jit = function
opcache.jit_prof_threshold = 0.001
opcache.jit_max_root_traces = 2048
opcache.jit_max_side_traces = 256
[zlib]
zlib.output_compression = On
zlib.output_compression_level = 9
start.container
#!/usr/bin/env bash
set -e
container_mode=${CONTAINER_MODE:-http}
queue_name=${QUEUE_NAME:-default}
echo "Container mode: $container_mode"
initialStuff() {
php artisan config:cache;
}
if [ "${container_mode}" = "http" ]; then
initialStuff
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.roadrunner.conf
elif [ "${container_mode}" = "scheduler" ]; then
initialStuff
php artisan schedule:work
elif [ "${container_mode}" = "worker" ]; then
initialStuff
php artisan queue:work redis --queue="${queue_name}" --daemon --sleep=3 --tries=3 --timeout=3600
else
echo "Container mode mismatched."
exit 1
fi
supervisord.roadrunner.conf
[supervisord]
nodaemon=true
user=root
logfile=/dev/stdout
logfile_maxbytes=0
pidfile=/var/run/supervisord.pid
[unix_http_server]
file=/var/run/supervisor.sock ; (the path to the socket file)
chmod=0700 ; sockef file mode (default 0700)
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[program:octane]
process_name=%(program_name)s_%(process_num)02d
command=php %(ENV_ROOT)s/artisan octane:start --server=roadrunner --host=0.0.0.0 --port=9996 --rpc-port=6001 --workers=4 --log-level=warn --max-requests=0 --rr-config=%(ENV_ROOT)s/deployment/.rr.yaml
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr
stdout_logfile_maxbytes=0
stderr_logfile_maxbytes=0
- 队列相关的可查看此仓库: 容器化方案操作https://github.com/exaco/laravel-octane-dockerfile
K8s 部署其它部分
- HTTP
- 容器退出前可以加一个
sleep 10
来等待当前请求处理完成
- 容器退出前可以加一个
- 任务调度
- 使用无状态部署, 然后容器注入运行命令
php artisan schedule:work
- 增加容器退出前执行
php artisan down
- 并设置
ShutdownGracePeriod
时间大一点
- 使用无状态部署, 然后容器注入运行命令
- 队列
- 使用无状态部署即可, 容器运行的命令可以注入进去(以便运行不同的命令)
php artisan queue:work --queue=xxx
- 增加容器退出前执行
php artisan down
- 并设置
ShutdownGracePeriod
时间大一点 - 可考虑用官方的horizon方法(
php artisan horizon
) – (php artisan horizon:terminate
)
- 使用无状态部署即可, 容器运行的命令可以注入进去(以便运行不同的命令)
Horizon
- 安装
composer require laravel/horizon
- 发布资源
php artisan horizon:install
- 主要配置说明
return [
// 上面部分暂时忽略
'defaults' => [
// 这个部分是类似默认配置, 会和下面的 environments 部分合并
'supervisor-1' => [
// 对应 config/queue.php -> 里使用的 connections 配置
'connection' => 'redis',
// 要去消费的队列名, 等效于 (php artisan queue:work --queue=)
'queue' => ['default'],
// 我一般使用 simple, 这样子好控制容器内存,
'balance' => 'simple',
'autoScalingStrategy' => 'time',
// 进程数
'maxProcesses' => 1,
'maxTime' => 0,
'maxJobs' => 0,
'memory' => 128,
'tries' => 1,
// 队列的超时在这里设置, 等效于 (php artisan queue:work --timeout=)
'timeout' => 3600,
'nice' => 0,
],
],
'environments' => [
'production' => [
// supervisor-1 名字随便自定义
'supervisor-1' => [
// 如果是 balance=simple, 那么 maxProcesses 就是进程数量
'maxProcesses' => 10,
'balanceMaxShift' => 1,
'balanceCooldown' => 3,
],
],
'local' => [
'supervisor-1' => [
'maxProcesses' => 3,
],
],
],
];
- 鉴权说明
class HorizonServiceProvider extends HorizonApplicationServiceProvider
{
// 忽略上卖弄部分
protected function gate(): void
{
// $user = null (要设置这个, 否则会无授权)
Gate::define('viewHorizon', function ($user = null) {
// 自行修改判断逻辑
return session()->has('xxx');
});
}
}
- 效果图
结束
- 之后就可以愉快的运行了
遇到的错误
- JsonException Syntax error HttpWorker.php
- 检查一下
rr
二进制文件的版本
- 检查一下