使用funkload运行和自动化分布式负载测试的工具

benchmaster的Python项目详细描述


板凳大师3000

这个包的目的是帮助您运行大型的并行负载测试 在多个服务器和/或处理器上使用funkload。如果你需要 只有适度的重载测试,使用 自行下载。

本文档可能仍然提供一些有用的提示和见解,即使您 最终使用"普通"funkload,但请阅读funkload文档 好。它是一个非常强大和灵活的工具。你当然需要 熟悉它的各种脚本和服务,以充分发挥其作用 师父,

目录

  • 板凳大师3000
    • 操作理论
    • 先决条件
    • 安装
    • 录制测试
    • 执行测试
    • 观察执行
    • 查看报告
    • 服务器监控
  • 手动生成报告
  • 差异报告
  • 学分
  • 更改日志
  • 操作理论

    台式机主设备将负载测试部署到多个服务器 (或单个服务器的多个别名,从而允许更好地使用 多核或多处理器系统),每个系统都有自己的负载测试运行程序。 当所有的负荷测试跑步者都完成了他们的基准测试,结果是 整理后返回主报表,主报表将生成合并报表。

    只有一个"基准主节点"和一个或多个"基准节点"。主人 通过ssh与节点通信,使用pssh库并行 操作。节点可以是不同的物理机器,尽管它是 可以多次使用同一台机器(在这种情况下,可以多次使用 将建立并发ssh连接)。同样也有可能 机器-甚至与台式主机相同的安装-用作主机和 一个或多个节点。(在这种情况下,船长实际上将设立一个或 到 本地主机的更多ssh连接

    负载测试通常使用funkload创建/记录。这将导致 两个文件,必须保存在同一目录中:

    • <;testname>;.conf ,用于配置负载测试运行程序, Funkload监控服务器等。
    • 测试<;testname>;.py ,它包含实际测试作为 FunkloadTestCase ,带有一个测试方法 test\lt;testname>;

    使用bench master时有一个扩展:您可以获取节点 数字(大于或等于0的整数,在配置中表示为 字符串)通过执行:

    node_num = self.conf_get('bench', 'node_num', '0')
    

    这对于消除节点的歧义很有用:因为所有节点都执行 并行测试运行时,您需要注意两个测试不会声明 同时指向同一资源(例如,登录名)。

    请注意,尽管可以把Funkload测试放在一个包里,Funkload 只考虑模块。放弃你的测试是完全可行的 和.conf文件配对到任何目录,即使没有 .py初始化

    先决条件

    首先,一些要求:

    • bench master只在unix类型的操作系统上工作。

    • 您至少需要安装Funkload 0.12和PSSH 2.1.1。这些会得到 作为 基准测试程序包的依赖项安装。

    • 您必须已将 ssh scp 安装在试验台主机上

    • 您还必须将 gnuplot 生成报告。通常最好使用 操作系统的包管理器。

    • 所有bench节点都必须运行ssh守护进程,接受来自 长凳大师。

      < Buff行情>

      提示: 工作台节点上的ssh守护进程可能接受 入站连接数。如果使用许多"虚拟"节点,则 需要注意的是,后面的连接不会被拒绝。 如果您使用的是openssh,那么应该设置 maxstartups sshd_config文件中的maxsessions 选项足够高 数量:

    • bench master必须能够在不输入密码的情况下通过ssh连接到节点 或者被提示接受远程主机的签名。实际上, 意味着板凳主控运行的用户必须具有其公钥 在远程工作台上用户的 授权密钥文件中列出 节点,并且每个远程节点的签名必须记录在 已知的文件存放在台架主机上。

    • 所有工作台节点的设置应相同。尤其是安装 工作台节点运行程序的工作目录应该在同一目录中 所有主机上的路径。

    可选地,您还可以将工作台节点上的ssh守护程序配置为 接受由板凳主控发送的各种环境变量。 这些不是正常操作所必需的,但可以用于书写 以及调试负载测试。变量为:

    < dl >
    pssh_nodenum
    节点的编号。第一个节点的编号为0。
    pssh_台架运行
    当前工作台运行的名称。您可以在调用 板凳师傅。它默认为基于当前日期的唯一命名 时间和测试名称。
    pssh_bench_working_dir工作目录
    顶层工作台节点工作目录。

    要使用这些,您需要将以下内容添加到 每个节点:

    AcceptEnv PSSH_*
    

    安装

    可以使用 zc.buildout easy_install 。它将安装两个控制台脚本, bench master 和 工作台节点,控制其执行。

    这里有一个 buildout.cfg 文件,它将创建一个独立的环境 可以用作工作台主控和/或节点:

    [buildout]
    parts = bench-tools
    versions = versions
    
    # Note: Change versions as required or remove versions block to get
    # latest versions always
    
    [versions]
    benchmaster = 1.0b1
    funkload = 1.12.0
    pssh = 2.1.1
    
    [bench-tools]
    recipe = zc.recipe.egg
    eggs =
        funkload
        benchmaster
    

    注意: 最好按上面所示"固定"版本。然而,你 应该在你阅读时检查哪些版本是合适的。 或者,您可以完全跳过 [版本] 块来获取 所有东西的最新版本,但请记住这可能会导致 如果某个依赖项的不兼容版本是 发布给PYPI。

    为了简单起见,建议您创建相同的安装 在工作台运行中涉及的所有服务器上。例如,您可以将 buildout.cfg 上面的文件在 /opt/bench 中,然后运行:

    $ buildout bootstrap --distribute # or download a bootstrap.py and run that
    $ bin/buildout
    

    提示: 您应该确保工作台节点装置归 一个合适的用户-通常是板凳师傅用来记录的用户 通过ssh远程进入。

    现在,您应该拥有脚本 工作台主节点 工作台节点 和 在 bin 目录中的funkload中有各种 fl-* 脚本。

    如果您喜欢使用 pip easy_install ,您可以只安装 基准测试程序。建议您在a virtualenv中执行此操作,但是:

    $ virtualenv --no-site-package bench
    $ cd bench
    $ bin/easy_install benchmaster
    

    录制测试

    要记录测试,可以使用安装了 负荷。要使用它,还需要安装tcpwatch。tcpwatch 二进制文件需要在系统路径中,以便能够找到fl记录。 或者,可以将 tcpwatch 环境变量设置为指向 二进制文件本身。

    例如,您可以使用这样的构建:

    [buildout]
    parts = bench-tools
    versions = versions
    
    # Note: Change versions as required or remove versions block to get
    # latest versions always
    
    [versions]
    benchmaster = 1.0b1
    funkload = 1.12.0
    pssh = 2.1.1
    tcpwatch = 1.3.1
    
    [bench-tools]
    recipe = zc.recipe.egg:scripts
    eggs =
        docutils
        funkload
        tcpwatch
        benchmaster
    initialization =
        import os
        os.environ['TCPWATCH'] = "${buildout:bin-directory}/tcpwatch"
    

    安装tcpWatch后,您可以使用以下命令启动录音机:

    $ bin/fl-record TestName
    

    注意: 您应该使用"camelcase"作为测试名称。这确保了 生成的代码遵循 工作台主控器所期望的约定 程序。如果使用其他命名约定,则可能必须指定 测试名称作为 bench master命令的可选命令行参数 -见下文。

    现在打开一个web浏览器,并将其配置为使用http代理 127.0.0.1 端口 8090 (有关详细信息,请参阅fl记录输出和文档)。

    此时,您可以访问要测试的网站并执行 要加载测试的操作。它有助于提前计划你的步骤,因为 "杂散"的点击或重新加载会使测试的重复性或实用性降低。

    完成后,返回运行fl record的终端并按 ctrl+c 。它应该生成两个文件: test_testname.py testname.conf

    您可能需要将这些文件移出当前目录,例如:

    $ mkdir bench-tests
    $ mv test_* bench-tests/
    $ mv *.conf bench-tests/
    

    此时,您应该编辑生成的两个文件,以确保它们将 作为负载测试是有效和有用的。conf文件包含注释,其中 您可能需要填写详细信息,例如更具描述性的名称。

    您还需要考虑如果您的测试用例被运行并且 并行地从多个工作台节点。如果只是取几个 页面,你可能会对记录的测试感到满意。但是,如果你是 执行任何用户特定的操作(例如登录或提交详细信息) 您需要确保并行测试不会干扰 另一个.

    要消除测试之间的歧义,您可以使用 node-num 配置 变量。您可以在funkloadtestcase中使用:

    node_num = self.conf_get('bench', 'node_num', '0')
    

    还要注意funkload附带了一个凭据服务器(请参见 fl credential ctl 脚本),可用于维护单个数据库 跨多个线程和多个测试运行的凭据。

    执行测试

    您可以使用fl run test脚本在给定的 模块。这对于负载测试不是很有用,但是在编写时非常有用 以及调试测试。它也可以作为一个简单的功能测试工具。

    node_num = self.conf_get('bench', 'node_num', '0')
    
    0

    这将在给定模块中运行测试。注意,测试和 对应的 .conf 文件需要在当前目录中。如果你 将测试移动到专用目录,如建议的 台架试验/ 。 上面,您可以做到:

    node_num = self.conf_get('bench', 'node_num', '0')
    
    1

    有关详细信息,请参阅 funkload 文档。

    要在一个节点上运行简单的台架测试,可以使用fl run bench。 (这最终是板凳主控在每个节点上所做的):

    node_num = self.conf_get('bench', 'node_num', '0')
    
    2

    注意,我们必须指定测试用例类( testname )和方法 ( test_testname ),因为长跑者将只运行一个测试,即使 如果您在模块中进行了多个测试。

    此时,开始了解控制 长跑运动员。

    < dl >
    周期

    台架转轮将运行给定试验的多个循环。每个周期 在特定的并发级别上运行,它转换为 在那个循环中使用的线程。这实际上是对 让多个并发用户执行负载测试方案。

    可以使用命令行参数指定周期。例如, -c 10:20:30 将用10、20和30个线程执行三个周期, 分别是。默认循环在 .conf 文件中配置 负载测试。

    为了获得有用的负载测试,通常需要运行多个周期 一个固定的阶梯式增长。这使得测试的输出更容易 比较,

    持续时间

    台架转轮将在固定时间内运行每个循环,如 秒。同样,默认值可以在 .conf 文件中找到,但是可以是 用 -d 命令行参数重写,例如 -d 300 以运行 每次循环5分钟。

    给定周期中的每个线程将尝试执行测试的次数 它可以一直持续到测试结束(即 持续时间 秒 通过)。未完成的测试被中止,不计入负载 测试结果。

    此外,您可以设置请求之间的最小和最大睡眠时间(实际 睡眠时间是两者之间的随机值),测试之间的睡眠时间 执行和线程启动延迟。这些有助于模拟 随机性和延迟,有时是允许服务器 在真正的测试开始前达到"稳定状态"。查看 -h 选项,以及fl run bench命令中的注释。 .conf 文件,以及Funkload文档了解详细信息。

    < Buff行情> 提示: 尝试不同的持续时间和并发设置。 因为每个线程将在测试中重复执行测试 持续时间,您可以增加 增加任一参数。高并发、低持续时间 模拟高负载的短脉冲。长时间模拟持续 负载。后者往往更具启示性,因为短期内 使funkload忽略在持续时间内未完成的测试, 因为网关超时而无法完成 在服务器上。

    一旦你测试了你的台架测试在"普通"的垃圾堆中工作,你就可以 使用长板凳展开。

    为了说明这种部署,我们假设:

    • 以上先决条件已安装。

    • 您已经在两台机器上安装了Bench Master, 192.168.0.10 192.168.0.11 ,使用上面建议的构建,在 /opt/工作台。因此,二进制文件位于 /opt/bench/bin/

    • 工作台主机以用户的身份运行。此用户存在于 两个主机,并拥有 /opt/bench 和 这个目录。

    • ssh密钥具有设置为使 工作台可以从主服务器ssh到 节点和从主节点到它自己(我们将使用 bm.example.com 作为 一个工作台节点和一个主节点)不需要密码。

      提示: 首先手动测试,并确保远程主机 已知,即记录在 已知主机 文件中。

    • 测试见 /opt/bench/bench tests/test_testname.py 在同一目录中对应的 testname.conf

    首先,我们需要创建一个节点配置文件。这告诉法官 掌握将测试部署到哪个节点。我们称之为节点。 并将其保存在顶级目录中。它应该包含 条目如下:

    node_num = self.conf_get('bench', 'node_num', '0')
    
    3

    第一个标记是主机名。第二个是要使用的用户名。注释 我们在这里使用的是"伪"主机名。这是因为我们想用 同一物理服务器不止一次。这些都可以分解为实际的 /etc/hosts 文件中的IP地址,例如使用:

    node_num = self.conf_get('bench', 'node_num', '0')
    
    4

    在这里,我们选择在每台物理机器上运行两个工作台节点。这种类型 的设置适用于双核/处理器计算机,其中一个python 流程可以充分利用每个核心。

    我们现在可以执行测试:

    node_num = self.conf_get('bench', 'node_num', '0')
    
    5

    在此命令中:

    • -s 选项提供指向远程平台节点的路径 工作台节点。(它不需要存在于主机上,除非 主服务器也没有用作节点。)如果 对于远程服务器上的给定用户,工作台节点位于路径中。 这在ssh调用中用于执行工作台节点脚本。 在每台主机上。
    • -w 选项是工作台主机的工作目录。本遗嘱 最终包含最终的试验报告,以及记录的信息 在长跑中。对每个梯段的具体信息进行整理 在名为bench run的中间目录下。默认值 使用当前日期/时间和测试名称。
    • -c 选项覆盖 .conf 文件中的并发设置。 对于每个节点上的台架试验 。在这里,我们将运行三个周期,其中10个, 每个节点上分别有20个和30个并发线程 。这意味着, 对于四个节点,真正的并发是40、80和120个线程, 分别。
    • -d 选项以类似的方式覆盖持续时间。因此,在 每个周期,每个节点上的每个线程都将尝试执行测试 尽可能多次5分钟(300秒)。因为节点运行在 平行,这意味着每个周期的总持续时间为5分钟。
    • 这两个位置参数给出了节点文件的路径和测试 模块。在这种情况下,可以给出一个相对或绝对路径-确实 不必在当前目录中。

    除了这些选项之外,您还可以指定:

    • -n ,给测试运行命名,用作目录名 在板凳主工作目录下。默认设置是使用生成的名称 从当前日期和时间,加上测试名称。请注意,如果您使用 在多个调用中使用相同的名称,临时文件可以是 覆盖,但保留所有最终报告。
    • --节点数 ,以限制正在使用的节点数。默认情况下,所有 使用节点文件中的节点。如果只想使用前两个节点, 例如,您可以指定 --num nodes=2
    • -x ,指示工作区的路径每个节点上的目录。这个 默认情况下使用 /tmp/bench节点,如果不使用,将创建该节点 存在。
    • -u ,覆盖测试的基本url,可在test .conf中找到。 文件
    • -v ,查看更多输出。

    最后,您可能需要给出测试名称(即 fl record(记录测试时)作为第三个位置参数,在 测试模块 .py 文件。如果不使用"camelcase",这是必要的 (或所有小写)记录测试时。例如,如果测试方法 在一个模块中,test-foo bar.py 是test-foobar() ,您可以使用:

    node_num = self.conf_get('bench', 'node_num', '0')
    
    6

    有关详细信息,请参见 料仓/工作台主机的输出。 -h

    观察执行情况

    当板凳主控运行时,它将:

    • 在每个节点上创建一个工作区,并将测试远程复制到其中,外加 .conf 为每个节点定制的文件。的父目录 每个节点上的工作区都可以使用 -x 命令行选项进行设置。 在这个目录中,为每个标记的测试创建一个子目录 运行.< /P> < Buff行情>

      注意:您可以使用 -n 选项设置标签。这对 将测试分组。默认设置是根据 当前日期/时间和测试名称。

      在每个测试运行子目录中,都会专门创建一个子目录 对于每个节点。这允许多个"虚拟"节点(即多个节点 在同一台物理机器上的同一安装中。

    • 在每个节点上执行工作台节点脚本。这反过来运行 卸载台架测试转轮。

    • 监视每个节点上的标准输出和标准错误。这些罐头 在工作区的 out/ err/ 中找到 目录,在每个节点对应的文本文件中。你可以用尾巴 这些文件可从每个节点获得近乎实时的输出。

      err/ 目录将帮助您了解是否出了问题 在远程节点上。 out/ 目录对于检查 每个节点的进度。

    当测试运行时,您将在 三个标题:"启动线程"、"记录持续时间"和"秒" "停止线程"。对于每一个,您可以看到一个".","e"或"f"的数字。 字符。a"."表示成功,"e"表示错误,"f"表示失败。

    启动和停止线程失败可能表示funkload不能 启动足够的线程以获得循环中指示的并发性。是否 这个问题取决于生成 有效载荷试验。不管怎样,Funkload都将继续测试。

    "持续时间"行最重要。这就是 Funkload实际执行测试的时间。此处的错误表示 测试代码本身的问题,应该很少见。"f"表示一页 无法获取,或者测试断言失败。在负载测试场景中, 这可能意味着您的服务器已停止响应或超时。这个 报告(见下文)将为您提供有关哪类故障的更多详细信息 并报告错误。

    查看报告

    远程节点全部完成后,工作台主机将:

    • 将funkload从每个节点输出的xml文件整理到 results/ 工作台主工作区的子目录。
    • 将这些文件合并到单个结果文件中。
    • 从这个res生成一个html报告U.L/LI>

    最终的html报告将出现在工作台的 report/ 目录中 主工作区。如果这是在远程服务器上,则可能需要提供 从能够提供静态HTML文件的Web服务器,使 查看报告。

    例如,可以使用以下命令在端口8000上启动一个简单的http服务器:

    node_num = self.conf_get('bench', 'node_num', '0')
    
    7

    当然,您也可以使用apache、nginx或任何其他web服务器,并且 您可以使用 -w 选项将所有 结果所在的目录已配置为用作Web内容。

    < Buff行情> 提示: 如果您正在运行几个相关的负载测试,例如测试 对您的基础设施进行一系列计划性更改的效果,可以是 有助于将这些报告组合在一起。如果你跑几次长跑 使用与 -n 选项相同的名称,台架主控台将 将所有报表组合在一个顶级目录下 ( <;工作台 名称>;/报告/* )。请注意,如果这样做,则 out/ err/ 目录每次都将被覆盖。

    当你第一次看到一个糟糕的报告时,你可能会有点不知所措 细节的数量。一些更重要的东西是:

    • 查找任何错误或失败。每一个周期都有报告, 以及各页,并在报告结尾处总结。 记住,错误-特别是像503或504这样的http错误- 在非常高的并发性下,可以简单地表示您的 服务器。如果并发性比您的 实际上,这可能不是问题。

    • 看看整个测试运行的总吞吐量,看看它是如何 随循环并发性而变化。Funkload提供了三个指标:

      < dl >
      每秒成功测试

      这是可以执行的完整测试数除以 在所有周期中聚合的持续时间。

      如果您的测试模拟用户完成特定过程(例如 购买产品或创建一些内容)通过许多步骤, 这可能是一个有用的"业务"指标(例如,"我们可以在 10分钟)。

      每秒成功页数

      这是可以下载的完整网页数, 每秒包括样式表和图像等资源。

      注意funkload将以与web浏览器相同的方式缓存资源, 因此,给定的线程在给定的周期内只能获取一次特定的资源。

      这是了解您的 当你的网站在负载下运行时,访问者可以接收。这是最 如果测试只获取一个页面,或获取 在服务器处理时间方面大致相当。

      每秒成功请求数

      这是原始吞吐量的度量,即 每秒完成。

      此指标不一定与访问者如何体验 网站,因为它将网页及其依赖资源计算为 单独请求。

    • 寻找整体趋势。并发性如何降低性能 上升?是否存在业绩明显下降的"硬"限制? 关闭,或者网站完全停止响应?如果是,试着想想 这可能是操作系统对线程数的限制,或者 处理器或打开的文件描述符。

    • 看看正在获取的各个页面。有没有特别慢的页面? 不同的页面在并发时性能如何降低? 增加?

    有关详细信息,请参阅 funkload 文档。

    < / dIV>

    服务器监控

    了解负载测试过程中发生的情况很重要 跑。如果结果不是你所期望的,你需要知道 从何处开始调整。

    一些重要的注意事项包括:

    • 托管服务器上的CPU、内存和磁盘I/O负载是多少 申请?瓶颈在哪里?
    • 工作台之间的网络基础设施的容量是多少 节点和正在测试的服务器?你受带宽限制吗?是 有防火墙或其他设备执行密集扫描 请求,甚至主动限制吞吐量?
    • 板凳节点上发生了什么?他们是否未能产生足够的 加载或无法处理从 服务器?

    在任何情况下,你都需要监控。这可以包括:

    • 在上运行 top free 和其他"时间点"监视工具 服务器,

    • 使用类似于monit的工具实时观察多个进程。

    • 查看应用程序中涉及的各种服务的日志文件, 在测试运行时和测试完成后 已完成。

    • 使用Funkload内置的监控工具。

      注意: Funkload监控服务器仅在Linux主机上工作。

    Funkload监视器是有用的,至少它包含在 最后报告。你可以看到负载过大,内存和 随着负载测试的进行,任何数量的服务器上的网络吞吐量。

    Funkload监视要求在每个主机上运行一个监视服务器 被监视。安装了监视器控制程序,即fl monitor ctl 很有趣。您可以使用上面显示的平台主构建来安装 它,或者简单地在一个 virtualenv 中安装funkload,或者在每个主机上构建。

    一旦安装了fl monitor ctl,就需要一个配置文件 在每个主机上。例如:

    node_num = self.conf_get('bench', 'node_num', '0')
    
    8

    您应该根据需要调整主机名、网络接口和端口。

    然后,您可以使用以下命令在每个主机上启动监视器:

    node_num = self.conf_get('bench', 'node_num', '0')
    
    9

    监视器就位后,您需要告诉funkload要监视哪些主机。 这在测试的 .conf 中,在 [监视器] 部分中完成。 例如:

    AcceptEnv PSSH_*
    
    0

    在本例中,我们还选择监视测试台主机和节点 作为正在测试的Web服务器。监测工作台节点很重要,因为 它有助于确定它们是否正常产生负载。

    有了这个配置,您应该在您的funkload中得到监视 报告

    < Buff行情> 注意: 如果您使用台架主机来运行测试,它将 确保只有第一个节点收集监视统计信息。它确实 无法同时监视所有节点上的多个主机。

    手动生成报告

    当funkload执行一个测试运行时,它将编写一个包含所有 相关检测结果及统计。bench master收集这些xml文件 从每个节点并将其整理为单个文件。(单个文件是 全部保存在内部的bench run目录下的 results/ 目录中 然后使用funkload报告 用于创建HTML报表的生成器。

    如果要手动创建报告,可以使用fl build报告 脚本,

    例如,要获取报表的纯文本版本,可以使用:

    AcceptEnv PSSH_*
    
    1 <至获取相同的HTML版本,您可以使用–html选项:

    AcceptEnv PSSH_*
    
    2

    报告将放在当前目录中。使用 -o标志 指示不同的输出目录。

    差异报告

    您可以使用负载测试来了解更改对性能的影响。 为了便于比较负载测试运行,funkload提供了 报告。

    例如,假设您在 试验台输出/基线/报告/试验_foo-20100101 。然后可以添加新的 服务器,并在"工作台主控"中重新运行相同的测试,这次使用 命名为"新服务器"。结果报告可能是 工作台输出/新服务器/报告/测试foo-20100201 。您可以创建 两者之间的差异:

    AcceptEnv PSSH_*
    
    3

    当然,这也适用于使用"普通"funkload生成的报告。

    < Buff行情> 提示: 要使差异报告有意义,您需要 相同的测试,以相同的周期数执行,相同的周期 同时,两份报告的持续时间相同。

    积分

    最初由Julian Coyne创建。重构的 由martin aspeli<; optilude @ gmail com >;单独打包成一个包

    更改日志

    1.0b1-2010-07-26

    • 初始版本

    欢迎加入QQ群-->: 979659372 Python中文网_新手群

    推荐PyPI第三方库


    热门话题
    java如何为ConcurrentHashMap使用并设置适当的并发级别?   java泛型方法,运行时错误,   java在页面上显示加载的图像   java Paypal定期直接支付问题   java如何延迟重新绘制组件   JavaSpringBoot+Hibernate如何维护@Transient字段   java在其方法中获取关于类的信息   在java中将别名添加到枚举   java如何解决向google报告成绩时“需要重新连接客户端”的问题   清晰的java图像背景   java未找到适合JDateChooser的构造函数(字符串、字符串、字符)   java LRU缓存实现。某些测试用例的代码失败   if语句Java嵌套的if/Else条件   java JSoup“wrap”并非每次都按预期工作   Java Spring引导循环依赖于一个环境   ssl证书无法通过Java和IntelliJ连接到SOAP服务   带整数验证的Java扫描器   java在Flex中呈现具有动态列的datagrid   java Android:通过用户选择的选项将文件上载到服务器   子类中的java抛出错误、异常和运行时异常