承接 kfosoft/symfony-daemonizable-command 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

kfosoft/symfony-daemonizable-command

Composer 安装命令:

composer require kfosoft/symfony-daemonizable-command

包简介

Daemonizable (endless running) commands for Symfony.

README 文档

README

A small bundle to create endless running commands with Symfony.

These endless running commands are very easy to daemonize with something like Upstart or systemd.

Why do I need this?

Because you want to create long running PHP/Symfony processes! For example to send mails with large attachment, process (delayed) payments or generate large PDF reports. They query the database or read from a message queue and do their job. This bundle makes it very easy to create such processes as Symfony commands.

How to install?

Use composer to include it into your Symfony project:

composer require kfosoft/symfony-daemonizable-command

What version to use?

Symfony did make some breaking changes, so you should make sure to use a compatible bundle version:

  • Version 3.0.* for Symfony 4 and 5 and higher
  • Version 2.0.* for Symfony 3
  • Version 1.3.* for Symfony 2.8+

How to use?

Just create a Symfony command that extends from EndlessCommand and off you go. Here is a minimal example:

namespace Acme\DemoBundle\Command;

use Wrep\Daemonizable\Command\EndlessCommand;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputInterface;

class MinimalDemoCommand extends EndlessCommand
{
	// This is just a normal Command::configure() method
	protected function configure()
	{
		$this->setName('acme:minimaldemo')
		     ->setDescription('An EndlessCommand implementation example');
	}

	// Execute will be called in a endless loop
	protected function execute(InputInterface $input, OutputInterface $output)
	{
		// Tell the user what we're going to do.
		// This will be a NullOutput if the user doesn't want any output at all,
		//  so you don't have to do any checks, just always write to the output.
		$output->write('Updating timestamp... ');

		// Do some work
		file_put_contents( '/tmp/acme-timestamp.txt', time() );

		// Tell the user we're done
		$output->writeln('done');
	}
}

Run it with php app/console acme:minimaldemo.

An example with all the bells and whistles is also available and gives a good overview of best practices and how to do some basic things.

How to daemonize?

Alright, now we have an endless running command in the foreground. Usefull for debugging, useless in production! So how do we make this thing a real daemon?

You should use systemd to daemonize the command. They provide very robust daemonization, start your daemon on a reboot and also monitor the process so it will try to restart it in the case of a crash.

If you can't use Upstart or systemd, you can use .lock file with LockHandler with crontab wich start script every minute.

An example Upstart script is available, place your script in /etc/init/ and start the daemon with start example-daemon. The name of the .conf-file will be the name of the daemon. A systemd example is not yet available, but it shouldn't be that hard to figure out.

Command line switches

A few switches are available by default to make life somewhat easier:

  • Use -q to suppress all output
  • Use --run-once to only run the command once, usefull for debugging
  • Use --detect-leaks to print a memory usage report after each run, read more in the next section

Memory usage and leaks

Memory usage is very important for long running processes. Symfony is not the smallest framework around and if you leak some memory in your execute method your daemon will crash! The EndlessCommand classes have been checked for memory leaks, but you should also check your own code.

How to prevent leaks?

Always start your command with the -e prod --no-debug flags. This disables all debugging features of Symfony that will eat up more and more memory.

Make sure you cleanup in the execute-method, make sure you're not appending data to an array every iteration or leave sockets/file handles open for example.

In case you are using the fingers-crossed handler in Monolog, this will also be a source of memory leaks. The idea of this handler is to keep all below-threshold log entries in memory and only flush those in case of an above-threshold entry. You can still use the fingers-crossed handler as long as you manually flush it at the end of the execute-method:

foreach ($this->getContainer()->get('logger')->getHandlers() as $handler)
{
    if ($handler instanceof FingersCrossedHandler) {
        $handler->clear();
    }
}

Detecting memory leaks

Run your command with the --detect-leaks flag. Remember that debug mode will eat memory so you'll need to run with -e prod --no-debug --detect-leaks for accurate reports.

After each iteration a memory report like this is printed on your console:

== MEMORY USAGE ==
Peak: 30038.86 KByte stable (0.000 %)
Cur.: 29856.46 KByte stable (0.000 %)

The first 3 iterations may be unstable in terms of memory usage, but after that it should be stable. Even a slight increase of memory usage will crash your daemon over time!

If you see an increase/stable/decrease loop you're probably save. It could be the garabage collector not cleaning up, you can fix this by using unset on variables to cleanup the memory yourself.

Busting some myths

Calling gc_collect_cycles() will not help to resolve leaks. PHP will cleanup memory right in time all by itself, calling this method may slow down leaking memory, but will not solve it. Also it makes spotting leaks harder, so just don't use it.

If you run Symfony in production and non-debug mode it will not leak memory and you do not have to disable any SQL loggers. The only leak I runned into is the one in the MonologBundle mentioned above.

Working with Doctrine

For reasons EndlessContainerAwareCommand clears after each Iteration Doctrine's EntityManager. Be aware of that. You can override finishIteration() to avoid this behaviour but you have to handle the EM on your own then.

kfosoft/symfony-daemonizable-command 适用场景与选型建议

kfosoft/symfony-daemonizable-command 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 28 次下载、GitHub Stars 达 0, 最近一次更新时间为 2020 年 10 月 06 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「symfony」 「Symfony2」 「daemon」 「background process」 「long running process」 「backgrounding」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 kfosoft/symfony-daemonizable-command 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 kfosoft/symfony-daemonizable-command 我们能提供哪些服务?
定制开发 / 二次开发

基于 kfosoft/symfony-daemonizable-command 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 28
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 8
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 41
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2020-10-06