关于Yii CHttpSession性能优化篇之源码流程分析

当我们使用Yii数据库去保存Session时,只要简单的配置就可以完成这个功能,在进行性能优化这个主题之前,我们先来查看一下CHttpSession和CDBHttpSession源代码,探讨CHttpSession和CDBHttpSession的流程再进行深一步优化主题。

首先我们来先看下CHttpSession源码中的init,getUseCustomStorage,Open这三个方法

/**
  * Initializes the application component.
  * This method is required by IApplicationComponent and is invoked by application.
  */
  public function init()
  {
       parent::init();
       if($this->autoStart)
           $this->open();
       register_shutdown_function(array($this,'close'));
 }

            /**
             * Returns a value indicating whether to use custom session storage.
             * This method should be overriden to return true if custom session storage handler should be used.
             * If returning true, make sure the methods {@link openSession}, {@link closeSession}, {@link readSession},
             * {@link writeSession}, {@link destroySession}, and {@link gcSession} are overridden in child
             * class, because they will be used as the callback handlers.
             * The default implementation always return false.
             * @return boolean whether to use custom storage.
             */
            public function getUseCustomStorage()
            {
                    return false;
            }

            /**
             * Starts the session if it has not started yet.
             */
            public function open()
            {
                    if($this->getUseCustomStorage())
                            @session_set_save_handler(array($this,'openSession'),array($this,'closeSession'),array($this,'readSession'),array($this,'writeSession'),array($this,'destroySession'),array($this,'gcSession'));
                    if(@session_start()===false && YII_DEBUG)
                    {
                            $message=Yii::t('yii','Failed to start session.');
                            if(function_exists('error_get_last'))
                            {
                                    $error=error_get_last();
                                    if(isset($error['message']))
                                            $message=$error['message'];
                            }
                            Yii::log($message, CLogger::LEVEL_WARNING, 'system.web.CHttpSession');
                    }
            }

可以看到,当我们在protected/config/main.php文件组件配置中加入下面一行之后

'session' => array(
         'timeout' => 300,
     ),

可以看到init方法里面将自动启动并调用open方法,getUseCustomStorage方法始终返回true,告诉Yii使用自定义方式管理Session,将session管理的方法全部注册到@session_set_save_handler 函数里面由PHP自动回调,所以我们如果需要扩展自定义的session管理方法,仅仅需要继承CHttpSession, 重写openSession,readSession,writeSession, destroySession,gcSession 这五个方法即可,可见Yii提供了非常简洁和强大扩展功能方式解决Session管理问题, 像CDbHttpSession 和 CCacheHttpSession扩展起来都非常方便。

接下来我们再看这五个方法的调用流程,分游客和登陆两种情况,我们来看CWebUser的源代之后就一目了然,看CWebUser::init方法,可以看到调用Yii::app()->getSession()->open(),由这里将开启一个新session.

/**
      * Initializes the application component.
      * This method overrides the parent implementation by starting session,
      * performing cookie-based authentication if enabled, and updating the flash variables.
      */
      public function init()
      {
          parent::init();
          Yii::app()->getSession()->open();
          if($this->getIsGuest() && $this->allowAutoLogin)
                $this->restoreFromCookie();
          else if($this->autoRenewCookie && $this->allowAutoLogin)
                $this->renewCookie();
          if($this->autoUpdateFlash)
               $this->updateFlash();
          $this->updateAuthStatus();
       }

接下来将解释未登陆和登陆之前的流程:

  1. 当用户是游客时访问网站时首先将调用openSession, 打开session之后接着调用readSession, 然后调用writeSession.

  2. 当用户登陆之后,由CWebUser::login方法调用$this->changeIdentity($id,$identity->getName(),$states),再调用CHttpSession:: regenerateID重新生成sessionid方法,再调用readSession, writeSession.

public function login($identity,$duration=0)
    {
          $id=$identity->getId();
          $states=$identity->getPersistentStates();
          if($this->beforeLogin($id,$states,false))
          {
                 $this->changeIdentity($id,$identity->getName(),$states); //由此方法调用
           }
    }

changeIdentity 方法

PHP代码

    protected function changeIdentity($id,$name,$states)
    {
          Yii::app()->getSession()->regenerateID();  //由这里手动调用生成新的session id
          $this->setId($id);
          $this->setName($name);
          $this->loadIdentityStates($states);
    }
  1. 当用户退出时由CWebUser里面logout手动调用销毁当前session
public function logout($destroySession=true)
    {
         if($this->beforeLogout())
         {
                if($this->allowAutoLogin)
          {
              Yii::app()->getRequest()->getCookies()->remove($this->getStateKeyPrefix());
              if($this->identityCookie!==null)
              {
                                         $cookie=$this->createIdentityCookie($this->getStateKeyPrefix());
                                            $cookie->value=null;
                                            $cookie->expire=0;
                                            Yii::app()->getRequest()->getCookies()->add($cookie->name,$cookie);
                                    }
                            }
                            if($destroySession)
                                    Yii::app()->getSession()->destroy();  //由这里手动调用销毁
                            else
                                    $this->clearStates();
                            $this->afterLogout();
                    }
            }
  1. 当用户没有退出或者直接关闭浏览器时session并没有销毁,当session设定的timeout超过时,PHP将自动启动垃圾回收机制调用gcSession 将自动执行session清理动作。
'session' => array(
           'timeout' => 300,
    ),

在这里,不用再多解释,相信大家已经清楚Yii 的Session执行过程,接下来我们将继续探讨Yii CDBHttpSession数据库存储session性能优化实战

原文出自: IT快讯网 连接: 关于Yii CHttpSession性能优化篇之源码流程分析

0 1
2 followers
Viewed: 17 603 times
Version: 1.1
Category: Tips
Written by: Darwin Wen
Last updated by: Maurizio Domba Cerin
Created on: Aug 17, 2011
Last updated: 12 years ago
Update Article

Revisions

View all history

Related Articles