laravel 使用队列

项目从 laravel 5.2 迁移到 5.7,发现之前的 Mail 有点问题,今天重构了下,用到几个地方:

	参考文档:
		https://laravelacademy.org/post/9569.html

	用到的几个技术点:
		app/Mail/Offer.php - 可邮件类
		resources/views/emails/offer.blade.php - email 模板
		app/Providers/EventServiceProvider.php - 注册邮件事件
		app/Listeners/LogSentMessage.php - 邮件发送成功回调

看了点源码,感觉绕的有点麻烦,不过架构应该清晰吧。。。。

同事一直想在项目中使用队列,这个问题我也纠结了好久了,干脆就趁这次,整下队列,下面记录下过程:

	参考文档:
		https://laravelacademy.org/post/9574.html

	需要的 2 个额外的技术:
		supervisor
		horizon 


	1.supervisor
		参考文章:
			http://supervisord.org/
			http://liyangliang.me/posts/2015/06/using-supervisor/
			http://blog.51cto.com/lixcto/1539136
			https://www.load-page.com/manuals/web-server/chapter-tools/supervisor.html
			https://www.cnblogs.com/zhoujinyi/p/6073705.html
			https://laravel-china.org/articles/3729/use-laravel-queue-to-understand-the-knowledge
			https://www.jianshu.com/p/f8735b039c67?from=groupmessage
			https://blog.csdn.net/zou79189747/article/details/80403016

		相信看了上面的几篇文章,基本对 supervisor 就有一个大概的认识了,我总结的肯定没人家的好,这里简述下几个核心:
			1>安装完 supervisor,总共有几个组件:
				1)supervisord 			// 服务端(redis 的 redis-sever)
				2)supervisorctl 		// 客户端(redis 的 redis-cli)
				3)web-server 管理界面		// 我们可以通过 web 来查看

			2>supervisor 的使用步骤:
				1)先配置 supervisord
					supervisord.conf

					分几大块:
						[unix_http_server] - socket 配置(方式1)
						[inet_http_server] - TCP 配置(web-server 应该得使用它)(方式2)
						[supervisord] - 服务端配置
						[rpcinterface:supervisor] - RPC 接口相关,supervisor 和 web-server 必须开启
						[supervisorctl] - 客户端配置
						[eventlistener:theeventlistenername] - 事件监听(和 program 类似,应该是可以定义多个监听事件)
						[group:thegroupname] - 将多个进程,划分到一个组,统一操作
						[program:theprogramname] - 进程配置
						[include] - 引入其他配置,我们将 '进程配置' 都放到独立的文件引入

				2)配置我们自己的进程配置文件,尽量是每个进程单独配置个配置
					在 supervisord.conf 最后,有个 include xxx,可以将我们自定义的进程配置文件载入

				3)启动 supervisord
					supervisord -c /xxx/supervisord.conf 		// 可以使用 -c 指定配置文件路径

				4)可以启动 supervisorctl 客户端,来进行交互操作
					supervisorctl -c /etc/supervisord.conf 		// 也可以使用 -c 指定配置文件路径(它的配置区块,和 supervisord 在同一个配置文件内)

					supervisorctl --help 		// 查看命令使用
						/usr/local/bin/supervisorctl [options] [action [arguments]]

					可用的 action 有(使用 supervisorctl help 查看):
						add
						exit
						open
						reload
						...

					每个 action 的使用,可通过命令查看
						supervisorctl help add
						supervisorctl help exit
						...

				5)web server 访问:
					http://localhost:9001/

			4>laravel 队列的监听配置:
				[program:laravel-worker]
				process_name=%(program_name)s_%(process_num)02d
				command=php /data/wwwroot/app/artisan queue:work redis --sleep=3 --tries=3
				autostart=true
				autorestart=true
				;user=forge
				numprocs=8
				redirect_stderr=true
				stdout_logfile=/data/wwwroot/app/storages/supervisor/worker.log

				参考官方文档:
					https://laravelacademy.org/post/8369.html#toc_17

		1>mac 本地安装
			安装:
				brew install supervisor 		// 看提示依赖了 pkg-config, sphinx-doc, gdbm, openssl, sqlite and python@2,安装了十来分钟呢

			安装完成后,提示了:
				brew services start supervisor		// 现在启动,并在登录时重新启动
				supervisord -c /usr/local/etc/supervisord.ini	// 默认是后台运行,希望前台运行

			启动发现问题:
				1)[program:theprogramname] 里有一个 user 配置。默认是禁用的,我们如果设置了 user,表示可以使用 user 来管理当前的 program。所以这个 user 必须是系统内存在的用户。

				2)启动 supervisorctl 报错:
					http://localhost:9001 refused connection

					查看默认的 supervisorctl 配置:
						/*
							[unix_http_server]
							file=/usr/local/var/run/supervisor.sock   ; the path to the socket file
							;chmod=0700                 ; socket file mode (default 0700)
							;chown=nobody:nogroup       ; socket file uid:gid owner
							;username=user              ; default is no username (open server)
							;password=123               ; default is no password (open server)

							;[inet_http_server]         ; inet (TCP) server disabled by default
							;port=127.0.0.1:9001        ; ip_address:port specifier, *:port for all iface
							;username=user              ; default is no username (open server)
							;password=123               ; default is no password (open server)

							// 这里得说明下:
							serverurl 有2种方式,就是上面的
								unix_http_server
								inet_http_server	
							默认是使用的 unix 配置,我们也可以开启 inet 配置

							[supervisorctl]
							serverurl=unix:///usr/local/var/run/supervisor.sock ; use a unix:// URL  for a unix socket
							;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
						*/

					serverurl 我们配置的是 socket,而非 tcp 


					而 supervisorctl --help 可以看到:
						-s/--serverurl URL -- URL on which supervisord server is listening
							(default "http://localhost:9001")

					默认是以 'tcp' 来请求的

					解决方法:
						1.修改 supervisorctl 的 serverurl 配置
						2.启动 supervisorctl 时,指定 -s 参数

				3)启动是启动了,又报错:
					supervisor: couldn't setuid to 4294967294: Can't drop privilege as nonroot user
					supervisor: child process was not spawned

					屏蔽程序里的 ;user=xxx(其他定义 user 方法,没看)

				/*
					搞不定了。。。。。
					127.0.0.1:9001 也一直被拒绝
					还查了半天,开启 mac 端口的文章,都不行!!!
					放弃!!!
					等待高手解答!!!
				 */

		2>linux 服务器上安装
			好多安装方式,推荐使用的这个,正好也有 easy_install 命令,就该方式安装:
				easy_install supervisor

			easy_install 安装方式,没有配置文件:
				echo_supervisord_conf		// 查看配置文件
				echo_supervisord_conf > /etc/supervisord.conf 		// 生成配置文件

			运行:
				supervisord -c /etc/supervisord.conf

			配置:
				vim /etc/supervisord.conf
				开启最下方的 [include],包含的文件目录为:/etc/supervisor.d/

				mkdir /etc/supervisor.d

				在 supervisor.d/ 下配置,各种进程的配置

			web server 配置:
				[inet_http_server]
				port=127.0.0.1:9001

				默认的 127.0.0.1:9001,通过 elinks,在服务器上确实可以访问!
				但我们使用的是云服务器,得通过 '外网:9001' 来访问,死活不行!!!
				对了,云服务器的 iptables 也必须开启 9001 端口

				最终在一篇文章里,看到个配置,终于可以访问(我都不知道花了多久时间):
				[inet_http_server]
				port=*:9001

			supervisor 退出、重启等,好像得使用 kill -HUP,搜索到一些文章来处理该问题:
				1.kill -s SIGTERM $(supervisorctl pid)

				2.supervisor 各个系统的启动脚本:
					https://github.com/Supervisor/initscripts

				3.https://www.load-page.com/manuals/web-server/chapter-tools/supervisor.html(这个比较给力,打算用这个)

	2.horizon
		参考文章:
			https://laravelacademy.org/post/8492.html

		安装:
			composer require laravel/horizon

		发布前端资源、配置:
			php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"

		配置文件:	
			config/horizon.php

		运行:
			php artisan horizon - 启动
			php artisan horizon:pause - 暂停
			php artisan horizon:continue - 继续
			php artisan horizon:terminate - 优雅地终止,会在所有当前正在执行的任务全部完成后退出

		进程监控:
			使用上面提到的 supervisor 来管理

			配置:
				[program:horizon]
				process_name=%(program_name)s
				command=php /data/wwwroot/app/artisan horizon
				autostart=true
				autorestart=true
				user=forge
				redirect_stderr=true
				stdout_logfile=/data/wwwroot/app/storages/supervisor/horizon.log

		访问:
			/horizon

		访问限制,线上访问 horizon,我们需要设置访问策略(不用考虑配置个其他目录...):
			AppServiceProvider -> boot() 调用
				Horizon::auth(function ($request) {
				    // return true / false;
				});

		队列任务等待超时通知:
			AppServiceProvider 调用不同的通知方法,取决于我们想使用哪种类型的通知
				Horizon::routeMailNotificationsTo('[email protected]');
				Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
				Horizon::routeSmsNotificationsTo('15556667777');
			config/horizon.php 配置 waits 来配置等待超时时间:
				'waits' => [
				    'redis:default' => 60,
				],

		监控:
			app/Console/Kernel.php 配置计划任务

				// 监控后台查看任务和队列的等待时间和吞吐量信息,获取实时信息
				$schedule->command('horizon:snapshot')->everyFiveMinutes();


猜你喜欢

转载自blog.csdn.net/beyond__devil/article/details/83659146