巨大的CPU负载/性能差的php zend系统编写的Flash Builder数据向导



我是一名自学成才的AS3/Flex/AIR开发人员,我已经构建了一个运行在AIR上的触摸屏kiosk系统,可以从在线Flex应用程序远程管理内容。

这是我第一次做服务器端的东西,所以如果需要的话,请随时纠正我的问题。

AIR应用和Flex应用都连接到mysql数据库,使用php脚本和Zend框架进行简单的CRUD操作。信息亭每隔30秒调用服务器进行更新。

所有这些简单的服务器端php脚本是由Flash Builder的数据向导自动生成的。我做了简单的调整(gateway.php, amf_config.ini, mysqli连接参数),并将所有内容部署到客户端的服务器上。这是一个共享服务器类型。

现在,系统工作了。但效果缓慢。每个创建/读取/更新/删除操作都工作,但我认为它应该快得多。此外,这些操作给服务器的cpu带来了很大的负载。根据托管人员的说法,这个系统打开的php-cgi进程占用了服务器40%的cpu功率,这样做会减慢服务器上托管的其他站点的速度。

我的问题是:

首先,是否一开始就有问题,或者Zend框架是否期望这种性能?自动生成的脚本写的Flash Builder写得很差,可以优化吗?这种类型的系统可以保留在共享托管服务器上吗?我们是否应该转移到VPS服务器以获得更好的性能?是否有可能,如果我在mysql数据库上使用phpmyadmin创建的表没有优化构建,它会对性能产生这种影响?

我不知道php或mysql。如能提供任何帮助,我将不胜感激。

萨尔河

这是Flash Builder编写的脚本:我没有添加任何东西-只是改变了连接参数。

<?php
class KiosksService {
   var $username = "--------";
   var $password = "--------";
   var $server = "--------";
   var $port = "3306";
   var $databasename = "--------";
   var $tablename = "kiosks";
   var $connection;
   /**
    * The constructor initializes the connection to database. Everytime a request is 
    * received by Zend AMF, an instance of the service class is created and then the
    * requested method is invoked.
    */
   public function __construct() {
        $this->connection = mysqli_connect(
                          $this->server,  
                          $this->username,  
                          $this->password, 
                          $this->databasename,
                          $this->port
                       );
      $this->throwExceptionOnError($this->connection);
   }
   /**
    * Returns all the rows from the table.
    *
    * Add authroization or any logical checks for secure access to your data 
    *
    * @return array
    */
   public function getAllKiosks() {
      $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename");      
      $this->throwExceptionOnError();
      mysqli_stmt_execute($stmt);
      $this->throwExceptionOnError();
      $rows = array();
      mysqli_stmt_bind_result($stmt, $row->KioskID, $row->Station, $row->Branch, $row->Chain, $row->Pingdate, $row->Layout, $row->Online, $row->Clips, $row->Extra);
       while (mysqli_stmt_fetch($stmt)) {
         $row->Pingdate = new DateTime($row->Pingdate);
         $rows[] = $row;
         $row = new stdClass();
         mysqli_stmt_bind_result($stmt, $row->KioskID, $row->Station, $row->Branch, $row->Chain, $row->Pingdate, $row->Layout, $row->Online, $row->Clips, $row->Extra);
       }
      mysqli_stmt_free_result($stmt);
       mysqli_close($this->connection);
       return $rows;
   }
   /**
    * Returns the item corresponding to the value specified for the primary key.
    *
    * Add authorization or any logical checks for secure access to your data 
    *
    * 
    * @return stdClass
    */
   public function getKiosksByID($itemID) {
      $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename where KioskID=?");
      $this->throwExceptionOnError();
      mysqli_stmt_bind_param($stmt, 'i', $itemID);      
      $this->throwExceptionOnError();
      mysqli_stmt_execute($stmt);
      $this->throwExceptionOnError();
      mysqli_stmt_bind_result($stmt, $row->KioskID, $row->Station, $row->Branch, $row->Chain, $row->Pingdate, $row->Layout, $row->Online, $row->Clips, $row->Extra);
      if(mysqli_stmt_fetch($stmt)) {
         $row->Pingdate = new DateTime($row->Pingdate);
         return $row;
      } else {
         return null;
      }
   }
   /**
    * Returns the item corresponding to the value specified for the primary key.
    *
    * Add authorization or any logical checks for secure access to your data 
    *
    * 
    * @return stdClass
    */
   public function createKiosks($item) {
      $stmt = mysqli_prepare($this->connection, "INSERT INTO $this->tablename (Station, Branch, Chain, Pingdate, Layout, Online, Clips, Extra) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
      $this->throwExceptionOnError();
      mysqli_stmt_bind_param($stmt, 'sssssisi', $item->Station, $item->Branch, $item->Chain, $item->Pingdate->toString('YYYY-MM-dd HH:mm:ss'), $item->Layout, $item->Online, $item->Clips, $item->Extra);
      $this->throwExceptionOnError();
      mysqli_stmt_execute($stmt);      
      $this->throwExceptionOnError();
      $autoid = mysqli_stmt_insert_id($stmt);
      mysqli_stmt_free_result($stmt);      
      mysqli_close($this->connection);
      return $autoid;
   }
   /**
    * Updates the passed item in the table.
    *
    * Add authorization or any logical checks for secure access to your data 
    *
    * @param stdClass $item
    * @return void
    */
   public function updateKiosks($item) {
      $stmt = mysqli_prepare($this->connection, "UPDATE $this->tablename SET Station=?, Branch=?, Chain=?, Pingdate=?, Layout=?, Online=?, Clips=?, Extra=? WHERE KioskID=?");      
      $this->throwExceptionOnError();
      mysqli_stmt_bind_param($stmt, 'sssssisii', $item->Station, $item->Branch, $item->Chain, $item->Pingdate->toString('YYYY-MM-dd HH:mm:ss'), $item->Layout, $item->Online, $item->Clips, $item->Extra, $item->KioskID);      
      $this->throwExceptionOnError();
      mysqli_stmt_execute($stmt);      
      $this->throwExceptionOnError();
      mysqli_stmt_free_result($stmt);      
      mysqli_close($this->connection);
   }
   /**
    * Deletes the item corresponding to the passed primary key value from 
    * the table.
    *
    * Add authorization or any logical checks for secure access to your data 
    *
    * 
    * @return void
    */
   public function deleteKiosks($itemID) {
      $stmt = mysqli_prepare($this->connection, "DELETE FROM $this->tablename WHERE KioskID = ?");
      $this->throwExceptionOnError();
      mysqli_stmt_bind_param($stmt, 'i', $itemID);
      mysqli_stmt_execute($stmt);
      $this->throwExceptionOnError();
      mysqli_stmt_free_result($stmt);      
      mysqli_close($this->connection);
   }

   /**
    * Returns the number of rows in the table.
    *
    * Add authorization or any logical checks for secure access to your data 
    *
    * 
    */
   public function count() {
      $stmt = mysqli_prepare($this->connection, "SELECT COUNT(*) AS COUNT FROM $this->tablename");
      $this->throwExceptionOnError();
      mysqli_stmt_execute($stmt);
      $this->throwExceptionOnError();
      mysqli_stmt_bind_result($stmt, $rec_count);
      $this->throwExceptionOnError();
      mysqli_stmt_fetch($stmt);
      $this->throwExceptionOnError();
      mysqli_stmt_free_result($stmt);
      mysqli_close($this->connection);
      return $rec_count;
   }

   /**
    * Returns $numItems rows starting from the $startIndex row from the 
    * table.
    *
    * Add authorization or any logical checks for secure access to your data 
    *
    * 
    * 
    * @return array
    */
   public function getKiosks_paged($startIndex, $numItems) {
      $stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename LIMIT ?, ?");
      $this->throwExceptionOnError();
      mysqli_stmt_bind_param($stmt, 'ii', $startIndex, $numItems);
      mysqli_stmt_execute($stmt);
      $this->throwExceptionOnError();
      $rows = array();
      mysqli_stmt_bind_result($stmt, $row->KioskID, $row->Station, $row->Branch, $row->Chain, $row->Pingdate, $row->Layout, $row->Online, $row->Clips, $row->Extra);
       while (mysqli_stmt_fetch($stmt)) {
         $row->Pingdate = new DateTime($row->Pingdate);
         $rows[] = $row;
         $row = new stdClass();
         mysqli_stmt_bind_result($stmt, $row->KioskID, $row->Station, $row->Branch, $row->Chain, $row->Pingdate, $row->Layout, $row->Online, $row->Clips, $row->Extra);
       }
      mysqli_stmt_free_result($stmt);      
      mysqli_close($this->connection);
      return $rows;
   }

   /**
    * Utility function to throw an exception if an error occurs 
    * while running a mysql command.
    */
   private function throwExceptionOnError($link = null) {
      if($link == null) {
         $link = $this->connection;
      }
      if(mysqli_error($link)) {
         $msg = mysqli_errno($link) . ": " . mysqli_error($link);
         throw new Exception('MySQL Error - '. $msg);
      }      
   }
}
?>

虽然Zend框架的性能可能有点问题,但在您的示例中没有Zend框架代码

这个系统打开了6个php-cgi进程

对于每个操作?这似乎不太可能。如果您提供一个访问日志的示例,显示一个典型的事务,以及他们提供的支持此断言的证据,将会很有帮助。

通过cgi运行php是一个非常糟糕的主意如果你在一点点关心性能(或者你的服务器机房有多热)。使用mod_php或php-fpm,甚至php通过fcgi与操作码缓存将减少执行时间超过75%。

查看代码,这里没有明显的错误——除了getkiosks_page——在没有显式ORDER BY的情况下进行行范围选择是非常草率的。

每个创建/读取/更新/删除操作都可以工作,但我认为它应该快得多

它有多快?请求在web服务器上的时间有多长,它执行了哪些查询?要花多长时间?数据库的结构是什么?查询的解释计划是什么样的?

我不能评论Zend框架,因为我从未使用过它。

CGI总是比快速CGI慢,更好的是,mod_php或类似的东西。当你使用CGI时,每次解释器启动和脚本完成后,所有的东西都被删除。

当你使用快速CGI或PHP模块时,web服务器模块可以维护一些状态,比如数据库连接,跨调用。

相关内容

  • 没有找到相关文章

最新更新