风险提示

使用Stone的一个很重要的事情是, 需要始终对内存使用抱有敬畏之心。 在未充分了解风险前, 请不要在实际项目中轻易尝试,否则可能产生非常严重的后果!!

比如,Laravle的Cookie实现了单例模式:

<?php

namespace Illuminate\Cookie;

use Illuminate\Support\ServiceProvider;

class CookieServiceProvider extends ServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('cookie', function ($app) {
            $config = $app['config']['session'];

            return (new CookieJar)->setDefaultPathAndDomain($config['path'], $config['domain'], $config['secure']);
        });
    }
}

这样,开发者在任何地方可以往Response里追加cookie, 使用:

Cookie::queue('key', 'value', 60);

所有的Cookie都被维护在一个数组中,等待Response发送到客户端:

<?php

namespace Illuminate\Cookie;

use Illuminate\Support\Arr;
use Symfony\Component\HttpFoundation\Cookie;
use Illuminate\Contracts\Cookie\QueueingFactory as JarContract;

class CookieJar implements JarContract
{
    /**
     * The default path (if specified).
     *
     * @var string
     */
    protected $path = '/';

    /**
     * The default domain (if specified).
     *
     * @var string
     */
    protected $domain = null;

    /**
     * The default secure setting (defaults to false).
     *
     * @var bool
     */
    protected $secure = false;

    /**
     * All of the cookies queued for sending.
     *
     * @var array
     */
    protected $queued = [];

在原来的PHP-FPM下,这不会有任何问题,因为请求结束后PHP对释放掉所有资源。 但Stone常驻内存后, 请求的资源没有在请求结束后释放, 因为cookie对象被ioc容器引用,PHP GC不会回收这部分内存。因此下一个请求再使用Cookie的时候获取的是同一个Cookie对象

比如, 第一个请求:

Cookie::queue('first', 'test', 60);

这个时候queue数组里已经有first的cookie。

第二个请求:

Cookie::queue('secend', 'test', 60);

由于获取的还是上一个cookie对象, 因此queue数组包含first和second的cookie!

想像下, 如果这是一个关于Session Id的cookie, 会产生多么严重的后果。

同样,Laravel的Auth对象, 也可能出现类似的问题

内存泄露什么的可能只是影响稳定性, 但是这个处理不当会带来难以估计的损失, 这是使用Stone或者类似常驻内存方案的最大风险。

Stone通过实例快照来解决这个问题。 简单来说就是在对象建立的时候把对象的当前状态保存下来, 当请求结束后通过保存的数据把实例恢复成初始化的状态,这样就可以避免这个问题。

在config/stone.php的配置中,你可以定义哪些对象需要建立快照。

        // 需要建立快照的绑定
        'snap_bindings' => [
            'view',
            'cookie',
            'session',
            'session.store',
            //'config', // debugbar 需要重置config
        ],

有关资源复用的更多细节, 请查看理解资源复用这个章节。

开始使用Stone

如果你已经了解这样的潜在风险, 并对此信心满满, 那开始使用吧:

results matching ""

    No results matching ""