小白折腾服务器(四):队列 supervisor 与定时任务 crontab
5

主要学习:《L06教程 电商进阶》 8.6. 队列与定时任务
云服务器:阿里云 centos7

环境

之前用docker-compose搭了云服务器上的一套Lnmp环境,用deployer部署,基础应用可以跑了,可是要折腾队列的时候,试着想用deplyer配置Supervisor,发现delpoyer不能用在docker的容器中。
比如我之前的环境是nginx、php-fpm、mysql、redis在不同的容器中,而部署代码是部署在主机(用主机中的php),而代码运行都应该是在php-fpm那个容器中,执行 php artisan horizon:terminate 这句也应该是在容器中,然而deployer只能是ssh连到主机。。。连不到容器。。。蓝后,就不会了。。。。
去github找,好像遇到同样的问题也还挂着- -链接在此,How to deploy a project in laradock ?Make way for host-containers: Task-iterations and command-template functionality
要么是放弃deployer、要么是放弃docker、要么是用k8s,我就一台服务器,也是初学,k8s我机器配置目测也跑不起来,于是就把nginx+php直接搭在云服务器上,mysql+redis依旧用docker。php是之前就在服务器上,现在搭nginx。

nginx

yum install nginx
访问服务器外网ip(localhost),就能看到nginx欢迎页了
然后配项目位置,删掉原本的nginx.conf,复制一份nginx.conf.default的默认配置
将路径指向我的iu项目

rm -rf nginx.conf
cp nginx.conf.default nginx.conf
vim nginx.conf

开启nginx服务
systemctl start nginx
service php-fpm start
修改配置文件后 service php-fpm reload
报错了好几回,最后发现是拷贝nginx配置文件没拷好,查端口如果是因为端口占用,就杀掉进程

// 查看一下端口进程
# netstat -ntpl
# netstat -tunlp

参数解释

  • -t (tcp) 仅显示tcp相关选项
  •  -u (udp)仅显示udp相关选项
  •  -n 拒绝显示别名,能显示数字的全部转化为数字
  •  -l 仅列出在Listen(监听)的服务状态
  •  -p 显示建立相关链接的程序名

php-fpm

这会儿还没phpfpm模块
yum -y install php72w-fpm

开启php-fpm服务
systemctl start nginx
service php-fpm start
到这里浏览器访问,才能看到项目欢迎页。然后是 mysql 和 redis,配置的文件链接地址都是之前用docker-compose时候配好的,这里就不改了。adminer是在线数据库管理页面,我自已本地用SequelPro已经连接上了,就先不弄了。
(域名配置下可以正常访问,就正常了那么一秒,就要备案balabala.....嫌麻烦,算了吧
项目欢迎页:http://120.27.8.8/welcome
phpinfo页面:http://120.27.8.8/info
项目文档页面:http://120.27.8.8/doc/index (文档是markdowm,只加了架子.....
项目日志页面:http://120.27.8.8/ (仅开发环境)

mysql

docker run -d -p 3306:3306 -v /root/aen233-dnmp/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
测试mysql:http://120.27.8.8/db
测试db页面就是很简单的读取user表的第一条数据

redis

docker run -d -p 6379:6379 -v /root/aen233-dnmp/redis:/data redis:alpine
测试redis:http://120.27.8.8/redis
测试redis页面就是很简单的set和get
环境就这样了

报错与解决

1.mysql的问题,主要参考:付杰问答:大家有没有用 mysql的json类型...

商品表本地测试都ok,到了云服务器上报SQLSTATE[HY000]: General error: 2036,搜了半天,将php_mysql扩展改成php_mysqlnd扩展,没用。最后将服务器上数据库中商品表的json类型改成text类型,好了。

mysql的json类型是5.7的新特性,建议做程序开发不要用最高版本的配置去开发项目,最高版本并不代表就是最好的!或许是mysql5.7 新特性目前在linux下还不兼容;

2.redis的问题,主要参考:笔记:解决redis连接错误:MISCONF Redis
某次部署完之后,horizon没法启动,查报错是:

MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.

究其原因是因为强制把redis快照关闭了导致不能持久化的问题,在网上查了一些相关解决方案,通过stop-writes-on-bgsave-error值设置为no即可避免这种问题。

有两种修改方法,一种是通过redis命令行修改,另一种是直接修改redis.conf配置文件
命令行修改方式示例:
127.0.0.1:6379> config set stop-writes-on-bgsave-error no
修改redis.conf文件:
vi打开redis-server配置的redis.conf文件,然后使用快捷匹配模式:/stop-writes-on-bgsave-error定位到stop-writes-on-bgsave-error字符串所在位置,接着把后面的yes设置为no即可。

我用的命令行修改方式,
docker exec -it 0d redis-cli 0d是我的redis容器
127.0.0.1:6379> config set stop-writes-on-bgsave-error no

队列

代码-新建话题时生成优化SEO的slug

把L教程几本都翻过,好像第一次讲队列是《L02 实战进阶——6.8.SEO 友好的 URL》
建立相关表,topics、categories,然后照着6.9使用队列,实现了一遍

horizon

composer require laravel/horizon
php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"
php artisan horizon

服务器配置Supervisor

环境是centos7,与L6教程的ubuntu稍微有些不一致
主要参考:Centos7 中使用Supervisor守护进程
1.安装supervisor
yum install Supervisor

2.启动服务
supervisord -c /etc/supervisord.conf
3.编辑配置文件
cd /etc/supervisord.d
在/etc/supervisord.d目录下创建一个iu.ini文件并编辑如下

[program:iu-horizon]
process_name=%(program_name)s
command=php /var/www/html/iu-deployer/current/artisan horizon
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/www/html/iu-deployer/current/storage/logs/worker.log
  • program:iu-horizon 代表这个配置的名称是 iu-horizon;
  • process_name= 代表这个进程在 Supervisor 内部的命名;
  • command= 代表要执行的命令;
  • autostart=true 代表这个进程跟随 Supervisor,只要 Supervisor 启动了,就启动这个进程;
  • autorestart=true 代表要求 Supervisor 监听进程状态,假如异常退出就再次启动;
  • redirect_stderr=true 代表输出错误信息;
  • stdout_logfile= 代表将进程的输出保存到日志文件中。

还是偷懒,全部都是root用户。
4.重载配置文件
执行命令使用新的配置文件运行supervisor服务
supervisorctl reload

调整deployer脚本

本地deploy.php中添加代码

desc('Restart Horizon');
task('horizon:restart', function() {
    run('{{bin/php}} {{release_path}}/artisan horizon:terminate');
});

// 在 deploy:symlink 任务之后执行 horizon:restart 任务
after('deploy:symlink', 'horizon:restart');
日志文件:/var/www/html/iu-deployer/releases/5/storage/logs/worker.log

Horizon started successfully.
Horizon started successfully.
[2019-01-04 18:17:15][1] Processing: App\Jobs\Blog\TranslateSlug
[2019-01-04 18:17:15][1] Processed:  App\Jobs\Blog\TranslateSlug
[2019-01-04 18:45:47][2] Processing: App\Jobs\Blog\TranslateSlug
[2019-01-04 18:45:47][2] Processed:  App\Jobs\Blog\TranslateSlug

In Client.php line 370:

  MISCONF Redis is configured to save RDB snapshots, but it is currently not   
  able to persist on disk. Commands that may modify the data set are disabled  
  , because this instance is configured to report errors during writes if RDB  
   snapshotting fails (stop-writes-on-bgsave-error option). Please check the   
  Redis logs for details about the RDB error.                             

在worker.log中也可以看到redis挂了,队列也就挂了

报错与解决

  1. deploy部署时报错

    Problem 1
      - Installation request for laravel/horizon v2.0.0 -> satisfiable by laravel/horizon[v2.0.0].
      - laravel/horizon v2.0.0 requires ext-posix * -> the requested PHP extension posix is missing from your system.

    解决:yum -y install php72w-posix(服务器)
    如果phppfm使用docker容器,dockerFile 加一句 RUN docker-php-ext-install posix

  2. Laravel Horizon启动时报错 undefined function Laravel\Horizon\Console\pcntl_asyn_signals
    解决:使用horizon需要pcntl扩展,安装一下就好了

定时任务

代码-众筹结束逻辑

把L教程几本都翻过,好像第一次讲定时任务是《L06 电商进阶——4.8. 众筹结束逻辑》
建立相关表,shop_crowdfunding_products,修改相关表shop_products,
商品的相关表是之前《L05 Laravel 教程 - 电商实战 ( Laravel 5.5 ) 》5.1. 商品的数据结构设计 时自己也做了一遍,(我看课程是挑着看,看了就实践,不用课程环境,学习分析问题的思考模式、解决问题的方法与小技巧),当时是多维度 SKU 应该有所讨论?这篇很感兴趣,也是这篇去试着用mysql json的思维。
我现在的代码只有最简单的时间到了根据金额修改状态(成功/失败),还没有失败后退款的逻辑,就最简单的定时任务咯

服务器配置定时任务crontab

主要参考: CentOS Crontab(定时任务)
1.安装crontab:
yum install crontabs
说明:
启动服务:service crond start
关闭服务:service crond stop
重启服务:service crond restart
重新载入配置:service crond reload
查看crontab服务状态:service crond status
加入开机自动启动:chkconfig crond on
2.编辑命令

   1)、在命令行输入: crontab -e 然后添加相应的任务,wq存盘退出

   2)、直接编辑/etc/crontab 文件,即vi /etc/crontab,添加相应的任务

编辑内容为:


* * * * * php /var/www/html/iu-deployer/current/artisan schedule:run >> /var/www/html/iu-deployer/current/storage/logs/cron.log 2>&1
  • 前面的 5 个 * 代表这个定时任务每分钟执行一次,
  • 后面的则是这个定时任务要执行的命令,
  • 同时我们使用 Linux 的管道 >> 将定时任务的输出追加到 cron.log 文件末尾,
  • 2 > &1 代表将错误输出也重定向到普通输出,即也输出到 cron.log 文件。

3.查看命令: crontab -l

日志查看

开发环境定时任务日志:http://120.27.8.8/?file=cron.log

日志文件:/var/www/html/iu-deployer/releases/5/storage/logs/cron.log
Running scheduled command: '/usr/bin/php' 'artisan' cron:finish-crowdfunding > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php' 'artisan' cron:finish-crowdfunding > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php' 'artisan' cron:finish-crowdfunding > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php' 'artisan' cron:finish-crowdfunding > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php' 'artisan' cron:finish-crowdfunding > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php' 'artisan' cron:finish-crowdfunding > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php' 'artisan' cron:finish-crowdfunding > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php' 'artisan' cron:finish-crowdfunding > '/dev/null' 2>&1
Running scheduled command: '/usr/bin/php' 'artisan' cron:finish-crowdfunding > '/dev/null' 2>&1

上传图片好麻烦- -,还得弄图床- -,不弄了

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 2

http://120.27.8.8/doc/index 这个页面的markdown用什么解析的?
上传图片不用图床,本站直接截图粘贴就行

file

1周前
aen233

@lovecn 那就是我写这篇时网不太好,图片一直复制粘贴不上来。
就是Parsedown, laravel本来就集成了,都不需要composer,可以直接用

  $parseDown = new Parsedown();
  $html = $parseDown->text(file_get_contents($docPath));
1周前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!