精华内容
下载资源
问答
  • Apache JMeter是 Apache 旗下的开源压测工具,创建于 1999 年初,迄今已有超过 20 年历史。...按指定压力量级启动压测。 压测监控分析。压测中通常关注施压 RPS,成功率,业务响应时间(RT),网.

    Apache JMeter 是 Apache 旗下的开源压测工具,创建于 1999 年初,迄今已有超过 20 年历史。JMeter 功能丰富,社区(用户群体)庞大,是主流开源压测工具之一。

    性能测试通常集中在新系统上线或大型活动前(如电商大促,春节活动等),以验证系统能力,帮助排查定位性能瓶颈等问题。

    一次压测活动可粗略分为几个步骤:

    1. 场景配置。配置压测场景模拟用户(业务)与系统的交互。
    2. 压测执行。按指定压力量级启动压测。
    3. 压测监控分析。压测中通常关注施压 RPS,成功率,业务响应时间(RT),网络带宽等关键指标。
    4. 报告总结。披露系统能力是否符合要求,同时沉淀记录系统性能演变和优化过程。

    下面我们讨论如何使用 JMeter 完成上述步骤,及相关的最佳实践建议。

    JMeter 使用 Java 开发,需要先安装 JDK 并配置好 PATH 环境变量,然后从官网下载 JMeter 二进制压缩包解压即可。
    建议将 JMeter bin 目录也添加到 PATH 环境变量,这样在命令行下输入 jmeter 命令即可启动 JMeter 。

    场景配置

    简单 HTTP 请求配置

    最常见的压测场景即 HTTP 压测。
    压测场景在 JMeter 脚本中叫做 Test Plan(压测计划),打开 JMeter 默认即为一个空 Test Plan 。JMeter 使用并发(线程)数控制压力大小,一个线程可看做一个执行请求的虚拟用户。在 Test Plan 上点击右键,添加一个 Thread Group(线程组)。

     

    线程组默认为 1 个线程并只执行一次 1 次,这很方便测试执行脚本,保持此默认值即可。

     

    JMeter 中发送请求的组件叫做 Sampler(采样器)。在 Thread Group 上单击右键,添加一个 HTTP Request 节点(采样器)。

     

    HTTP 请求最关键的配置即 URL,JMeter 允许将 URL 协议类型(Protocol)、服务器名、请求路径(Path)等拆开单独配置。也可以直接将整个 URL(如 JMeter 主页 http://jmeter.apache.org/ )填写到 Path,其他字段保留为空即可。这样,一个最简单的 HTTP 压测脚本就配置好了。

     

    为了方便测试、调试脚本,可在 Test Plan 下添加一个 View Results Tree 监听器(Listener)。这个监听器仅用于编辑脚本时测试、调试脚本,查看请求执行详情,不需要做任何配置。

     

    测试执行脚本

    第一次执行脚本前,需要先保存脚本,如保存为 test.jmx 。以后每次执行脚本前,JMeter 默认会自动保存脚本。

    连续多次执行脚本时,JMeter 默认不会清理历史记录。为了避免历史执行结果干扰,可先点击 Clear All 按钮手动清空历史记录,再点击 Start 按钮执行脚本,这样看到的执行结果更清爽,方便排查问题。

     

    按照默认线程组配置,脚本执行一次即结束。点击 View Results Tree ,可看到请求执行详细信息,包括请求头,请求体,响应头和完整的响应体等信息。

     

    场景编排

    真实压测场景通常不会只有一个请求,而是多个请求按一定顺序和规则的编排组合,即场景编排。场景编排是 JMeter 等压测引擎最重要的功能之一,也是与 apache ab等简单压测工具的重要区别之一。

    这里我们假设一个最简单的场景,先访问 JMeter 主页,停留 1 秒钟后跳转到下载页。

    一个脚本访问一个网站的不同页面(Path)时,可添加一个 HTTP Request Defaults 节点,配置默认协议类型和服务器名。这样可避免重复配置,需要修改协议类型(如 https 与 http 切换)或压测域名时,只用修改 HTTP Request Defaults 即可。

     

    HTTP Request Defaults 配置服务器名为 jmeter.apache.org(协议类型默认为 http),鼠标可拖动 HTTP Request Defaults 节点移动到 HTTP 请求节点之前。

     

    每个请求节点可设置一个具有业务含义的名字,方便理解和管理。访问 JMeter 主页的 HTTP 请求可改名为 home ,同时 Path 修改为 / 。再添加一个 HTTP 请求节点,命名为 download page ,设置 Path 为 /download_jmeter.cgi 即可。

     

    模拟在 home 页面停顿 1 秒钟。home 节点上右键,添加一个 Constant Timer 子节点,设置延迟时间为 1000 毫秒即可。

     

    再次执行脚本,点击 View Results Tree 可看到两个 HTTP 请求节点的执行详情。

     

    注意:

    1. Timer 节点作为场景编排辅助节点,没有请求执行动作,也没有执行详情显示。
    2. 循环执行脚本时,最后一个节点 download page 执行结束后,会立即跳转到脚本开头,执行第一个节点 home 。

    可在 download page 上也添加一个 Timer,模拟停留一秒之后再继续后续请求。

    JMeter 的压测执行

    编辑、调试脚本时,我们通常设置为 1 个线程并且只执行 1 次。执行压力测试时,通常需要以较高的压力持续执行一段时间。

    脚本固定配置压力

    如计划以 50 并发执行 2 分钟,可修改脚本 Thread Group 配置如下。

     

    配置说明:

    1. 并发数(Number of Threads (users))设置为 50 。
    2. 循环次数(Loop Count)勾选永远执行(Forever)。
    3. 勾选 Scheduler,设置执行时长(Duration (seconds))为 120 秒。

    通常我们在 JMeter 图形界面(GUI)编辑脚本,但执行压力测试时 GUI 占用额外资源可能影响施压性能,而且施压机可能没有图形界面环境(如 ssh 远程登录施压机)。因此脚本编辑完成后,通常以命令行模式执行 JMeter 压力测试。

    进入 JMeter 脚本目录,执行 JMeter 压力测试的命令为:

    jmeter -n -t <脚本>
    

    如执行上述 test.jmx 脚本,命令如下:

    jmeter -n -t test.jmx
    

    输出结果如下:

    Creating summariser <summary>
    Created the tree successfully using test.jmx
    Starting the test @ Tue Jun 25 14:38:32 CST 2019 (1561444712414)
    Waiting for possible Shutdown/StopTestNow/Heapdump message on port 4445
    summary +    553 in 00:00:27 =   20.3/s Avg:  1378 Min:   252 Max:  8587 Err:     0 (0.00%) Active: 50 Started: 50 Finished: 0
    summary +    882 in 00:00:30 =   29.4/s Avg:   685 Min:   222 Max:  4272 Err:     0 (0.00%) Active: 50 Started: 50 Finished: 0
    summary =   1435 in 00:00:57 =   25.1/s Avg:   952 Min:   222 Max:  8587 Err:     0 (0.00%)
    summary +    829 in 00:00:30 =   27.5/s Avg:   815 Min:   222 Max: 21310 Err:     0 (0.00%) Active: 50 Started: 50 Finished: 0
    summary =   2264 in 00:01:27 =   25.9/s Avg:   902 Min:   222 Max: 21310 Err:     0 (0.00%)
    summary +    881 in 00:00:30 =   29.5/s Avg:   700 Min:   221 Max:  3896 Err:     0 (0.00%) Active: 50 Started: 50 Finished: 0
    summary =   3145 in 00:01:57 =   26.8/s Avg:   845 Min:   221 Max: 21310 Err:     0 (0.00%)
    summary +    127 in 00:00:05 =   24.2/s Avg:   797 Min:   224 Max:  3819 Err:     0 (0.00%) Active: 0 Started: 50 Finished: 50
    summary =   3272 in 00:02:02 =   26.7/s Avg:   843 Min:   221 Max: 21310 Err:     0 (0.00%)
    Tidying up ...    @ Tue Jun 25 14:40:35 CST 2019 (1561444835251)
    ... end of run
    

    压测过程中默认每 30 秒输出一次统计数据,2 分钟后(实际为 00:02:02,比预设的 2 分钟多出少许误差)压测结束。看最后一行统计数据,平均 RPS(每秒请求数)为 26.7,平均 RT (响应时间)为 843 毫秒。

    尝试核对一下统计数据。脚本包含两个请求,每个请求附加 1 秒钟等待时间,发送一个请求平均耗时为 RT 843 毫秒 + 等待 1000 毫秒。单线程理论 RPS 为 1000.0 / (843 + 1000),总共 50 个线程,全场景理论 RPS 为 1000.0 / (843 + 1000) * 50 = 27.13,与统计值 26.7 有一定误差。这是因为除了请求 RT 和等待时间,脚本执行请求之间还可能存在少量时间消耗。

    命令行动态设置压力

    实际工作中,常常需要以不同的压力大小反复执行压力测试,在脚本中写死压力大小(并发数)和执行时间显然很不方便。

    如何动态指定压力大小呢,这里有一个技巧。JMeter 脚本支持使用 JMeter 属性进行配置,JMeter 命令行支持使用 -J 参数动态指定 JMeter 属性。把这两者结合起来,即可实现在命令行通过 -J 参数动态设置压力大小。

    修改 JMeter 脚本使用 JMeter 属性配置压力大小,配置如下:

     

    配置说明:

    1. 并发数配置为 ${__P(load.concurrency,1)},循环次数取消勾选 Forever,配置为 ${__P(load.count,1)}。 未设置对应的 JMeter 属性时,默认为 1 ,满足只执行 1 次以测试、调试脚本的需求。
    2. 执行时长配置为 ${__P(load.duration,60)},默认 1 分钟(60 秒)。

    测试命令行直接执行脚本:

    jmeter -n -t test.jmx
    

    可看到统计输出如下:

    summary =      2 in 00:00:03 =    0.6/s Avg:   485 Min:   408 Max:   563 Err:     0 (0.00%)
    

    默认一个并发并且只执行一次,发出 2 个请求(脚本循环一次发出两个请求),约 3 秒后脚本停止。
    注意:默认执行时间是 1 分钟,同时配置了循环次数和执行时间时,有一个条件先满足脚本即停止。

    为了按指定时长执行,需要将执行次数设置为 Forever 。
    在 JMeter 内部实现中,执行次数为 -1 即表示 Forever 。
    指定以 50 并发执行 2 分钟,jmeter 命令行如下:

    jmeter -n -t test.jmx -Jload.concurrency=50 -Jload.duration=120 -Jload.count=-1
    

    执行结果与前述脚本固定配置 50 并发的结果类似。

    云上的 JMeter 实践

    阿里巴巴有着非常丰富的业务形态,每一种业务形态背后都由一系列分布式的技术体系提供服务,随着业务的快速发展,特别是在双 11 等大促营销等活动场景下,准确评估整个业务站点的服务能力成为一大技术难题。

    在这个过程中,我们打造了自己的全链路压测系统,以应对更复杂、更多样的压测需求,并将此技术输出到 性能测试 PTS 上,同时支持原生 JMeter 压测。

    打开 PTS 控制台 主页,左侧导航栏选择 创建压测 > JMeter 压测 ,新建 JMeter 压测场景。填写场景名,如 jmeter-test 。场景配置 页面点击 上传文件 按钮,上传本地测试通过的 test.jmx 脚本。

     

    施压配置 页面,并发数设置为 50,压测时长设置为 2 分钟。

     

    点击 保存去压测,弹出提示框点击 确认,PTS 即开始在云端引擎执行 JMeter 脚本发起压力。

     

    压测中页面如下:

     

    压测中实时展示场景(及每个请求页面)实时 RPS 和 RT 等信息。可看到场景并发数为 50,RPS 为 26,RT 为 812 毫秒,与本地压测的结果差不多。
    注意:因为机器配置和网络环境的差异(PTS 施压机默认为 4 核 8G,BGP 多线路公网),PTS 上压测结果可能与本地压测结果存在一定差异。

    针对 JMeter 施压配置,再补充几点说明:

    1. PTS 上的施压配置会覆盖原脚本中的配置。 原脚本无论是写死固定配置还是使用 JMeter 属性配置都没关系。
    2. 循环次数表示每个线程循环执行脚本的次数,可能与用户的直觉理解不一样,如 总请求数 = 脚本执行一次的请求数 * 循环次数 * 并发数 。
    3. 循环次数与预热时间同时配置时可能导致意外行为(如不能达到最大并发), 因此 PTS 上不允许同时配置预热时间和循环次数(即只有预热时间为 0 时才允许设置循环次数)。

    压测监控分析

    性能测试不仅仅是简单的发起压力,对压力负载(RPS,网络带宽等)和业务表现(RT,成功率等)的监控和分析也是压测活动的重要组成部分。

    JMeter 脚本中每个请求节点(Sampler)可设置一个具有业务含义的名字(如 home 和 download page ),我们可称之为业务 API 。JMeter 监控统计按业务 API 名字汇总,如两个名字相同的请求节点将汇总统计为一个业务 API 。配置脚本时需注意,不同业务 API 节点应配置为不同的名字。

    业务 API 压力负载和表现

    实际工作中,不同业务 API 的统计数据可能存在巨大差异(如浏览商品 RT 通常比提交订单快很多),因此 PTS 默认将各个业务 API 独立统计展示(如上述压测中页面展示的 home 和 download page)。

    压测中每个时间点的数据 PTS 都在后台记录了下来,最终将形成完整直观的压测报告。点击业务 API 实时监控趋势图按钮

     

    ,即可查看对应的 RPS,成功率,响应时间,网络带宽等监控数据的变化趋势图。

     

    业务 API 采样日志

    很多时候我们还希望看到一个具体请求执行的详细信息。如有 1% 的请求失败,需要查看完整的请求、响应内容,以排查失败原因等。JMeter 图形界面下测试脚本时,可添加 View Results Tree 查看单个请求的详细信息,但执行压力测试时,对每个请求都记录详细信息,不仅没有必要,而且非常耗费资源,影响施压性能。

    阿里云 PTS 采取了一个折中的办法,施压引擎每 5 秒对每个业务 API(压测 Sampler)分别采样记录一条成功和失败(如果有)的请求详细信息。在压测中或压测报告页面,点击 查看采样日志 按钮即可查询记录的请求采样信息,并支持按业务 API(压测 Sampler),响应状态(是否成功),请求时间等进行搜索过滤。

     

    点击 查看详情 即可看到单个请求的详细信息。目前对详细信息提供了通用和 HTTP 两种展示模板,HTTP 展示模板可针对 HTTP 请求进行更友好的排版展示,展示内容包括请求 URL,请求方法,返回码,完整的请求头、请求体,响应头、响应体等。

     

     

    因为页面上只展示文本内容,请求体或响应体包含图片等无法识别为文本的内容时,可能显示为乱码。另外当请求体或响应体很大时,对应的内容可能被截断。

    JMeter 日志

    本地执行 JMeter 脚本时,默认将日志记录到 jmeter.log 文件。在 PTS 上执行 JMeter 脚本时,可通过 JMeter 日志 页面实时查看 JMeter 日志,并支持根据日志级别、时间或线程名进行查询过滤。

     

    JMeter 日志主要用于脚本执行报错时排查错误原因。一些插件可能通过 JMeter 日志输出一些重要信息,用户在 groovy 脚本等代码中也可以直接打印日志。

    日志打印过于频繁时,不仅可读性极差(大量重复日志淹没重要信息),而且影响 JMeter 性能,对 PTS 采集存储 JMeter 日志造成额外开销。因此 PTS 在采集 JMeter 日志时默认进行了限流,每秒钟打印日志条数超过 10 条时部分日志可能会丢失。良好设计的 JMeter 脚本应避免大量打印重复日志。

    同样,良好设计的 JMeter 脚本应避免通过标准输出(System.out)或标准错误(System.err)打印输出信息,
    需要输出查看的重要信息应使用 JMeter 日志输出(如 groovy 脚本中使用 log.info("") )。
    PTS 上不支持查看 JMeter 脚本执行产生的标准输出和标准错误内容。

    报告总结

    压测结束后,PTS 将汇总监控数据形成压测报告。用户根据压测报告分析评估系统性能是否符合要求,如 RPS,成功率和 RT(响应时间)是否符合期望。并可辅助用户排查分析业务系统性能瓶颈。

    PTS 压测报告页面可查询历史压测报告列表。

     

    点击 查看报告 打开查看报告详情。压测报告在 PTS 上默认保存 30 天,可点击 报告导出 按钮,导出保存 PDF 版压测报告到本地。
    压测报告概要信息包括压测执行时间,RPS,RT,成功率等概要数据。场景详情包含全场景维度和业务 API 维度的监控统计信息。
    注意:受 JMeter 引擎本身统计功能的限制,仅全场景维度包含并发数统计。

     

    此外,全场景维度和业务 API 维度均包含 RPS,成功率,网络带宽等统计。如 home 请求相关监控趋势图如下。

    相比手动命令行执行 JMeter 脚本,PTS 更加 简单易用 ,提供 简单直观的监控 ,并提供 海量施压能力 。

    免费 开通 PTS 服务,购买 5000 VU
    以上资源包,即可使用 JMeter 压测。PTS 计费单位是 VUM ,即并发(VU)* 分钟(最低消费 100 VUM)。上述场景消费为 50 并发 * 2 分钟 = 100 VUM 。如购买 5000 VU资源包,包含 10 万 VUM,售价 ¥278 ,上述计费可换算为 (100 / 10万) * ¥278 = ¥0.278 。

    使用 CSV 参数文件

    上述 JMeter 脚本仅简单请求固定 URL ,真实业务 API 通常带有请求参数。

    JMeter 中可使用 CSV Data Set Config 读取 CSV 数据文件,简单实现请求参数化。CSV 文件默认首行为变量名(列名),其余行为 CSV 数据。准备一个 user.csv 文件,包含 id , name 两列,内容如下:

    id,name
    1,ali
    2,pts
    3,jmeter
    

    注意:手工编辑 CSV 文件容易出错,推荐使用 Excel、Numbers 等软件导出,或编程使用 apache commons-csv 生成。编辑 JMeter 脚本,右键单击 Thread Group 添加一个 CSV Data Set Config 节点。

     

    配置如下:

     

    其中有两个地方需要注意(其他配置保持默认即可):

    1. Filename 配置为文件名 user.csv 即可,不要包含文件路径。 不同施压机上 CSV 文件路径可能不一样,只使用文件名(并在当前路径下执行脚本)以便兼容不同的施压机环境。
    2. Sharing mode 设置为 Current thread group,指定 CSV 文件只被当前线程组使用。

    假设 home 请求需要设置参数,配置请求参数直接使用 ${id} ,${name} 引用对应的变量即可。

     

    测试执行脚本,查看 View Results Tree ,可看到执行请求时即会带上请求参数。

     

    在阿里云 PTS 上执行脚本,只需编辑 JMeter 场景,上传修改后的 test.jmx 脚本文件和 user.csv 数据文件,点击 保存去压测 即可。

     

    查看请求采样,可看到请求 URL 已添加对应的参数。

     

    使用 JMeter 插件和附加 jar 包

    JMeter 社区提供了丰富的插件,用户还可以自由添加使用 Java 库 Jar 包。在 PTS 上执行脚本时,只需要将额外添加的插件和 jar 包一起上传到 PTS 上,PTS 执行 JMeter 脚本时即可自动加载这些 Jar 包。详情可参考 如何进行 WebSocket 协议的压测 。

    如果遇到问题,请先确认本地已测试通过,并确认额外使用的 Jar 包已全部上传到 PTS 。

    海量施压能力

    之前的脚本中,我们在请求后添加了 1 秒钟的等待时间以演示业务场景编排。如果压测场景前后请求没有关联,从服务器的角度看只是不停的收到各种请求,与客户端是否等待无关,因此 JMeter 脚本可去掉这些等待时间,以最大压力向服务器发起极限压测。

    JMeter 使用并发(线程)数控制压力大小,通常(并发较小时)线程数越多压力越大。但单台施压机的能力毕竟有限,单机线程数增加到某个阈值时请求压力即达到极限。显然,为了继续增加压力,必须使用多台施压机进行分布式压测。

    分布式压测需要注意以下几点:

    1. 每台施压机需要安装、启动 JMeter,拷贝分发脚本、CSV 数据、附加 jar 包等文件。
    2. 协调分配施压并发数。通常施压机配置相同,均分施压并发数即可。
    3. 统一控制启动、停止压测,统一收集聚合监控数据。
    4. 希望 CSV 数据唯一或打散数据时,多台施压机需要拆分 CSV 数据文件 。

    使用阿里云 PTS 执行 JMeter 脚本时,用户只需要设置期望的最大并发即可 ,PTS 自动透明处理了分布式压测的问题,用户不用关心是单机压测还是分布式压测。PTS 默认每台 JMeter 施压机最大分配 500 并发,场景并发数超过 500 时即自动分配多台施压机。如果希望多台施压机拆分 CSV 数据文件,只要在上传 CSV 文件后勾选 切分文件 即可。详情参考 切分 CSV 数据文件 。

     

    单机线程数极限与 JMeter 脚本的复杂程度和资源占用(如 CPU,内存,网络带宽占用等)情况有关。占用内存过高的 JMeter 脚本在并发过高时甚至可能会因内存溢出而导致 JMeter 引擎异常退出。对有特殊需求的高级用户,PTS 允许用户手动指定施压机数量,以更精确的控制总并发数和单机并发数。只需在 施压配置 页面勾选 指定 IP 数,设置相应的施压机数量即可。每台施压机有一个 IP 地址,指定 IP 数即指定施压机数量。

     

    注意:指定 IP 数后,压测执行时独占了指定数量的施压机,每台施压机将按 500 并发计费(无论实际并发多少)。此功能专为有特殊需求的高级用户提供,普通用户通常不需要使用。

    展开全文
  • 本次新增对每组参数采用协程压测的方式进行压测yaml 管理用例支持登陆成功后返回 token 或者 user_id 给其他接口使用,如果接参数需要多个加密参数,留了扩展,自己去封装检查点采用检查接口和访问数据库的方式进行...

    本次新增

    对每组参数采用协程压测的方式进行压测

    yaml 管理用例

    支持登陆成功后返回 token 或者 user_id 给其他接口使用,如果接参数需要多个加密参数,留了扩展,自己去封装

    检查点采用检查接口和访问数据库的方式进行检查

    如果正常参数直接访问数据库,如果是异常参数直接读取接口返回值

    注意此框架暂时还是探索阶段,有什么好想法欢迎提供

    常用配置

    全局变量

    PICT_PARAMS = "d:/params.txt" # 请求参数存放地址txt

    PICT_PARAMS_RESULT = "d:/t2.txt" # 参数配对后的路径excel

    # 数据库的常用字段

    FIND_BY_SQL = "findBySql" # 根据sql查找

    COUNT_BY_SQL = "countBySql" # 自定义sql 统计影响行数

    INSERT = "insert" # 插入

    UPDATE_BY_ATTR = "updateByAttr" # 更新数据

    DELETE_BY_ATTR = "deleteByAttr" # 删除数据

    FIND_BY_ATTR = "findByAttr" # 根据条件查询一条记录

    FIND_ALL_BY_ATTR = "findAllByAttr" #根据条件查询多条记录

    COUNT = "count" # 统计行

    EXIST = "exist" # 是否存在该记录

    #接口简单点中的erro定义

    NORMAL = "0" # 正常参数,可以到表里面找到

    DEFAULT = "1" # 无此参数

    EMPTY = "2" # 参数为空值,如name=''

    DROP = "3" # 数据库中找不到此参数

    # 接口统计

    LOGIN_KEY = "" # 登陆后返回的key

    LOGIN_VALUE = "" # 登陆后返回的value

    RESULT = {"info": []} # 存最后结果

    api.yaml

    ---

    title: XXXX接口测试

    host: rap.taobao.org

    port: 80

    protocol: http://

    header: {"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.59 Safari/537.36"}

    database: {"databaseName":userinfo,"host":"127.0.0.1", "user": "root", "password": "", "port": 3306, "charset": "utf8"} #配置数据库

    api_list:

    - id: 1001

    name: 登陆

    method: post

    url: /mockjs/11463/login

    stress: 2

    hope_sql: {"findKey": "findBySql", "sql": "select * from info", "params": { }} #注意findKey的值,要对应全局变量里面的值

    params:

    - "user_name:user_name:error:0:send_keys:333:type:str,user_name:error:1,user_name:error:2,user_name:error:3:send_keys:22222:type:str"

    - "pwd:pwd:error:0:send_keys:111:type:str,pwd:error:1,pwd:error:2,pwd:error:3:send_keys:32321:type:str"

    # 注意这里的error,对应全局变量里面的error

    is_first: 1 # 预览的登陆接口

    login_key: user_id # 返回给其他接口使用的key

    - id: 1002

    ...

    get_login_param: 1 # 需要登陆接口返回过来的参数

    核心代码分析

    入口代码

    from DAL import httpConfig as hc

    from DAL import gevents, dbConnection, httpParams

    from common import operateYaml

    from DAL.pairs import *

    PATH = lambda p: os.path.abspath(

    os.path.join(os.path.dirname(__file__), p)

    )

    def myRequest(**kwargs):

    # {"appStatus": {"errorCode": 0,"message": "操作成功"},"content": {"nickname":"1212121","user_id": 30}} 接口定义的规则

    # 现在只是考虑到了登陆后返回token,user_id这方面的需求

    method = kwargs["param_req"]["method"]

    get_login_params = 0 # 标识接受了返回多少个参数(user_id,token),用作后面拓展

    param = httpParams.params_filter(kwargs["param_result"]) # 请求参数的处理,如果这里有各种加密可从此处扩展

    # get_login_param表示此接口需要登陆返回来的id(token),一般登陆成功后返回的字段

    if kwargs["param_req"].get("is_first", "false") == "false" and kwargs["param_req"].get("get_login_param", "false") != "false":

    param[Const.LOGIN_KEY]= Const.LOGIN_VALUE

    get_login_params += 1

    if kwargs["param_req"]["method"] == Const.HTTP_POST:

    really_result = kwargs["http_config"].post(dict_post=kwargs["param_req"], param=param) # 发送post请求

    elif kwargs["param_req"]["method"] == Const.HTTP_GET:

    really_result = kwargs["http_config"].get(dict_get=kwargs["param_req"], param=param) # 发送get请求

    if really_result.get("status_code") == 200:

    print("请求%s成功鸟" %method)

    if kwargs["param_req"].get("is_first", "false") != "false" :

    # 需要接口返回过来的login_key,如token,user_id)等,此时就不用查数据库作为检查点,检查点为直接读取响应结果

    if really_result["appStatus"]["errorCode"] == 0:

    Const.LOGIN_KEY = kwargs["param_req"]["login_key"]

    Const.LOGIN_VALUE = really_result["content"][Const.LOGIN_KEY]

    print("%s接口验证通过,不查数据库" %method)

    kwargs["result"]["success"] += 1

    else:

    print("%s接口测试失败,不查数据库~" %method)

    kwargs["result"]["failed"] += 1

    #如果实际的参数是异常,is_first表示是非登陆接口,就不查数据库.

    elif len(kwargs["param_result"].keys()) != len(param) - get_login_params:

    #根据接口返回的errorCode判断,假如errorCode=2表示参数异常

    if really_result["appStatus"]["errorCode"] == 2:

    print("%s接口异常参数检测通过" % method)

    kwargs["result"]["success"] += 1

    else:

    print("%s接口异常参数检测失败" % method)

    kwargs["result"]["failed"] += 1

    return

    else: #直接查询数据库作为检查点

    check_sql_key = kwargs["param_req"]["hope_sql"]["findKey"] # 根据这里的key,来跳转到不同的数据库查询语句

    kwargs["param_req"]["hope_sql"]["params"] = param # 已经处理好的请求参数传给数据库sql语句参数,结果为:params{"a":"b"}

    for item in kwargs["param_result"]:

    # error: 0正常,1无此参数,2参数的值为空,3在数据库中不存.0和3查数据库,1,2直接读取接口返回信息

    error = kwargs["param_result"][item]["error"]

    if error == Const.NORMAL or error == Const.DROP:

    if kwargs["check_sql"].findKeySql(check_sql_key, **kwargs["param_req"]["hope_sql"]):

    print("%s数据库接口验证成功" %method)

    kwargs["result"]["success"] += 1

    else:

    print("%s数据库接口验证失败" %method)

    kwargs["result"]["failed"] += 1

    return

    elif error == Const.DEFAULT or error == Const.EMPTY:

    if really_result["appStatus"]["errorCode"] == 2: # 接口返回的2为参数异常

    print("%s接口异常参数检测成功" %method)

    kwargs["result"]["success"] += 1

    else:

    print("%s接口异常参数检测失败" % method)

    kwargs["result"]["failed"] += 1

    return

    else:

    print("请求发送失败,状态码为:%s" % really_result.get("status_code"))

    def gevent_request(**kwargs):

    for i in kwargs["api_config"]: # 读取各个接口的配置,api.ymal

    # 生成参数

    pict_param(params=i["params"], pict_params=Const.PICT_PARAMS,

    pict_params_result=Const.PICT_PARAMS_RESULT)

    # 读取参数

    get_param = read_pict_param(Const.PICT_PARAMS_RESULT)

    count = len(get_param) # 根据不同分组参数,循环请求

    green_let = []

    req = {}

    for key in i:

    if key != "params": # 过滤请求参数,参数上面已经处理好了

    req[key] = i[key]

    result = {} # 统计数据

    result["name"] = req["name"] # 接口名字

    result["method"] = req["method"]

    result["url"] = req["url"]

    result["sum"] = count

    result["stress"] = req["stress"]

    result["success"] = 0

    result["failed"] = 0

    kwargs["result"] = result

    for k in range(0, count):

    kwargs["param_result"] = get_param[k] # 接口中不同的参数组合,是dict类型

    kwargs["param_req"] = req #每次请求除组合参数之外的参数,如逾期只,请求的url,method,结束等

    for item in range(kwargs["param_req"]["stress"]): # 压力测试,启动协程去压测

    green_let.append(gevents.requestGevent(myRequest(**kwargs)))

    for k in range(0, kwargs["param_req"]["stress"]):

    green_let[k].start()

    for k in range(0, kwargs["param_req"]["stress"]):

    green_let[k].join()

    Const.RESULT["info"].append(kwargs["result"])

    def get_config(api_ymal):

    '''

    得到api.ymal中的设置的接口信息

    :param api_ymal:

    :return:

    '''

    http_config = {} # http信息的记录

    api_config = [] # api的记录记录

    get_api_list = operateYaml.getYam(api_ymal)

    for key in get_api_list:

    if type(get_api_list[key]) != list:

    http_config[key] = get_api_list[key]

    else:

    api_config = get_api_list[key]

    return http_config, api_config

    if __name__ == "__main__":

    start_time = time.time()

    get_api_config = get_config(PATH("api.ymal"))

    http_conf = hc.ConfigHttp(dict_http=get_api_config[0]) # http请求的设置

    apiConfigs = get_api_config[1]

    check_sql = dbConnection. MySQLet(host=get_api_config[0]["database"]["host"], user=get_api_config[0]["database"]["user"],

    password=get_api_config[0]["database"]["password"], charset=get_api_config[0]["database"]["charset"],

    database=get_api_config[0]["database"]["databaseName"], port=get_api_config[0]["database"]["port"])

    gevent_request(http_config=http_conf, api_config=get_api_config[1], check_sql=check_sql)

    check_sql.close()

    end_time = time.time()

    print("共花费:""%.2f" % (end_time - start_time))

    print(Const.RESULT)

    封装好的访问数据库,查看主要代码来自这里,我修改了一些东西和 bug

    import mysql.connector

    import mysql.connector.errors

    from common.customConst import Const

    class MySQLet:

    """Connection to a MySQL"""

    # def __init__(self,user='',password='',database='',charset=None,port=3306):

    def __init__(self,**kwargs):

    try:

    self._conn = mysql.connector.connect(host=kwargs["host"], user=kwargs["user"], password=kwargs["password"],

    charset=kwargs["charset"], database=kwargs["database"], port=kwargs["port"])

    self.__cursor = None

    print("连接数据库")

    #set charset charset = ('latin1','latin1_general_ci')

    except mysql.connector.errors.ProgrammingError as err:

    print('mysql连接错误:' + err.msg)

    # def findBySql(self, sql, params={}, limit=0, join='AND'):

    def findBySql(self, **kwargs):

    """

    自定义sql语句查找

    limit = 是否需要返回多少行

    params = dict(field=value)

    join = 'AND | OR'

    """

    print("-----------findbysql-----")

    print(kwargs)

    cursor = self.__getCursor()

    # sql = self.__joinWhere(kwargs["sql"], kwargs["params"], kwargs["join"])

    if kwargs.get("join", 0) == 0: kwargs["join"] = "AND"

    if kwargs.get("limit", "0") == "0": kwargs["limit"] = 1

    sql = self.__joinWhere(**kwargs)

    cursor.execute(sql, tuple(kwargs["params"].values()))

    rows = cursor.fetchmany(size=kwargs["limit"]) if kwargs["limit"] > 0 else cursor.fetchall()

    result = [dict(zip(cursor.column_names,row)) for row in rows] if rows else None

    return result

    # def countBySql(self,sql,params = {},join = 'AND'):

    def countBySql(self, **kwargs):

    """自定义sql 统计影响行数"""

    if kwargs.get("join", 0) == 0: kwargs["join"] = "AND"

    cursor = self.__getCursor()

    # sql = self.__joinWhere(kwargs["sql"], kwargs["params"], kwargs["join"])

    sql = self.__joinWhere(**kwargs)

    cursor.execute(sql, tuple(kwargs["params"].values()))

    result = cursor.fetchall() # fetchone是一条记录, fetchall 所有记录

    return len(result) if result else 0

    # def insert(self,table,data):

    def insert(self, **kwargs):

    """新增一条记录

    table: 表名

    data: dict 插入的数据

    """

    fields = ','.join('`'+k+'`' for k in kwargs["data"].keys())

    values = ','.join(("%s", ) * len(kwargs["data"]))

    sql = 'INSERT INTO `%s` (%s) VALUES (%s)' % (kwargs["table"], fields, values)

    cursor = self.__getCursor()

    cursor.execute(sql, tuple(kwargs["data"].values()))

    insert_id = cursor.lastrowid

    self._conn.commit()

    return insert_id

    # def updateByAttr(self,table,data,params={},join='AND'):

    def updateByAttr(self, **kwargs):

    # """更新数据"""

    if kwargs.get("params", 0) == 0:

    kwargs["params"] = {}

    if kwargs.get("join", 0) == 0:

    kwargs["join"] = "AND"

    fields = ','.join('`' + k + '`=%s' for k in kwargs["data"].keys())

    values = list(kwargs["data"].values())

    values.extend(list(kwargs["params"].values()))

    sql = "UPDATE `%s` SET %s " % (kwargs["table"], fields)

    kwargs["sql"] = sql

    sql = self.__joinWhere(**kwargs)

    cursor = self.__getCursor()

    cursor.execute(sql, tuple(values))

    self._conn.commit()

    return cursor.rowcount

    # def updateByPk(self,table,data,id,pk='id'):

    def updateByPk(self, **kwargs):

    """根据主键更新,默认是id为主键"""

    return self.updateByAttr(**kwargs)

    # def deleteByAttr(self,table,params={},join='AND'):

    def deleteByAttr(self, **kwargs):

    """删除数据"""

    if kwargs.get("params", 0) == 0:

    kwargs["params"] = {}

    if kwargs.get("join", 0) == 0:

    kwargs["join"] = "AND"

    # fields = ','.join('`'+k+'`=%s' for k in kwargs["params"].keys())

    sql = "DELETE FROM `%s` " % kwargs["table"]

    kwargs["sql"] = sql

    # sql = self.__joinWhere(sql, kwargs["params"], kwargs["join"])

    sql = self.__joinWhere(**kwargs)

    cursor = self.__getCursor()

    cursor.execute(sql, tuple(kwargs["params"].values()))

    self._conn.commit()

    return cursor.rowcount

    # def deleteByPk(self,table,id,pk='id'):

    def deleteByPk(self, **kwargs):

    """根据主键删除,默认是id为主键"""

    return self.deleteByAttr(**kwargs)

    # def findByAttr(self,table,criteria = {}):

    def findByAttr(self, **kwargs):

    """根據條件查找一條記錄"""

    return self.__query(**kwargs)

    # def findByPk(self,table,id,pk='id'):

    def findByPk(self, **kwargs):

    return self.findByAttr(**kwargs)

    # def findAllByAttr(self,table,criteria={}, whole=true):

    def findAllByAttr(self, **kwargs):

    """根據條件查找記錄"""

    return self.__query(**kwargs)

    # def count(self,table,params={},join='AND'):

    def count(self, **kwargs):

    """根据条件统计行数"""

    if kwargs.get("join", 0) == 0: kwargs["join"] = "AND"

    sql = 'SELECT COUNT(*) FROM `%s`' % kwargs["table"]

    # sql = self.__joinWhere(sql, kwargs["params"], kwargs["join"])

    kwargs["sql"] = sql

    sql = self.__joinWhere(**kwargs)

    cursor = self.__getCursor()

    cursor.execute(sql, tuple(kwargs["params"].values()))

    result = cursor.fetchone()

    return result[0] if result else 0

    # def exist(self,table,params={},join='AND'):

    def exist(self, **kwargs):

    """判断是否存在"""

    return self.count(**kwargs) > 0

    def close(self):

    """关闭游标和数据库连接"""

    if self.__cursor is not None:

    self.__cursor.close()

    self._conn.close()

    def __getCursor(self):

    """获取游标"""

    if self.__cursor is None:

    self.__cursor = self._conn.cursor()

    return self.__cursor

    # def __joinWhere(self,sql,params,join):

    def __joinWhere(self, **kwargs):

    """转换params为where连接语句"""

    if kwargs["params"]:

    keys,_keys = self.__tParams(**kwargs)

    where = ' AND '.join(k+'='+_k for k,_k in zip(keys,_keys)) if kwargs["join"] == 'AND' else ' OR '.join(k+'='+_k for k,_k in zip(keys,_keys))

    kwargs["sql"]+=' WHERE ' + where

    return kwargs["sql"]

    # def __tParams(self,params):

    def __tParams(self, **kwargs):

    keys = ['`'+k+'`' for k in kwargs["params"].keys()]

    _keys = ['%s' for k in kwargs["params"].keys()]

    return keys,_keys

    # def __query(self,table,criteria,whole=False):

    def __query(self, **kwargs):

    if kwargs.get("whole", False) == False or kwargs["whole"] is not True:

    kwargs["whole"] = False

    kwargs["criteria"]['limit'] = 1

    # sql = self.__contact_sql(kwargs["table"], kwargs["criteria"])

    sql = self.__contact_sql(**kwargs)

    cursor = self.__getCursor()

    cursor.execute(sql)

    rows = cursor.fetchall() if kwargs["whole"] else cursor.fetchone()

    result = [dict(zip(cursor.column_names, row)) for row in rows] if kwargs["whole"] else dict(zip(cursor.column_names, rows)) if rows else None

    return result

    # def __contact_sql(self,table,criteria):

    def __contact_sql(self, **kwargs):

    sql = 'SELECT '

    if kwargs["criteria"] and type(kwargs["criteria"]) is dict:

    #select fields

    if 'select' in kwargs["criteria"]:

    fields = kwargs["criteria"]['select'].split(',')

    sql+= ','.join('`'+field+'`' for field in fields)

    else:

    sql+=' * '

    #table

    sql+=' FROM `%s`'% kwargs["table"]

    #where

    if 'where' in kwargs["criteria"]:

    sql+=' WHERE '+ kwargs["criteria"]['where']

    #group by

    if 'group' in kwargs["criteria"]:

    sql+=' GROUP BY '+ kwargs["criteria"]['group']

    #having

    if 'having' in kwargs["criteria"]:

    sql+=' HAVING '+ kwargs["criteria"]['having']

    #order by

    if 'order' in kwargs["criteria"]:

    sql+=' ORDER BY '+ kwargs["criteria"]['order']

    #limit

    if 'limit' in kwargs["criteria"]:

    sql+=' LIMIT '+ str(kwargs["criteria"]['limit'])

    #offset

    if 'offset' in kwargs["criteria"]:

    sql+=' OFFSET '+ str(kwargs["criteria"]['offset'])

    else:

    sql+=' * FROM `%s`'% kwargs["table"]

    return sql

    def findKeySql(self, key ,**kwargs):

    print("-----------")

    print(key)

    sqlOperate = {

    Const.COUNT: lambda: self.count(**kwargs),

    Const.COUNT_BY_SQL: lambda: self.countBySql(**kwargs),

    Const.DELETE_BY_ATTR: lambda: self.deleteByAttr(**kwargs),

    Const.EXIST: lambda: self.exist(**kwargs),

    Const.FIND_ALL_BY_ATTR: lambda: self.findAllByAttr(**kwargs),

    Const.INSERT: lambda: self.insert(**kwargs),

    Const.FIND_BY_ATTR: lambda: self.findByAttr(**kwargs),

    Const.UPDATE_BY_ATTR: lambda: self.updateByAttr(**kwargs),

    Const.FIND_BY_SQL: lambda: self.findBySql(**kwargs)

    }

    return sqlOperate[key]()

    if __name__ == "__main__":

    mysqlet = MySQLet(host="127.0.0.1", user="root", password="", charset="utf8", database="userinfo", port=3306)

    # 根据字段统计count, join>>AND,OR,可以不传,默认为AND

    # print(mysqlet.findKeySql(Const.COUNT, table="info", params={"id": "11", "name": "666"}, join="OR"))

    # # 自定义sql语句统计count

    # print(mysqlet.findKeySql(Const.COUNT_BY_SQL, sql="select * from info", params={"name": "666"}, join="AND"))

    # #插入数据

    # print(mysqlet.findKeySql(Const.INSERT, table="info", data={"name":"333", "pwd": "111"}))

    测试结果分析

    现在只是简单的记录下结果,后续优化

    #{'method': 'post', 'success': 32, 'stress': 2, 'failed': 0, 'url': '/mockjs/11463/login', 'name': '登陆', 'sum': 16}

    '''

    sum 表示此接口有16组参数

    stress: 表示每组参数压测两次

    method: 请求方法

    success: 成功请求次数

    failed:失败请求次数

    url:请求的网址

    name:接口名字

    '''

    其他

    后面会简单把结果记录到 excel 中,发邮件

    最终的目的是想做成平台化,这里估计短时间内无法完成

    展开全文
  • 安全生产模拟考试一点通:R1快开门式压力容器操作最新解析是安全生产模拟考试一点通总题库中生成的一套R1快开门式压力容器操作证考试,安全生产模拟考试一点通上R1快开门式压力容器操作作业手机同步练习。...

    题库来源:安全生产模拟考试一点通公众号小程序

    安全生产模拟考试一点通:R1快开门式压力容器操作最新解析是安全生产模拟考试一点通总题库中生成的一套R1快开门式压力容器操作证考试,安全生产模拟考试一点通上R1快开门式压力容器操作作业手机同步练习。2021年R1快开门式压力容器操作最新解析及R1快开门式压力容器操作证考试

    1、【多选题】固定式压力容器下列部件属于主要受压元件:()。( AB )

    A、筒体;

    B、封头;

    C、螺栓;

    D、压力管道和法兰

    2、【多选题】下列哪些条件能满足《特种设备作业人员证》复审申请要求?()( ABC )

    A、持证人年龄64周岁

    B、持证期间,无违章作业,未发生责任事故

    C、持证期间,《特种设备作业人员证》的聘用记录中所从事持证项目的作业时间连续中断未超过1年

    D、持证期间,《特种设备作业人员证》的聘用记录中所从事持证项目的作业时间中断超过1年

    3、【多选题】根据TSG21-2016《固定式压力容器安全技术监察规程》规定,下列哪些属于()安全附件。( ACD )

    A、安全阀

    B、压力表

    C、爆破片

    D、安全联锁装置

    4、【多选题】按安全附件的功能作用,快开门式压力容器安全附件可以分为()三类。( ACD )

    A、泄压装置

    B、计量显示装置

    C、报警装置

    D、控制装置

    5、【多选题】下列哪些是特种设备使用安全节能管理制度的内容?()( ABCD )

    A、特种设备安全管理机构(需要设置时)和相关人员岗位职责

    B、特种设备经常性维护保养、定期自行检查和有关记录制度

    C、特种设备使用登记、定期检验、锅炉能效测试申请实施管理制度

    D、特种设备隐患排查治理制度

    6、【多选题】压力容器运行中的工艺条件检查主要检查()。( ABC )

    A、工作压力;

    B、工作温度;

    C、液位;

    D、有无腐蚀

    7、【多选题】《特种设备安全法》规定,特种设备检验、检测机构及其检验、检测人员应当依法为特种设备生产、经营、使用单位提供()的检验、检测服务。( ACDE )

    A、安全

    B、及时

    C、可靠

    D、便捷

    E、诚信

    8、【多选题】快开门式压力容器的疲劳破坏最容易发生在()。( ABC )

    A、容器接管根部

    B、开孔处

    C、结构不连续处

    D、封头

    E、筒体

    9、【多选题】卡箍式快开门具有开启速度快的优点,密封性能不佳,可靠性较()差,安全连锁实现较为()。( BC )

    A、好

    B、差

    C、容易

    D、困难

    10、【多选题】快开门式压力容器操作人员在操作中应该做到()。( ABCDE )

    A、熟悉本岗位工艺流程

    B、熟悉容器的结构、类别、主要技术参数和性能

    C、严格按照操作规程操作

    D、掌握处理一般事故的方法

    E、如实填写有关操作记录

    11、【多选题】关于快开门式压力容器使用管理方面,给容器安全使用带来事故隐患的有:( ABCD )

    A、私自拆除快开门安全联锁

    B、发现釜门变形,使用单位可以自行修复,对釜门实施焊接

    C、安全附件失灵

    D、操作人员未经专业培训,未持证上岗

    12、【多选题】根据《大容规》的规定,用()连接的不属于快开门式压力容器。( AB )

    A、螺栓

    B、活节螺栓

    C、快速开关盖装置

    13、【多选题】下列哪些情况可以吊销操作人员资格证书?( ACD )

    A、不履行岗位职责造成事故

    B、不服从领导安排造成事故

    C、违反操作规程造成事故

    D、违反有关安全规章制度造成事故

    14、【多选题】微机控制联锁装置通过微机进行(),自动控制开闭快开门。( ABCDE )

    A、信息存储

    B、数据处理

    C、数值运算

    D、过程控制

    E、数据传输

    15、【多选题】安全联锁装置是容器辅助的安全附件之一,与容器的()互为补充,形成安全保护系统。( ABC )

    A、压力表

    B、安全阀

    C、温度计

    D、液位计

    16、【多选题】密封元件按密封机理、密封结构分为()密封。( AB )

    A、强制式(通过拧紧螺栓压紧);

    B、自紧密封(靠容器内压力压紧)

    17、【多选题】阀门按驱动方式分为()。( ABC )

    A、手动阀;

    B、动力驱动阀;

    C、自动阀;

    D、安全阀。

    18、【多选题】连接联锁装置各个元件,构成完整的联锁系统,实现联锁控制功能和同步报警功能的系统主要有()等。( ABCDE )

    A、电路控制系统;

    B、液(气)路系统

    C、控制箱

    D、电磁继电器;

    E、声光报警器

    19、【多选题】控制快开门关闭到位后,才能升压的进气阀,主要有()等。( ABC )

    A、电磁阀;

    B、电动阀;

    C、气动隔膜阀

    20、【多选题】下列部件属于弹簧式安全阀的部件:()。( ABCD )

    A、阀座;

    B、阀芯;

    C、调整螺丝;

    D、弹簧;

    E、加压装置

    21、【多选题】快开门式压力容器按其结构型式分为()三种大类。( ABD )

    A、球形容器

    B、圆形截面容器

    C、塔形容器

    D、非圆形截面容器

    22、【多选题】《特种设备使用管理规则》规定,特种设备管理制度包括()。( ABCD )

    A、特种设备安全管理机构(需要设置时)和相关人员岗位职责;

    B、特种设备经常性维护保养、定期自行检查和有关记录制度;

    C、特种设备安全管理人员与作业人员管理和培训制度;

    D、特种设备而事故报告和处理制度。

    23、【多选题】快开门式压力容器用钢材回火处理的主要目的是()。( ABC )

    A、提高材料性能

    B、消除残余应力

    C、获得所需要的组织

    D、改善材料的焊接性能

    24、【多选题】对快开门式压力容器的使用要求要求是:采用快速开关盖装置,同时还要()。( ABC )

    A、抗疲劳性能好

    B、物料装卸方便

    C、设置安全联锁装置

    25、【多选题】根据快开门式压力容器的工作特点,判断下列情况中容易造成快开门式压力容器发生人身伤亡事故的是()。( CDE )

    A、容器长期在最高工作压力下运行

    B、容器长期在高温环境下运行

    C、容器端盖经常开启

    D、容器端盖未完全闭合就升压

    E、容器在卸压未尽前打开端盖

    26、【多选题】压力容器的停止运行包括()。( AB )

    A、正常停止运行;

    B、紧急停止运行;

    C、长期停运

    27、【多选题】对快开门式压力容器的使用要求要求是:()。( ABCD )

    A、采用快速开关盖装置

    B、抗疲劳性能好

    C、物料装卸方便

    D、设置安全联锁装置。

    28、【多选题】对快开门式压力容器的使用要求要求是:采用快速开关盖装置,物料装卸方便,同时还要()。( AB )

    A、抗疲劳性能好

    B、设置安全联锁装置

    29、【多选题】压力容器点腐蚀的发生一般与容器的()有关。( AC )

    A、材料

    B、载荷

    C、介质

    D、流速

    30、【多选题】材料的基本力学性能主要包括()等。( ABCD )

    A、强度

    B、塑性

    C、硬度

    D、韧性

    E、可焊性

    F、腐蚀性

    31、【多选题】下列部件中,()属于压力容器的安全附件及仪表。( ACEF )

    A、安全阀

    B、放空阀

    C、压力表

    D、法兰

    E、液面计

    F、温度计

    32、【单选题】《中华人民共和国特种设备安全法》规定:特种设备使用单位应当按照安全技术规范的要求,在检验合格有效期届满前()个月向特种设备检验机构提出定期检验要求。( A )

    A、1

    B、2

    C、3

    D、6

    33、【单选题】《特种设备安全法》规定,国家()投保特种设备安全责任保险。( A )

    A、鼓励

    B、推荐

    C、强制

    34、【单选题】《固定容规》规定:以水为介质产生蒸汽的压力容器,应当做好水质管理与监督,没有可靠的水处理措施的()投入运行。( B )

    A、一般不得;

    B、不得;

    C、不应

    35、【单选题】《特种设备安全法》规定,组织事故调查的部门应当将事故调查报告报本级人民政府,并报上一级人民政府负责()的部门备案。( C )

    A、安全生产监督管理

    B、事故单位所属行业主管

    C、特种设备安全监督管理

    36、【单选题】液面计上下标注的警戒红线表示容器()。( B )

    A、危险液位

    B、最高液位和最低液位

    C、警告标识

    37、【单选题】辐射式温度计是利用物质()的原理显示温度变化。( A )

    A、热辐射

    B、受热膨胀

    C、产生的热电势

    D、热电效应

    38、【单选题】热点偶式温度计是利用不同的材料温度不同()的原理显示温度的变化。( C )

    A、热辐射

    B、受热膨胀

    C、产生的热电势

    D、热电效应

    39、【单选题】下列压力容器封头形式中,受力状况最好是()。( A )

    A、球形封头

    B、碟形封头

    C、平板封头

    D、椭圆封头

    40、【单选题】压力表的弹簧弯管是根据弹簧弯管在容器内部压力作用下发生()的原理制成的。( B )

    A、挤压;

    B、位移;

    C、震动

    41、【单选题】二次爆炸是指盛装可燃介质的压力容器爆炸后,介质外泄扩散与空气混合达到(),遇火源而发生的器外燃烧爆炸。( B )

    A、一定混合时间;

    B、爆炸极限;

    C、一定扩散范围

    42、【单选题】《固定容规》规定:压力容器()时,试验单位的安全管理部门应当派人进行现场监督。( A )

    A、气压;

    B、水压试验;

    C、气密性试验

    43、【单选题】按照《固定容规》规定:使用满足下列条件的()单位,可以向国家质检总局提出应用基于风险评估(RBI)。( C )

    A、较大容器的使用;

    B、成套装置的使用;

    C、大型成套装置的使用

    44、【单选题】快开门式压力容器的操作压力、最高工作压力、设计压力是指()。( A )

    A、表压力

    B、绝对压力

    C、标准大气压

    45、【单选题】温度计是()的安全装置。( B )

    A、控制温度

    B、测量温度

    C、显示温度

    46、【单选题】《特种设备事故报告和调查处理规定》规定,发生特种设备事故后,事故现场有关人员应当立即向()报告。( A )

    A、事故发生单位负责人

    B、县以上质量技术监督部门

    C、安全生产监察部门

    47、【单选题】《中华人民共和国特种设备安全法》规定,特种设备安全管理人员、检测人员和作业人员应当按照国家有关规定取得(),方可从事相关工作。( B )

    A、合格成绩

    B、相应资格

    C、行业认可

    48、【单选题】各种类型的热交换器是通过()实现冷热交换的。( C )

    A、直接加热

    B、电热

    C、器壁或管壁与介质的温度差

    49、【单选题】确定介质是否是易燃介质的标准:()。( A )

    A、与空气混合后的爆炸下限小于10%,或爆炸上限和下限之差值大于等于20%;

    B、会发生燃烧的介质

    50、【单选题】《条例》规定:特种设备的安全管理人员在进行经常性检查中,如发现情况紧急时()决定停止使用压力容器。( B )

    A、必须

    B、可以;

    C、尽快;

    D、立即

    51、【单选题】凡符合登记发证的压力容器在投入使用前或投用后()内,应当向特种设备安全监督管理部门登记。( C )

    A、10日;

    B、20日;

    C、30日

    52、【单选题】对于《特种设备作业人员证》考试要求,哪一项是正确的?()( A )

    A、单项考试科目不合格者,1年内可以向原考试机构申请补考1次

    B、单项考试科目不合格者,1年内可以向原考试机构申请补考2次

    C、单项考试科目不合格者,2年内可以向原考试机构申请补考任意次

    D、单项考试科目不合格者,应当向发证机关重新提出考核申请。

    53、【单选题】当快开门达到预定关闭部位方能升压运行的联锁功能是:余压指示电磁阀呈()状态,容器无法加压运行。( A )

    A、开启

    B、关闭

    54、【判断题】安全阀超过校验有效期,使用单位应当限期改正并且采取有效措施确保改正期间的安全,否则暂停该压力容器的使用。( √ )

    55、【判断题】根据TSG21-2016《固定式压力容器安全技术监察规程》规定:安全附件的检查包括对安全阀、爆破片装置、安全联锁装置等的检查。( √ )

    56、【判断题】压力容器发生化学爆炸时,通常会发生粉碎性破坏。()( √ )

    57、【判断题】()空气是一种容易压缩,但不能液化的气体。( × )

    58、【判断题】长期带压使用快开门式压力容器可以采用在线校验的手段对安全阀进行年检。( √ )

    59、【判断题】止回阀在安装时必须按箭头的指标方向与介质流动方向一致。()( √ )

    60、【判断题】《固定式压力容器安全技术监察规程》规定,压力容器耐压试验过程中出现泄漏应该立即带压紧固螺栓,防止出现泄漏现象。( × )

    61、【判断题】纯净的蒸汽无色、无味、无毒。()( √ )

    62、【判断题】杠杆式安全阀属于平衡式安全阀。()( × )

    63、【判断题】快开门式压力容器操作人员必须取得快开门式压力容器操作证才能操作该类压力容器。( √ )

    64、【判断题】《中华人民共和国特种设备安全法》规定,特种设备检验、检测机构的检验、检测人员可以同时在两个以上检验、检测机构执业;变更执业机构的,应当依法办理变更手续。()( × )

    65、【判断题】《中华人民共和国特种设备安全法》规定,特种设备行业协会应当加强行业自律,推进行业诚信体系建设,提高特种设备安全管理水平。()( √ )

    66、【判断题】快开门式压力容器在高温空气中的氧化属于化学腐蚀。( √ )

    67、【判断题】快开门式压力容器停止运行时,操作人员时应快速打开或关闭阀门。( × )

    68、【判断题】奥氏体型耐酸不锈钢常用于腐蚀性较强的介质中。()( √ )

    69、【判断题】快开门式压力容器具体的结构型式是根据容器的作用、工艺要求等因素确定的。( √ )

    70、【判断题】物质的化学反应过程有新物质生成,物质组成和化学性质都发生变化。()( √ )

    71、【判断题】所有在用压力容器上都必须安装安全阀,防止超压发生事故。()( × )

    72、【判断题】当容器内压力降至0.003Mpa以下时,零压开关会将信号传至电控柜,“釜内有压”指示灯灭,“釜内无压”指示灯亮,同时手动(或电动)减速机控制线路解锁,操作人员可以进行开门操作。( √ )

    73、【判断题】()《特种设备安全法》规定,特种设备安全工作应当坚持安全第一、预防为主、综合治理的原则。( × )

    74、【判断题】在空气中能够抵抗腐蚀的钢称为不锈钢。()( √ )

    75、【判断题】快开门式压力容器运行时应保持安全距离,不得对设备进行任何检查。( × )

    76、【判断题】压力容器的液面计上应该标注安全液位警戒线。( √ )

    77、【判断题】如爆破片串联在安全阀出口时,爆破片的动作压力应低于安全阀整定压力。()( × )

    78、【判断题】压力容器上常用阀门有:闸阀、截止阀、节流阀、止回阀、减压阀、疏水器、安全阀等。()( √ )

    79、【判断题】快开门式压力容器属于III类压力容器。( × )

    80、【判断题】压力表与固定式压力容器之间,应装设三通旋塞或针形阀,三通旋塞或者针形阀上应有开启标记和锁紧装置,并且不得连接其他用途的任何配件或者接管。()( √ )

    81、【判断题】《特种设备安全监察条例》中,特种设备的事故的级别是完全按所造成的人员死亡人数确定的。( × )

    82、【判断题】对安全泄放量较小和要求压力平稳的固定式压力容器,宜采用全启式安全阀。()( × )

    83、【判断题】快开门式压力容器的开门装置启闭频繁、方便快捷,同时风险较大。( √ )

    84、【判断题】蒸压釜限位开关因设在釜门附近,在操作釜门时容易碰损限位开关,容易造成信号失灵。( √ )

    85、【判断题】直接作用式安全联锁装置是依靠容器内压力实现联锁动作的,具有整洁灵活可靠、成本低、寿命长和可靠性好等优点( √ )

    86、【判断题】安全联锁装置采用微机控制,由微机进行信息存储、数据处理、数值运算、过程控制和数据传输,自动控制开闭快开门,操作人员懂微机基本知识就行了。( × )

    87、【判断题】正常情况下,压力开关检测并判断容器内部压力后发出信号:有余压时,联锁插销不能脱开,快开门不允许动作。( √ )

    88、【判断题】正常情况下,行程开关检测并判断快开门关闭到位时,进气自动阀才能开启,才可以进、升压。( √ )

    89、【判断题】平移式快开门开启、关闭平稳且机械化程度较高。( √ )

    90、【判断题】最高允许工作压力是指定温度下,容器顶部所允许承受的最大表压力。该压力是根据容器受压元件的有效厚度,考虑该元件承受所有载荷而计算所得,且取其最小值。( √ )

    91、【判断题】压力容器只应当承受内压。()( × )

    92、【判断题】金属材料、非金属材料都可以用于压力容器的制造。()( √ )

    93、【判断题】安全阀属于超压泄放类安全附件。()( √ )

    94、【判断题】《特种设备安全管理和作业人员证》复审只需进行理论考试。( × )

    95、【判断题】申请人对考试机构答复结果有异议的,可以电话向发证机关提出申诉。( × )

    96、【判断题】压力容器操作人员未经专业培训发证上岗操作,是导致压力容器事故的重要原因。()( √ )

    97、【判断题】接管、紧固件损坏,难以保证压力容器安全运行时,应紧急停运。()( √ )

    98、【判断题】使用快开门式压力容器之前须检查安全联锁装置运行是否正常。( √ )

    99、【判断题】灭菌器主要用于医院、实验室和制药厂。( √ )

    100、【判断题】压力容器运行中,操作人员应检查设备的保温层、支座、支撑、紧固件是否完好,基础有无下沉、倾斜及阀门启、闭情况。()( √ )

    支持全国各地区精准R1快开门式压力容器操作考试试题,支持安全资格证,特种作业操作证,职业技能鉴定等工种题库练习。

    展开全文
  • 因为项目需要,接触到了两款压力测试工具,对其进行总结和学习。 1) LTP 简介: LTP套件是由 Linux Test Project 所开发的一套系统测试套件。它基于系统资源的利用率统计开发了一个测试的组合,为系统提供足够的...

    因为项目需要,接触到了两款压力测试工具,对其进行总结和学习。

    1) LTP

    简介:

        LTP套件是由 Linux Test Project 所开发的一套系统测试套件。它基于系统资源的利用率统计开发了一个测试的组合,为系统提供足够的压力。

        通过压力测试来判断系统的稳定性和可靠性。

        压力测试是一种破坏性的测试,即系统在非正常的、超负荷的条件下的运行情况 。用来评估在超越最大负载的情况下系统将如何运行,是系统在正常的情况下对某种负载强度的承受能力的考验 。

        使用LTP测试套件对Linux操作系统进行超长时间的测试,重点在于Linux用户环境相关的工作负荷。而并不是致力于证明缺陷。

    下载链接

    https://github.com/linux-test-project/ltp/releases/tag/20200120

    压力测试

           可以验证产品在系统高使用率时的健壮性。作为runalltests.sh的补充,特别设计了一个名为ltpstress.sh的测试场景,在使用网络与内存管理的同时并行地运行大范围的内核组件,并在测试系统上生成高压力负荷。

           ltpstress.sh也是LTP测试套件的一部分。这个脚本并行地运行相似的测试用例,串行地运行不同的测试用例,这样做是为了避免由于同时访问同一资源或者互相干扰而引起的间歇性故障。

    默认地,这个脚本执行:

    - NFS 压力测试。

    - 内存管理压力测试。

    - 文件系统压力测试。

    - 数学 (浮点) 测试。

    - 多线程压力测试。

    - 硬盘 I/O 测试。

    - IPC (pipeio, semaphore) 测试。

    - 系统调用功能的验证测试。

    - 网络压力测试。

    LTP工作组在设计Linux 内核压力测试脚本 ltpstress.sh 时使用了这一设计方法,为给系统提供足够的压力,LTP工作组对这个组合测试进行了分析,以确定 Linux 内核的哪些部分在测试执行中得到了使用。然后,修改了组合测试,在保持期望的高强度系统压力的同时提高代码覆盖率的百分比。最终得到的压力测试涵盖了Linux 内核的足够多部分,有助于稳定性声明,并且有系统使用情况和内核代码覆盖情况的数据来支持它。

    测试当中的注意项

    1 测试之前所有选定的测试系统的硬件配置尽可能相同。去掉额外的硬件以减少潜在的硬件故障。在映像安装过程中选择最低的安全选项。预留至少 2 GB 的硬盘空间以保存 top 数据文件和 LTP 日志文件。

    比如:不建议插入U盘测试,可能会带来干扰;(实测在此情况下出现了死机,但是不知道是不是必然联系)。

    2 在测试期间系统不要受到干扰。偶尔访问一下系统以确认测试仍在进行是可以接受的。确认的手段包括使用 ps 命令、检查 top 数据和检查 LTP 日志数据。

    源安装包目录列表

    doc: 该目录是说明文件和帮助文档的所在地,这个目录中对LTP的内容和每个工具都有详细的说明

    testscripts: 该目录中存储的是可执行的测试脚本,不同方面的测试脚本的集合

    testcases: 该目录存储了所有LTP测试套件中所使用的测试用例的源码

    runtest: 该目录中的每个文件都是要执行的测试用例的命令集合,每个文件针对测试的不同方面

    (用于链接testscripts内的测试脚本和testcases测试项目)

    include: LTP测试套件的头文件目录,定义了LTP自身的数据结构和函数结构

    lib: LTP测试套件运行时自身需要的库文件,定义了LTP自身的各种函数

    bin: 存放LTP测试的一些辅助脚本

    results: 测试结果默认存储目录

    output: 测试日志默认存储目录

    share: 脚本使用说明目录

    pan: 该目录存储的是LTP测试套件的测试驱动程序pan

    操作步骤

    1、从上述链接中下载ltp的源码

    需要注意的是最新的版本20200120 testscripts目录下没有上文提到的ltpstress.sh;可能是版本升级之后的测试方法不同。实测在20180525版本中有脚本ltpstress.sh。

    2、解压、安装

    进入解压后的脚本目录,执行./ltpstress.sh,执行压力测试。(需要添加额外的两个服务)

    也有版本是将此部分服务添加到ltp压缩包中,通过make install 安装的。

    2)stress 

    Stress是一款Posix系统下生成Cpu/Menory/IO/Disk负载的工具。

    1. 测试CPU负荷

      输入命令:stress -c 4 -t 10

      增加4个cpu进程,处理sqrt()函数函数,以提高系统CPU负荷,测试10s

    2. 内存测试

      输入命令:stress -i 4 –vm 10 –vm-bytes 1G –vm-hang 100 –timeout 100s

      新增4个io进程,10个内存分配进程,每次分配大小1G,分配后不释放,测试100S

    3. 磁盘I/O测试

      输入命令:stress -d 1 –hdd-bytes 3G

      新增1个写进程,每次写3G文件块

    4. 硬盘测试(不删除)

      输入命令:stress -i 1 -d 10 –hdd-bytes 3G -hdd-noclean

      新增1个IO进程,10个写进程,每次写入3G文件块,且不清除,会逐步将硬盘耗尽

    3)区别

    1、ltpstress在做压力测试的时候,使用默认的脚本ltpstress.sh,CPU和内存会保持100%(满负荷)的压力测试;

          可以通过修改指定的内存参数,来降低CPU和内存的使用率,一般情况下也不这么使用。

          stress可以做满负荷的CPU测试,如4核,则 -c 4 CPU满负荷测试。如果要保证CPU占用率60以上,则可以设置-c 3(默认4核的情况下)。

          因此在做单项CPU压力测试的时候,可以选择stress,且容易控制CPU的占用率。

    2、 stress可以做内存、硬盘、CPU的测试(或组合测试);全面系统长时间的压力测试选择LTP。

     

    转自https://blog.csdn.net/weixin_42121713/article/details/105838481

     

    展开全文
  • CSV是唯一支持的格式,结果以逗号分隔各个指标项。 -o Output type. If none provided, a summary is printed. “csv” is the only supported alternative. Dumps the response metrics in comma-separated values ...
  • 压测,即压力测试,是确立系统稳定性的一种测试方法,通常在系统正常运作范围之外进行,以考察其功能极限和隐患。主要检测服务器的承受能力,包括用户承受能力(多少用户同时玩基本不影响质量)、流量承受等。压测的...
  • 用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。 它可以用于测试静态和动态资源,例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库、FTP服务器, 等等。JMet...
  • 主要介绍下kafka的producer配置参数,只取了其中的一部分常用的,后续的有时间,也会补充一些,更多的详细参数,可以参考《kafka官网》,参数的内容,主要是选取《apache ka...
  • MySQL参数调整

    2021-01-19 04:19:38
    1MySQL参数调整1.1tx_isolation事务参数1.1.1事务的特征事务具有四个特性:原子性(Atomiocity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),这四个特性简称ACID特性。原子性:事务是数据库的逻辑...
  • 今天一同事问我有木有比较靠谱的mysql压力测试工具可用。其实mysql自带就有一个叫mysqlslap的压力测试工具,还是模拟的不错的。下面举 例说说。mysqlslap是从5.1.4版开始的一个MySQL官方提供的压力测试工具。通过...
  • 虽然学习过TCP的三次握手与四次挥手,但是对于Linux服务器的这方面参数所知甚少。故在网上搜集了一下,整理如下:net.ipv4.tcp_syncookies = 1表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可...
  • 在开发接口或者功能点完成后,就需要对接口或功能点压力测试,测试出接口的极限以应对较大并发,举一个最直接的例子:淘宝双十一购物节,2018年淘宝交易创建峰值达到49.1万笔/秒,而在双十一之前淘宝都要对系统进行...
  • 3压力支持通气(PSV) 是一种辅助通气方式,即在有自主呼吸的前提下,每次吸气都接受一定水平的压力支持,以辅助和增强病人的吸气深度和吸入气量。 4呼气末正压通气(PEEP) 指通气机在吸气相产生正压,将气体压入肺内...
  • 1、 测试目标地址:http://www.cnblogs.com/2、 1秒内有100个用户同时访问,看性能如何3、 步骤线程组、http请求、查看结果树、聚合报告添加http请求如下:继续填入参数格式:服务器或名称IP:www.cnblogs.com 端口...
  • 怎么看服务器详细配置参数 内容精选换一换代码迁移工具进行代码迁移时,需要调用Linux下的rpm、deb等命令才能完成扫描和迁移相关任务,这些命令和逻辑必须在后端Linux运行。IDE插件只支持以Web模式使用root用户安装...
  • mysql 压力测试

    2021-02-02 06:20:29
    mysql 压力测试sysbench支持的测试模式:1、CPU运算性能2、磁盘IO性能3、调度程序性能4、内存分配及传输速度5、POSIX线程性能6、数据库性能(OLTP基准测试)目前sysbench主要支持 mysql,drizzle,pgsql,oracle 等几种...
  • 线程池的参数应该怎样设置呢?相信对于很多的人来说这也是一个比较难的问题,下面就让我们一起来解决一下,究竟应该如何设置线程池的参数才是最合理的吧!首先在设置参数的时候,有以下的几点是我们需要考虑到的!1、...
  • 文档介绍:深信服超融合平台招标参数文档使用说明:1.招标参数分:“技术功能参数要求”、“产品及厂商资质要求”、“超融合一体机参数要求”三部分;2.其中技术功能参数包含了服务器虚拟化aSV、存储虚拟化aSAN、的技术...
  • R1快开门式压力容器操作考试考前必练!安全生产模拟考试一点通每个月更新R1快开门式压力容器操作考试题题目及答案!多做几遍,其实通过R1快开门式压力容器操作试题及解析很简单。 1、【多选题】弹簧式安全阀被...
  • psi与kpa换算(smc数显压力表设定方法)

    千次阅读 2021-01-16 18:00:22
    磅每平方英寸(psi)是一个英制的压力(压强)单位,定义为每平方英寸面积承受1磅重量所产生的压力,psi为pound per square inch或pound-force per square inch 的缩.1psi=6.895KPa=0.00689476MPa ,1bar≈14.5psi。...
  • go 实现压力测试

    2021-10-25 15:10:11
    go-stress-testing 是go语言实现的简单压测工具,源码开源、支持二次开发,可以压测http、webSocket请求,使用协程模拟单个用户,可以更高效的利用CPU资源。 项目地址:1.Git下载...
  • PID控制器参数的工程整定,各种调节系统中P.I.D参数经验数据以下可参照: 温度T: P=20~60%,T=180~600s,D=3-180s 压力P: P=30~70%,T=24~180s, 液位L: P=20~80%,T=60~300s, 流量L: P=40~100%,T=6~60s。 常用口诀:...
  • 服务端压力测试分享

    2021-06-04 09:41:33
    压测的目的压力测试是对系统不断施加压力,来获得系统最大服务能力的测试。一般而言,只有在系统基础功能测试验证完成、系统趋于稳定的情况下,才会进行压力测试。目的:1.当负载逐渐增加时,观察系统各项性能指标的...
  • 本篇从不同的表空间特性谈起,说明使用的参数特性。下面是一个使用命令行创建表空间的实例。SQL> create tablespace tradway datafile '/u01/oradata/WILSON/datafile/trad.dbf' size 100m ...
  • mysql压力测试工具

    2021-01-21 11:15:59
    mysql自带就有一个叫mysqlslap的压力测试工具,还是模拟的不错的。下面举例说说。mysqlslap是从5.1.4版开始的一个MySQL官方提供的压力测试工具。通过模拟多个并发客户端访问MySQL来执行压力测试,同时详细的提供了...
  • thread_concurrency = 8 #该参数取值为服务器逻辑CPU数量*2,在本例中,服务器有2颗物理CPU,而每颗物理CPU又支持H.T超线程,所以实际取值为4*2=8;这个目前也是双四核主流服务器配置。 skip-networking #开启该选项...
  • JMeter压力测试

    2020-12-28 22:29:29
    临时客串了下性能测试人员,对Web页面进行了压力测试,做个记录,方便以后的查阅。先用了阿帕奇的JMeter进行的压力测试,后来又使用了loadrunner。今天先整理下JMeter的压力测试。先介绍下JMeter吧:Apache JMeter是...
  • 1、参数化的定义 参数化是自动化测试脚本的一种常用技巧,可将脚本中的某些参数使用变量来代替。例如登录操作时,利用GET/POST请求方式传递参数的场景,可在脚本运行时指定参数的取值范围和规则。 脚本在运行时,...
  • 如何测试MySQL的压力?

    2021-01-19 14:31:32
    但出现过几次因为MYSQL并发太多而挂掉,一直想对MYSQL做压力测试。刚看到一篇介绍MYSQL压力测试的文章,确实不错,先收藏先吧。转载自:http://xfshean.blog.163.com/blog/static/60206566201272434556544/其实mysql...
  • 安全生产模拟考试一点通:R1快开门式压力容器操作免费试题根据新R1快开门式压力容器操作考试大纲要求,安全生产模拟考试一点通将R1快开门式压力容器操作模拟考试试题进行汇编,组成一套R1快开门式压力容器操作全真...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 151,361
精华内容 60,544
关键字:

压力支持参数