拓冰建站拓冰建站
首页 / 资讯中心 / 正文

用Conquest搭建DICOM测试环境:从协议验证到压力测试实战指南

简介这是一份面向医疗影像开发者和系统管理员的Conquest DICOM Server测试工具包用于在本地搭建DICOM SCP服务模拟设备交互、验证PACS网络通信同时支持worklist工作列表查询与数据匿名化处理。压缩包整体22.28MB包含可执行程序、批处理脚本、DICOM字典、匿名化脚本以及7-Zip命令行工具等关键文件便于快速启动服务、自动化配置和维护。已有710人浏览学习。借助这套工具读者可以进行新设备入网前的兼容性验证、系统集成测试、性能评估及跨PACS数据迁移演练通过脚本掌握DICOM协议下C-STORE、C-FIND等核心操作匿名化脚本能有效规避隐私风险适合在研发测试环境中反复验证提升DICOM应用开发与接入效率。 做医疗信息化时间久了你会发现一个很有意思的现实真正的DICOM服务器在测试阶段往往不是那么好用的。厂商PACS还在迭代开发医院生产环境的设备又不能拿来随便做破坏性测试可集成测试的排期又一天都不会等你。这个时候一套稳定、可控、能快速部署的DICOM测试服务就成了刚需。Conquest DICOM Server是圈子里相当经典的开源轻量级DICOM服务器实现我把它当作搭建DICOM测试环境的核心工具配合dcm4che、dcmtk、pydicom这些辅助工具能覆盖从连通性验证到影像批量归档再到异常场景模拟的绝大部分测试需求。这篇文章就把我从零开始基于 Conquest DICOM Server 搭测试环境、写测试脚本、排坑的经历完整拆给你看。适合正在做 PACS/RIS 集成测试、DICOM 设备对接验证、或者想快速搭一套本地影像归档环境来练手的工程师。1. 项目解读Conquest 在测试体系中的定位1.1 为什么需要专门搭一套 DICOM 测试服务器DICOM 服务器要测的东西其实很直接能不能接、能不能存、能不能查、能不能给四条通路必须全部跑通。但麻烦在于DICOM 协议本身是建立在 TCP/IP 之上的复杂应用层协议光是一个 C-STORE 请求就涉及 AE Title 协商、传输语法协商、PDU 分包、超时重传等一堆环节。任何一个环节有问题对接方要么直接报错要么默默丢包排查起来非常被动。直接拿生产环境的 PACS 当测试目标有风险拿厂商的开发服务器当测试目标又经常过期。所以我倾向于用 Conquest DICOM Server 自己搭一个“影子服务器”。它扮演的角色可以是标准接收方用来验证客户端发送能力也可以是标准发送方用来验证服务端的接收能力甚至能同时跑多个实例模拟多设备并发。这个灵活性是生产级 PACS 给不了的。1.2 Conquest 的核心优势与选型理由Conquest 在 DICOM 测试场景里被广泛使用主要有四个原因。第一轻。整个安装包就几十兆Java 虚拟机都不用装Windows 下直接跑 dgate.exeLinux 下用 wine 或者编译原生版本都能跑。测试环境往往需要反复重建轻量意味着你可以随时删了重来。第二支持多数据库后端。默认内置的 B-Tree 存储就能满足大多数测试需求也可以切到 MySQL、PostgreSQL、Oracle 或者 SQLite。我测过 MySQL 后端在百万级影像数量级下查询性能依然够用用来做大数据量回归测试很合适。第三协议覆盖面完整。C-ECHO、C-STORE、C-FIND、C-MOVE、C-GET、C-STORE-RQ/SCP 这些基础 SOP 类都支持还能配 JPEG、JPEG 2000、RLE 等多种传输语法基本能把 DICOM 标准里最常见的流程都串起来。第四配置逻辑简单清晰。所有服务器配置都在一个 dicom.ini 文件里搞定不需要图形界面改完重启服务就生效。对于自动化测试来说这种纯文本配置的方式非常友好我可以把配置模板直接塞进 Git 仓库里管理。2. 测试环境搭建从裸机到可用的 DICOM 服务2.1 安装 Conquest 并完成基础配置我在 Windows 环境下的安装步骤如下。下载最新版安装包后解压到 D:\Conquest 目录然后双击 dgate.exe 启动第一次运行会自动在当前目录生成 dgate.ini 和 dicom.ini。dicom.ini 里有几个关键配置项我直接给出适合测试的模板。# 服务器基本配置 ServerName DICOM_TEST_SERVER TCPPort 11112 AEAddress 0.0.0.0 Database builtin # 存储目录 MicroPACS D:\Conquest\data EOF # 日志配置 StoreDB 0 LogFile D:\Conquest\logs\dgate.log LogLong 0 LogKeepDays 30 # 允许的调用方客户端AE Title # 逗号分隔* 表示允许所有 AllowAll 1这里重点说两个配置的作用。TCPPort 是服务器监听的端口DICOM 默认端口是 11112但测试时我经常在一个主机上跑多个 Conquest 实例这时候就需要分别设置 11112、11113、11114 等端口。AllowAll 是 AE Title 白名单开关测试阶段我会直接设成 1省得一个个加白名单但生产化部署时一定要关掉。改完配置后在命令行执行dgate.exe --start启动服务。启动成功后Windows 服务管理器里会多出一个 Conquest 服务也可以手动把服务注册成系统服务方便开机自启。2.2 配套测试工具链准备只有 Conquest 还不够测试时还需要能从客户端侧发起 DICOM 请求的工具。我常用的工具链有三套。第一套是 dcm4che 工具集。这是一个纯 Java 的 DICOM 工具包提供 storescu、storescp、echoscu、findscu、movescu、getscu 等一系列命令行工具。它比 dcmtk 的坑少对中文字段支持也更好我主要拿它来做标准符合性验证。第二套是 dcmtk 工具集。老牌 C 工具包离线文档丰富出错信息详细。虽然命令行参数风格有点古老但稳定性和兼容性一流尤其是在和旧设备联调时dcmtk 往往是最后能对上话的工具。第三套是 pynetdicom 库。这是 Python 生态里最成熟的 DICOM 网络库我主要用它来写自定义测试脚本做场景化自动化。比如模拟异常中止、注入错误参数、批量压测这些用现成命令行工具很难灵活实现自己写脚本就非常顺手。我有一次测试一个对接方的接收服务用 dcm4che 的 storescu 发图总是失败但用 dcmtk 的 storescu 却能发上去后来查原因是对方接收服务对 PDU 最大长度的处理有 bug对 dcm4che 默认的 16384 字节 PDU 协商结果处理异常。这提醒我多套工具交叉验证不是重复劳动而是排查问题的重要手段。2.3 快速验证服务已就绪服务装好之后第一步不是急着调用例而是先确认 Echo 通路正常。我这里给一个标准的 echoscu 命令。echoscu -v -aec DICOM_TEST_SERVER 127.0.0.1 11112参数含义依次是-v 打印详细过程-aec 指定被调用的 AE Title后面跟服务器地址和端口。如果返回Echo SCU (C-ECHO) - Response Success说明服务已经就绪可以开始测业务了。在这个阶段我还会顺手验证一下存储目录是否可写。用 storescu 发一张测试 DICOM 文件进去然后在 Conquest 的 data 目录里确认文件确实落盘了。这一步能提前暴露权限问题或磁盘空间不足的问题避免后面正式测试时被打断。3. 核心测试场景与实操步骤3.1 连通性验证C-ECHOC-ECHO 是 DICOM 世界里的 ping专门用来验证网络连通性、AE Title 配置、端口可达性。它不传输业务数据只发一个很小的 DICOM 消息确认双方能正常握手。我在项目启动的第一天就会跑一遍 Echo 测试之后每次环境变更换 IP、改端口、更新证书后也会重新跑一遍。这是一个成本极低但收益极高的回归手段。实操时还会遇到一个常见场景Conquest 既要当 SCP 做接收端又要当 SCU 主动往外推数据。这时要确认 Conquest 作为 SCU 发起 Echo 的能力。可以在 Conquest 的控制台里直接输命令也可以用 dgate 自带的dgate.exe -v -e参数做检测。如果 Conquest 对应的配置里 AE Title 没写对反过来建立会话时就会失败。3.2 影像上传下载测试C-STOREC-STORE 是 DICOM 系统使用频率最高的操作对应到业务场景就是设备的影像传到 PACS、或者 PACS 向阅片工作站分发影像。测试时需要覆盖发送、接收、重传、断点续传这几个维度。最简单的方式是用 dcm4che 的 storescu 发送本地 DICOM 文件storescu -v -aec DICOM_TEST_SERVER -aet TEST_CLIENT 127.0.0.1 11112 /path/to/ct_image.dcm这里 -aet 是发起方 AE TitleConquest 会把这对 AE Title 记录到日志中。发送成功后再到 Conquest 的 data 目录里确认 Study、Series、Instance 三层目录是否按预期创建。如果测的是一台 CT 或 MR 设备它发图的行为更像“批处理”一次 C-STORE 连接里连续传几十上百张图。这时要注意测试脚本能否模拟“同一连接内多实例发送”。PACS 设备端最容易出问题的也是这里很多设备在单连接传多图时如果某一张图出问题整个连接都会断开。我在测试脚本里会用一个循环一个 Connection 内连续发送指定数量的 DICOM 文件并记录每个文件的发送结果。如果中间有失败需要区分是网络层中断还是应用层拒绝这直接影响定位方向。3.3 查询与调阅流程测试C-FIND / C-MOVE影像存进来了下一步就是验证“查得到、调得出来”。C-FIND 是用来查询影像元数据的比如按患者 ID、检查号、日期范围查询。C-MOVE 则是把一个存储管理操作C-STORE委托给服务器让服务器主动把影像推到目标 AE 地址。用 findscu 做查询的示例findscu -v -aec DICOM_TEST_SERVER -aet TEST_CLIENT -P -k QueryRetrieveLevelSTUDY -k PatientIDTEST001 127.0.0.1 11112这里-P表示要求服务器返回匹配结果-k指定查询条件。如果返回了 STUDY 级别的记录说明 C-FIND 通路正常。C-MOVE 的测试稍微复杂一点因为涉及第三个 AE。比如 Conquest 作为 SCP 存储影像客户端发起 C-MOVEConquest 作为 C-MOVE SCU 把影像推到客户端指定的目标 AE。我一般会先在本机再起一个 storescp 监听端口作为 C-MOVE 的目标接收端一次性验证完整的两次 C-STORE 链路。3.4 批量压力与异常场景测试在正式对接上线前我通常会做一轮压力测试重点看服务器在并发连接、批量发送、长时间挂机场景下的表现。压力测试我用 Python 脚本实现核心思路是开多个线程同时发图每个线程持有独立的 DICOM Association循环发送。from pynetdicom import AE, StoragePresentationContexts from pydicom import dcmread import threading def send_images(thread_id, file_paths): ae AE(ae_titlebLOADTEST) ae.requested_contexts StoragePresentationContexts assoc ae.associate(127.0.0.1, 11112, ae_titlebDICOM_TEST_SERVER) if assoc.is_established: for f in file_paths: ds dcmread(f) status assoc.send_c_store(ds) if status.Status ! 0x0000: print(fThread {thread_id} failed: {f}, status{status.Status}) assoc.release() else: print(fThread {thread_id} cannot establish association) if __name__ __main__: files [img_%04d.dcm % i for i in range(1, 101)] threads [threading.Thread(targetsend_images, args(i, files[i*10:(i1)*10])) for i in range(10)] for t in threads: t.start() for t in threads: t.join()这个脚本会创建 10 个并发连接每个连接发 10 张图。如果 Conquest 的数据库并发处理能力不足或者磁盘 IO 成为瓶颈这时就会暴露出来。我在实测中遇到的典型表现是部分线程报 Association 建立失败或者发送后服务器响应超时。这种问题大多可以通过调大 Conquest 数据库连接池上限、换更高性能的存储目录来解决。除了压力测试异常场景同样值得关注。比如发送一半时手动断开网络、发送一个损坏的 DICOM 文件、让对方 AE Title 与配置不符、发送超大单帧图像这些都会触发服务器的容错逻辑。只有把这些异常都测过一遍才能真正放心让设备对接生产环境。4. 常见问题排查与避坑实录4.1 AE Title 配置不生效排查 DICOM 连接问题AE Title 永远是最先怀疑的对象。DICOM 协议在建立连接时双方要交换 AE Title 并做校验。如果服务器配置里只允许特定 AE Title 接入客户端传一个不在白名单里的 AE Title连接会被直接拒绝。Conquest 的 AllowAll 配置默认是 0也就是严格模式。测试环境建议先开成 1等业务确认了再收紧。还有一个小坑是dicom.ini 里的配置项名称大小写不能错AllowAll如果写成allowallConquest 会当成未识别字段忽略掉AE Title 限制依然生效。我遇到过好几次看似配置生效但实际被忽略的情况最后都是通过看启动日志确认的。4.2 传输语法不匹配传输语法协商是 DICOM 连接建立过程中最隐蔽的坑之一。发送方支持无损 JPEG接收方只支持 RLE两边协商不下来连接直接建立失败但报错信息往往只有一句Failed to negotiate a presentation context根本定位不到根因。排查思路是抓包看 DICOM Association 请求里的 Presentation Context 列表再对照服务器支持的传输语法表。Conquest 的配置里有一个Compression参数可以设置支持的压缩格式。我把 JPEG 无损、JPEG-LS、RLE 都打开后兼容性明显提升。4.3 字符集与中文患者姓名乱码国内医院的患者姓名基本都是中文而 DICOM 标准里字符集默认是 ASCII如果不声明扩展字符集中文会直接变乱码。Conquest 在配置里支持CharacterSet GB18030或CharacterSet ISO_IR 192需要根据客户端实际编码方式做对应配置。最常见的现象是用 dcm4che 发送中文患者姓名到 Conquest 后用 Conquest 自带浏览器看记录是正常的但用第三方 PACS 再调阅时却乱码。这是因为 Conquest 默认会把未知字符集转成 UTF-8而某些老设备只识别 GBK。解决办法是在发送客户端就明确指定字符集并通过 DICOM 的 SpecificCharacterSet 字段传给对方让两边对编码方式达成一致。4.4 性能瓶颈与数据库锁问题Conquest 内置数据库在小数据量时非常流畅但如果你拿它压测到几十万张图就会遇到数据库锁等待的问题。最典型的表现是发送速度急剧下降日志里频繁出现Lock timeout或database is locked的错误。我踩了这个坑后就改成用 MySQL 后端来支撑压力测试。Conquest 连接 MySQL 需要额外创建数据库并导入初始化脚本配置相对繁琐但换来的是并发写入能力的大幅提升。如果你只是想测试客户端功能内置库足够如果你要做压测或长时间稳定运行验证建议直接上 MySQL。5. 扩展实践与个人心得5.1 用 Python 脚本封装测试流程命令行工具适合单步验证但真正做回归测试时我会用 Python 把测试流程串成一套自动化套件pynetdicom 负责 DICOM 层交互pytest 负责用例管理与结果断言。每个测试用例都设计成独立的函数比如 test_echo_success、test_store_ct_series、test_find_study_by_date、test_move_multiple_instances这样既能单独跑也能一键全量回归。这个封装过程不仅提高了测试执行效率也让团队里刚接触 DICOM 的新人更容易上手。可以说把基于 Conquest 的 DICOM 测试从“手工敲命令”升级到“自动化套件”是我觉得整个项目中最有价值的一件事。5.2 结合 CI/CD 做每日回归在 Conquest 测试环境稳定后我把它挂进了 CI 流水线。每天早上自动构建最新的 Conquest 测试环境跑一遍全量 DICOM 协议回归测试然后把结果推送到项目群。这样即使对接的开发分支有改动也能第一时间感知到 DICOM 兼容性是否被破坏。这个实践让我在项目后期省下了大量手工排查时间。有一次对接方的服务端更新了传输语法优先级导致所有 C-STORE 请求都协商到 JPEG 2000影像精度测试直接失败。如果不是 CI 回归及时捕捉到这个变化真等部署到现场再发现返工成本就太大了。5.3 数据准备与持续集成测试 DICOM 服务器最烦的事情之一就是准备测试数据。真实设备导出的 DICOM 文件往往带着患者真实信息不能随意复制更不能放到公共仓库。我的方案是用 pydicom 批量生成标准 DICOM 文件并随机化患者姓名、检查号、医院 ID 等字段同时保留不同模态CT、MR、DX、US的典型标签结构。生成好的数据打包成一个压缩文件统一存到测试环境的指定目录。Conquest 在首次启动时会扫描该目录并注册元数据之后所有测试用例直接用这些数据。每次回归前我会做一次数据清空重建确保测试结果可重复不会因上一次脏数据残留造成干扰。最后再分享一个小技巧Conquest 的日志非常详细它记录了每一次 DICOM 请求的 AE Title、传输语法、响应状态、耗时等关键信息。很多你从客户端侧看不透的问题翻一下 Conquest 的日志就能一目了然。如果排查过程中客户端报错和服务端日志对不上先确认两边的时间基准是否一致这个看起来不起眼的点曾经让我白费了好几个小时。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门