转自:http://www.oracle.com/technetwork/cn/testcontent/vaswani-zend-154971-zhs.html
开发人员:PHP
作者:Vikram Vaswani
建立 Oracle/PHP/Apache/Linux (OPAL) 开发和部署环境的快速方法
2010 年 6 月 更新
过去几年间,PHP 凭借其友好的许可条款和在构建强健且安全的应用程序时的易用性,在企业中越来越受欢迎。它越来越多地与大型企业选择的数据库系统 — Oracle Database 结合使用。
这是一个良好的局面,只是存在一个问题:建立 Oracle/PHP/Apache/Linux (OPAL) 开发环境通常是一个手动过程,不适合于习惯了自动、简单的企业 IT 环境。虽然提供了针对一些平台的在线参考材料,如 PHP Oracle 秘笈、Oracle 的 PHP 常见问题解答 Wiki 以及各种“入门”级指南,但是这个过程仍然不像单击一系列按钮并让自动化的安装程序完成繁重的任务那样简单。
在这种环境下快速配置 PHP 环境的一个最简便的方法是使用 Zend Server,这是一个既可在 Windows 上又可在 Linux 上运行的 PHP 系统,您可随取随用地使用该系统构建基于 Oracle 的应用程序。Zend Server 提供的高性能、企业就绪 OPAL 解决方案使企业 IT 部门能够轻而易举地将 PHP 中间件添加到其现有安装中。
Zend Server 是一个现成的 PHP 解决方案,可以简化 Windows 和 Linux 环境中 PHP 应用程序的开发和运行。它包括一个经过全面测试的 PHP 最新版本、对众多数据库系统的支持(包括通过 Oracle Instant Client 库对 Oracle 的支持),以及许多用于改善 PHP 性能和诊断的专用于 Zend 的附加软件。
Zend Server 目前有两个可用版本。如果您在 PHP 方面有一定的经验并且愿意手动维护服务器和管理更新,可以选择 Zend Server 的“社区”版,称为 Zend Server CE。该版本适用于“非关键”应用程序并且针对 Windows、Linux 和 Mac OS X 免费提供;但是,它不包含“商业”版所包括的页面缓存、代码跟踪、脱机作业排队、自动更新和诊断特性。如果这些特性对您比较重要(如果您使用的服务器要为关键业务 PHP 应用程序提供服务,这些特性应该比较重要),那么您应考虑购买 Zend Server 的商业版,这样您将有权使用以上全部特性并能得到 Zend 提供的技术支持。在购买之前,您也可以通过 Zend Server 的一个 30 天试用许可密钥进行试用,这需要进行注册。
下面我们简要介绍一下 Zend Server 的主要特性(除非专门指明,这些特性在两个版本中均提供):
在本文中,我将假设您已安装并使用某一版本的 Oracle。如果未安装,您可以从 Oracle 网站下载适合于您开发系统的 Oracle 版本。本文中的示例均使用 Oracle Database 11 g 第 1 版 (11.1.0.6.0) 开发;但是,与 Zend Server 捆绑提供的 PHP 扩展也可与其他版本的 Oracle(包括 Oracle 的免费的 Oracle Database 10 g 快捷版)结合使用。
如果是在 Linux 上运行 Oracle,则很可能您当前使用的是 Oracle Enterprise Linux 或 Red Hat Enterprise Linux。在 Oracle Enterprise Linux 上安装 Zend Server 时,建议您使用 up2date
和 yum
进行基于 RPM 的安装。如果您订阅了 Unbreakable Linux Network (ULN),可通过订阅“Enterprise Linux 5 Add ons (i386)”或“Enterprise Linux 5 Add ons (x86_64)”频道并用 up2date
安装 zend-server-repo RPM 来安装 Zend Server。
shell> up2date zend-server-repo shell> yum install zend-server-php-5.3
您也可以手动进行这一工作:以 root 用户身份登录,向 yum 指示 Zend 信息库。在 /etc/yum.repos.d/zend.repo
下创建一个新文件并在其中添加以下内容:
[Zend] name=Zend Server baseurl=http://repos.zend.com/zend-server/rpm/$basearch enabled=1 gpgcheck=0 [Zend_noarch] name=Zend Server - noarch baseurl=http://repos.zend.com/zend-server/rpm/noarch enabled=1 gpgcheck=0
该文件创建后,使用一个命令即可安装 Zend Server(及其相关项),如下所示:
shell> yum install zend-server-php-5.3
以下是 yum 运行时的屏幕截图:
如果您使用的是其他基于 Debian 的 Linux 发布版本(如 Ubuntu),则您还可以使用 aptitude
等程序包管理程序安装 Zend Server。Zend Server 手册对此提供了详细说明。简而言之,该过程需要您先将以下代码行添加到系统的主信息库列表(位于 /etc/apt/sources.list
)中:
deb http://repos.zend.com/zend-server/deb server non-free
同时,取消“universe”信息库的行注释,以便 aptitude 可以找到并下载必要的相关项,例如:
deb http://archive.ubuntu.com/ubuntu intrepid universe
然后,将 Zend 的公共密钥添加到系统的信息库数据库中:
shell> wget http://repos.zend.com/deb/zend.key shell> apt-key add zend.key
最后,使用 aptitude 下载并安装 Zend Server 以及所有必要的相关项:
shell> aptitude update shell> aptitude install zend-server-php-5.3
无论您使用哪种方法,Zend Server 都将安装到 /usr/local/zend/
中,并且安装程序将自动启动它。
安装完 Zend Server 后,您可以使用喜爱的 Web 浏览器通过 URL http://localhost:10081/ZendServer 对其进行访问。您首次尝试访问它时,它将提示您输入管理员口令和您的许可密钥,如下所示:
输入所需信息,您将进入服务器管理控制台,该控制台为主服务器管理区域提供了一个选项卡式的界面,如下所示:
以下是您可以通过这个基于 Web 的控制台进行的操作的简要列表:
获取服务器信息: 可通过 Monitor -> PHP Info
页面获取关于当前 PHP 版本的详细信息,该页面将显示 phpinfo()
命令的全部输出。
同样,您还可通过 Monitor -> Logs
页面获取各种重要日志文件的不断刷新的视图,通过 Monitor -> Server Info
页面获取 Zend Server 各个已安装组件的概要信息,其中包括版本信息和主要文件路径。
激活或停用服务器扩展:在 Zend Server 中可以通过 Server Setup -> Extensions
页面轻松地将对新技术的支持添加到您的 PHP 版本中,该页面提供了用于打开/关闭 PHP 扩展的复选框式界面。
Server Setup -> Components
页面中有一个类似的界面用于激活或停用 Zend 自己的性能和诊断工具,例如 Zend Optimizer+ 或 Zend Monitor。(可使用 Server Setup -> Debugger
页面配置外部调试器)。
修改 PHP 配置文件: 通常,修改 PHP 配置是一件很麻烦的事,需要您确定要更改的 PHP 配置变量,然后手动编辑 php.ini 配置文件进行更改。Zend Server 极大地简化了这一工作,您可通过一个 Web 表单( Server Setup -> Directives
)来编辑 PHP 配置变量。该表单界面还包含每个配置变量的摘录信息,从而可以更加轻松、快速地了解各配置项的位置。Zend Server Web 界面还包括一个重新启动 PHP 的控件,这样您可以很容易地即时查看配置更改的结果。
设置页面缓存: 基于 URL 的页面缓存是 Zend Server 中最重要的性能工具之一(Zend Server CE 中不提供此特性)。可通过 Rule Management -> Caching
页面访问该特性。利用该特性,服务器管理员可以(基于正则表达式)设置 URL 匹配规则,并使服务器自动缓存这些 URL 的输出,这样以后对相同 URL 的访问请求就可以由该缓存提供服务了。在本文稍后,您将看到该特性可将性能提高几个数量级。
监视 PHP 警报和异常:Zend Server 的另一个重要特性是能够收集 PHP 警报和异常并在一个集中位置显示它们: Monitor -> Events
页面。该特性在典型企业环境中有独特的优势,因为它可以将令人担心的服务器事件(例如,内存过度使用)立即通知我们,从而使我们可以采取纠正性措施。管理员还可以使用 Rule Management -> Monitoring
页面为事件监视器设置自定义“监视规则”。(Zend Server CE 中不提供该事件监视特性)。
调试和回溯跟踪代码错误: 对程序错误进行回溯分析的过程艰难而费时,尤其是在处理深长或复杂的对象层次结构时。以前,进行错误调试的唯一有效方法是使用堆栈跟踪,或者通过在程序代码中不同位置手动设置调试语句。Zend Server 5.0 通过 代码跟踪 特性极大简化了这一过程,这个新特性为开发人员提供了一种完善的 URL 请求回溯跟踪功能(Zend Server CE 中不提供该特性)。代码跟踪既可用于手动工作流又可用于自动(事件监视)工作流,它通常为我们提供有关请求执行的总体视图,包括调用的函数,其输入参数和返回值、内存使用情况和执行时间。如果存在错误,则会标记出它们以便查阅,同时会记下行号和文件号、错误消息和错误代码。可通过 Monitor -> Code Tracing
页面访问代码跟踪报告,并且可通过 Rule Management -> Monitoring
页面设置监视规则。本文稍后将举例说明。
建立和管理重复执行的作业: Zend Server 5.0 另一个重要的新特性是能够建立作业队列,这类似于 cron 表(Zend Server CE 中不提供此特性)。利用此特性,管理员可定义让服务器自动执行的重复的任务,并提供一个界面以便我们查看作业状态和失败的作业。可通过 Rule Management -> Recurring Jobs
页面定义作业,可通过 Monitor -> Jobs
和 Monitor -> Queue Statistics
视图查看作业状态。
更改服务器管理口令: Administration 页面提供了一个简单的界面,您可通过该界面为 Zend Server 设置一个新的管理口令并更新许可详细信息。
您还可通过该页面更新 Zend Server 自身。
之前已经提到,Zend Server 附带对 Oracle 数据库的内置支持。这意味着安装该服务器后,您可以立即开始用 PHP 编写 Oracle 数据库支持的应用程序。让我们来看看实际的例子,用一些示例数据填充一个 Oracle 数据库表,然后使用 Oracle 调用接口和 PHP 的 oci8 扩展编写一个 PHP 脚本以检索该数据并将其显示为 Web 页面。
首先,以系统管理员身份登录到 Oracle 数据库,然后新建一个用户帐户:
shell> sqlplus / as sysdba SQL*Plus: Release 11.1.0.6.0 - Production on Tue Apr 6 07:29:18 2010 Copyright (c) 1982, 2007, Oracle. All rights reserved. Connected to: Oracle Database 11g Release 11.1.0.6.0 - Production SQL> CREATE USER john IDENTIFIED BY doe; User created. SQL> GRANT ALL PRIVILEGES TO john; Grant succeeded.
接着,以该用户身份进行连接并创建一个新表:
shell> sqlplus SQL*Plus: Release 11.1.0.6.0 - Production on Tue Apr 6 07:29:18 2010 Copyright (c) 1982, 2007, Oracle. All rights reserved. Enter user-name: john Enter password: *** Connected to: Oracle Database 11g Release 11.1.0.6.0 - Production SQL> CREATE TABLE CITIES ( 2 CITY_ID NUMBER NOT NULL, 3 CITY_NAME VARCHAR2(50) 4 ); Table created. SQL> INSERT ALL 2 INTO CITIES (CITY_ID, CITY_NAME) VALUES (1, 'Mumbai') 3 INTO CITIES (CITY_ID, CITY_NAME) VALUES (2, 'London') 4 INTO CITIES (CITY_ID, CITY_NAME) VALUES (3, 'Paris') 5 INTO CITIES (CITY_ID, CITY_NAME) VALUES (4, 'Rome') 6 SELECT * FROM dual; 4 rows created. SQL> COMMIT; Commit complete.
用一个快速 SELECT 确认已成功插入记录:
SQL> SELECT * FROM CITIES; CITY_ID CITY_NAME ---------- -------------------------------------------------- 1 Mumbai 2 London 3 Paris 4 Rome
现在,使用 PHP 完成相同的工作,创建一个新的 PHP 脚本 (oci.php) 并在其中添加以下代码。应将此脚本保存到 Web 服务器的文档根目录下,该目录在 Ubuntu 和 Debian 发布版上通常为 /var/www
,在其他发布版本上通常为 /var/www/html
:
<html> <head> <style type="text/css"> table { border-collapse: collapse; } td { border: solid 1px black; padding: 3px; } </style> </head> <body> <h2>Cities</h2> <?php // open database connection $db = oci_connect('john', 'doe', '//achilles/orcl'); if (!$db) { die('Unable to connect to database'); } // formulate and parse query $sql = 'SELECT * FROM CITIES'; $stmt = oci_parse($db, $sql); // execute query $rslt = oci_execute($stmt); // iterate over result set $count = 0; echo '<table>'; while ($row = oci_fetch_object($stmt)) { echo '<tr>'; echo '<td>' . $row->CITY_ID . '</td>'; echo '<td>' . $row->CITY_NAME . '</td>'; echo '</tr>'; $count++; } echo '</table><br/>'; echo $count . ' record(s) found.'; // close connection oci_free_statement($stmt); oci_close($conn); ?> </body> </html>
该脚本首先使用 oci_connect()
函数(服务器主机名称为“achilles”,数据库服务为“orcl”)和用户凭证打开一个到数据库服务器的连接。然后,用 oci_parse()
函数准备一个查询,该函数返回一个语句对象;然后,通过 oci_execute()
函数使用该语句对象执行对数据库服务器的查询。
将使用循环遍历结果集,通过 oci_fetch_object()
将各条记录作为对象返回。现在可以用对象属性访问每条记录的各个字段;接下来就是相当容易的了,我们用一个 HTML 表呈现这些字段值。当结果集中的所有记录都得到处理后,使用 oci_close()
关闭连接。
通过 Web 浏览器访问该脚本时,您应该看到类似下图的 Web 页面:
Oracle Database 11 g 包含一个专门针对需要高可伸缩性的应用程序的新特性:数据库驻留连接池 (DRCP)。有了 DRCP,就可以在不同的应用程序进程之间共享数据库连接,从而可以更高效地使用服务器资源并全面提高性能。Zend Server 随附的 PHP OCI8 扩展(目前为 V1.4.1)包含对 DRCP 的即用支持,使开发人员可以在其 PHP 应用程序中直接使用该特性。有关 PHP 和 DRCP 的更多详情,请参考 Oracle 的 PHP DRCP 白皮书,其中包括一个说明连接池的优点的基准测试结果。
要启用 DRCP,登录到数据库服务器并启动连接池:
shell> sqlplus / as sysdba SQL*Plus: Release 11.1.0.6.0 - Production on Tue Apr 6 14:24:13 2010 Copyright (c) 1982, 2007, Oracle. All rights reserved. Connected to: Oracle Database 11g Release 11.1.0.6.0 - Production SQL> execute dbms_connection_pool.start_pool(); PL/SQL procedure successfully completed.
通过查询特定的 DBA_CPOOL_INFO 视图确认该池已启动:
SQL> SELECT CONNECTION_POOL, STATUS, MAXSIZE 2 FROM DBA_CPOOL_INFO; CONNECTION_POOL STATUS MAXSIZE ---------------------------------------------------------- SYS_DEFAULT_CONNECTION_POOL ACTIVE 40
然后,在 Zend Server 管理控制台的 Server Setup -> Directives
页面,找到 OCI8 部分并在 oci8.connection_class 变量中设置 PHP 应用程序所使用的 DRCP 连接类的名称。这个用户选择的名称允许不同应用程序的池化服务器间的逻辑划分:
最后,通过在您的 oci_connect()
连接字符串中添加关键字 POOLED 使您的 PHP 应用程序能够使用 DRCP。虽然不是必需的,但建议您用 oci_pconnect()
函数替换 oci_connect()
函数。下面是上文中的例子,只是将其修改为了使用 DRCP (drcp.php):
<html> <head> <style type="text/css"> table { border-collapse: collapse; } td { border: solid 1px black; padding: 3px; } </style> </head> <body> <h2>Cities</h2> <?php // open database connection $db = oci_pconnect('john', 'doe', '//achilles/orcl:POOLED'); if (!$db) { die('Unable to connect to database'); } // formulate and parse query $sql = 'SELECT * FROM CITIES'; $stmt = oci_parse($db, $sql); // execute query $rslt = oci_execute($stmt); // iterate over result set $count = 0; echo '<table>'; while ($row = oci_fetch_object($stmt)) { echo '<tr>'; echo '<td>' . $row->CITY_ID . '</td>'; echo '<td>' . $row->CITY_NAME . '</td>'; echo '</tr>'; $count++; } echo '</table><br/>'; echo $count . ' record(s) found.'; // close connection oci_free_statement($stmt); oci_close($conn); ?> </body> </html>
需要注意的是,该脚本中唯一改动之处是连接调用,此外不需要进行其他更改。您还可以通过 $ORACLE_HOME/network/admin/tnsnames.ora
文件指定服务器连接要经过池化处理,如以下示例所示:
ORCL = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = achilles)(PORT = 1521)) (CONNECT_DATA = (SERVER = POOLED) (SERVICE_NAME = orcl) ) )
这种情况下,您的 PHP 连接调用将如下所示:
<?php // open database connection $db = oci_pconnect('john', 'doe', 'ORCL'); ?>
Zend Page Cache 是 Zend Server 中内置的最重要的性能改进特性之一,提供基于 URL 的 HTML 输出缓存。该特性最适用于使用 PHP 代码动态生成 HTML 页面的应用程序,因为从 Zend Page Cache 检索缓存输出明显快于让 PHP 针对每个新请求动态重新生成相同页面。
Zend Page Cache 可通过 Zend Server 管理控制台启用,并使用正则表达式匹配和识别要缓存的 URL。该特性完全基于服务器;启用时无需对应用程序代码进行更改。
为说明其工作原理,我们对一个使用 Zend Server 构建的流行的开源应用程序进行基准性能测试:phpBB3 是一个可以与包括 Oracle 在内的多种数据库系统结合使用、基于 PHP 的成熟公告板。phpBB3 可以从其官方网站免费下载,其附带的自动安装程序使您可以轻松安装和运行。以下讨论假设您已经安装并配置了 phpBB3;关于如何完成此工作的详细说明,请参见 phpBB3 快速入门指南。
假设您已经完成所有设置,登录到 phpBB3 Administration Control Panel。
现在,创建一个新论坛 ( Forums -> Manage Forums
)。不要忘记从默认(示例)论坛复制论坛权限,以便新的论坛可以在主板索引页中显示。
重复此过程,直至拥有 3 至 4 个新论坛。
现在,当您访问主板索引页面时,应该会看到新添加的论坛。
该索引页面由 PHP 动态生成,PHP 查询 Oracle 数据库服务器、检索论坛列表并将每次请求的结果设置为 HTML 格式。记录下该页面的 URL,稍后您将用到它。
下一个步骤是使用 ApacheBench 监视工具定量分析 Zend Page Cache 的优势。首先,访问 Zend Server 管理控制台的 Server Setup -> Components
页面,关闭 Zend Page Cache 和 Zend Optimizer+。不要忘记重新启动 Zend Server 以使更改生效。
然后,使用 ApacheBench 生成有关服务器响应时间的基准测试结果,做法是使用之前步骤中的 URL 针对论坛索引页同时发送多个请求。以下是 500 个请求(一次发送 10 个请求)的输出:
shell> ab -n 500 -c 10 http://192.168.1.3/phpBB3/index.php This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.1.3 (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Finished 500 requests Server Software: Apache/2.2.11 Server Hostname: 192.168.1.3 Server Port: 80 Document Path: /phpBB3/index.php Document Length: 11599 bytes Concurrency Level: 10 Time taken for tests: 49.903 seconds Complete requests: 500 Failed requests: 0 Write errors: 0 Total transferred: 6152000 bytes HTML transferred: 5799500 bytes Requests per second: 10.02 [#/sec] (mean) Time per request: 998.058 [ms] (mean) Time per request: 99.806 [ms] (mean, across all concurrent requests) Transfer rate: 120.39 [Kbytes/sec] received
现在,返回 Zend Server 管理控制台的 Server Setup -> Components
页面,打开 Zend Page Cache。针对论坛索引页面 URL 设置一个新缓存规则,如下所示:
将显示保存的规则。
重新启动 PHP 以使更改生效,然后尝试使用与之前相同的参数再次运行 ApacheBench:
shell> ab -n 500 -c 10 http://192.168.1.3/phpBB3/index.php This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.1.3 (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Finished 500 requests Server Software: Apache/2.2.11 Server Hostname: 192.168.1.3 Server Port: 80 Document Path: /phpBB3/index.php Document Length: 11606 bytes Concurrency Level: 10 Time taken for tests: 0.253 seconds Complete requests: 500 Failed requests: 0 Write errors: 0 Total transferred: 6002916 bytes HTML transferred: 5826212 bytes Requests per second: 1974.79 [#/sec] (mean) Time per request: 5.064 [ms] (mean) Time per request: 0.506 [ms] (mean, across all concurrent requests) Transfer rate: 23153.27 [Kbytes/sec] received
将本次运行输出与之前输出进行比较,您将看到使用 Zend Page Cache 使每个请求的时间从 998 毫秒降至 5 毫秒!该服务器每秒能够处理更多的请求,从 10 个提高到 1974个。
现在,返回 Zend Server 管理控制台的 Server Setup -> Components
页面,打开 Zend Optimizer+。然后,重新启动 PHP 并再次运行 ApacheBench:
shell> ab -n 500 -c 10 http://192.168.1.3/phpBB3/index.php This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.1.3 (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Finished 500 requests Server Software: Apache/2.2.11 Server Hostname: 192.168.1.3 Server Port: 80 Document Path: /phpBB3/index.php Document Length: 11606 bytes Concurrency Level: 10 Time taken for tests: 0.158 seconds Complete requests: 500 Failed requests: 0 Write errors: 0 Total transferred: 6002916 bytes HTML transferred: 5826212 bytes Requests per second: 3171.82 [#/sec] (mean) Time per request: 3.153 [ms] (mean) Time per request: 0.315 [ms] (mean, across all concurrent requests) Transfer rate: 37187.88 [Kbytes/sec] received
应该可以很明显地看到 Zend Optimizer+ 进一步提升了性能,将每个请求的平均时间减至 3 毫秒,服务器现在每秒可以处理 3171 个事务。与首次运行相比,您将发现只需打开这两个组件(无需额外的调优或代码优化)即可显著提升性能。
Zend Server 5.0 包括一个强大的新的代码跟踪系统,开发人员可以通过该系统查看特定请求的完整详细的历史记录。这包括脚本调用的所有函数和方法的列表,同时包括其输入参数、返回值和内存使用情况。数据分层次显示,从而易于执行细粒度的代码分析,易于准确追溯到引发错误的代码行。
默认情况下,Zend Server 的代码跟踪处于启用状态。要查看其实际运行情况,请访问 Monitor -> Code Tracing
页面并输入一个请求 URL。然后,Zend Server 将请求指定的 URL,生成一个有关整个请求的跟踪文件。下面是跟踪输出的一个例子:
请注意,如果存在错误,Zend Server 会在跟踪输出中自动标记出来,从而便于调试错误。
跟踪输出还包括所请求脚本的统计信息,它会指明特定函数或方法的调用次数,并提供有关执行时间和内存使用的信息。
如上述示例所示,Zend Server 是一个稳定安全的 PHP 系统,可立即与 Oracle Database 结合使用,使用户能够在企业环境中轻松开发和部署 Oracle+PHP 应用程序。该程序包提供强大灵活的缓存引擎、基于浏览器的管理控制台以及对 Oracle Database 11 g 新技术(例如,数据库驻留连接池)的内置支持,所有这些使其成为需要使用基于 Oracle 的基础架构部署 PHP 应用服务器的所有用户的理想选择。