DICOM:基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前篇)

背景:

目前对于传统WEB网站性能(压力/负载)的测试工具有很多,loadrunner、iperf、siege等,操作都比较简单,这里就不介绍了。然而对于医疗领域内的服务器,通常指的是DICOM服务器,提供满足DICOM3.0标准规定的各项DIMSE服务,诸如DIMSE-C(C-STORE、C-FIND、C-MOVE、C-ECHO)、DIMSE-N(N-CREATE、N-DELETE)等等。倘若使用传统的压力测试工具会有几大局限性:

  1. 常见压力测试工具,通过模拟上千万用户实施并发负载及实时性能监测的方式来实现对WEB服务端的压力测试,且模拟的并发请求多以HTTP或TCP为主。然而DICOM服务无法直接通过HTTP请求进行访问(WADO、WADO-RS服务除外)。
  2. 虽然部分压力测试工具(例如LoadRunner、JMeter等)可以发送TCP请求进行压力测试,但是DICOM服务在TCP基础上还需要继续多次“请求-响应”来完成,通过常见的手动填充TCP数据体的方式无法模拟真实的DICOM请求。
  3. 遵循DICOM协议的PACS影像服务器自身通常有一定的约束,例如模拟多用户同时上传同一组图像(即同时发送同一套数据)时服务端可能会直接忽略数据体来减少负载,即使我们成功模拟了请求,此时的检测的性能并不能代表影像服务器性能上限,测试结果不准确。

资料搜集:

鉴于以上几点原因,我们需要寻找一款合适的能够监测DICOM服务器性能的工具,初步设想有几种可能的方案:
第一种,利用python等语言手动编写测试脚本,循环调用dcm4che2工具包中的dcmsnd.bat工具模拟多用户并发访问。这种方案的优点是思路简单,直接模拟真实用户操作;缺点是利用python调用dcmsnd.bat批处理指令我们只能获取简单的运行时间,且结果不具有可视化,应付简单的测试(比如内部开发人员自我测试)比较可行,不适用于实际项目发布测试。
第二种,利用JMeter、LoadRunner等工具的TCP请求测试,将DICOM文件以二进制形式放到TCP请求数据体中。该方案的优点是可以利用JMeter、LoadRunner等工具诸多可视化功能,对服务器性能进行全面分析;缺点是需要对DICOM协议进行抓包分析,梳理出具体的完整的数据包,难度较大。
第三种,尝试搜索现有工具或解决方案。通过gfsoso、baidu等搜索引擎,检索与DICOM Server performance相关的资料,发现相关性大的很少。主要有以下几篇有参考价值的资料:
JMeter-wiki中jakarta-jmeter-dev中Germany用户的使用实例。
DICOMetrix与Performance Tools for your PACS systems
利用JMeter测试TCP服务器发送十六进制请求
自定义jar包利用JMeter的“Java请求”模拟测试

实施方案:

整理分析上述资料,确定可以实施的方案有以下几种,各方案按照实施可行性高低进行排列:
1)利用开源JMeter工具,通过扩展自己的jar包(在jar包内部模拟dcmsnd请求)结合JMeter现有的”Java请求“完成DICOM服务端测试。具体实施方案可参考以下资料:
【可行性★★★★
【注】:初步设想可以直接在jar包中调用dcm4che工具包中的dcmsnd.jar,实际情形以具体编码时为准,可能会出现很多问题。
2)利用开源JMeter工具,使用wireshark等抓包工具对现有的dcmsnd与DICOM服务器之间的交互数据包进行提取分析,找出在TCP协议上发送的实际数据包,然后将该数据包手动填充到TCP请求数据体中,利用JMeter的”TCP请求“完成DICOM服务端性能测试。
【可行性★★★
【注】:该方法可能的问题是,DICOM整个协议的数据包无法通过一次TCP数据体完成发送,即使顺利完成数据包发送,也很难手动替换每个数据包中的dcm文件体,无法真正模拟多用户并发上传多套数据的应用场景。
3)通过注册DICOMetrix官网账号,申请DICOMetrix60天免费试用版对DICOM服务器进行测试。
【注】:由于该工具使用者较少,目前没找到破解版,即使获得试用版对其测试性能也有所怀疑。

具体实施:

本文基于JMeter+dcm4che2工具的基础上,决定尝试实施第一解决方案。通过“扩展JMeter”方式初步实现了模拟多用户并发调用dcmsnd发送多组数据到PACS影像服务器的测试,具体实现方式如下:

扩展JMeter的方法:

JMeter是Apache下开源测试框架,扩展方式有多种,诸如自定义协议扩展、Java请求扩展等等。此处采用的JMeter扩展方式为“Java请求扩展”,即通过继承AbstractJavaSamplerClient类,重写其中的runTest函数来完成对dcm4chee2影像服务器的存储服务压力测试。

扩展JMeter具体实现:

在runTest函数内部直接调用现有的dcmsnd工具包的main函数,通过在runTest中自动构建main函数的命令行参数arg0,来实现模拟多用户并发调用dcmsnd发送dcm文件到dcm4chee2服务器的场景。具体实现代码如下:

    public SampleResult runTest(JavaSamplerContext arg0) {

        String ipAddr=arg0.getParameter("IP","127.0.0.1");
        String portString=arg0.getParameter("Port", "11112");
        String calledAET=arg0.getParameter("AET", "DCM4CHEE");
        String callingAET=arg0.getParameter("CallingAET", "DCM4CHEE");
        String filePath=arg0.getParameter("FilePath", ".\\");
        int threadnum=arg0.getIntParameter("ThreadNumber");
        ++dirIndex;
        String dirPath=String.valueOf((int)(Thread.currentThread().getId())%threadnum+1);
        System.out.println("Current Thread id is "+String.valueOf(Thread.currentThread().getId()));
        String[] args=new String[]{
                calledAET+"@"+ipAddr+":"+portString,
                filePath+"\\"+dirPath
        };
        SampleResult sampleResult=new SampleResult();
        sampleResult.sampleStart();
        try {
            DcmSnd.main(args);
            sampleResult.sampleEnd();
            sampleResult.setSuccessful(true);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            sampleResult.sampleEnd();
            sampleResult.setSuccessful(false);
        }
        return sampleResult;
    }

使用说明:

1)将上述备选方案导出为jar包,例如jMeterTestDICOM.jar。
2)拷贝jMeterTestDICOM.jar包到JMeter的lib/ext目录下;
3)将jMeterTestDICOM.jar包依赖的jar包同时拷贝到lib/ext目录下,即dcm4che2-2.0.28/lib下的所有jar包(为了保险起见,拷贝所有jar包)
4)进入JMeter源码的bin目录,运行jMeter.bat脚本,弹出启动界面:
DICOM:基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前篇)_第1张图片
5)在JMeter中新建Java请求测试方案(具体操作参考:http://www.cnblogs.com/yuki-lau/archive/2013/04/20/3033010.html)
6)在Java请求中选中刚才新建的jMeterTestDICOM.jar包的dcmSendSamper类,如下图:
DICOM:基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前篇)_第2张图片
7)如图中输入IP、Port、AET、CallingAEt、FilePath、ThreadNumber参数,即可启动压力测试。

【说明】
:上图中的参数最终会传递到dcmSendSampler类中,runTest中会自动构造dcmsnd的命令行参数,即AET@IP:Port。其中需要格外说明的是FilePath参数,为了尽最大可能模拟现实中多用户并发上传,希望JMeter的每个线程传递的数据是不同的,因此在FilePath中是根目录,通过结合ThreadNumber(即总的JMeter线程并发数)来自动构造不同的二级目录,构造方式是:FilePath+”\”+String.valueOf(Thread.CurrentThread().getId()%ThreadNumber+1),即JMeter并发线程数有多少,就需要在FilePath根目录下创建从1到并发线程数对应数量的文件夹,内用任意数量的dcm文件填充。

测试结果:

由于直接使用的是dcm4che2工具包的工具,对于具体的测试结果就不分析了,直接贴几张实测结果图:
DICOM:基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前篇)_第3张图片
DICOM:基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前篇)_第4张图片
DICOM:基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前篇)_第5张图片
DICOM:基于JMeter+dcm4che2测试PACS服务器性能的解决方案(前篇)_第6张图片




作者:[email protected]
时间:2015-05-24

你可能感兴趣的:(JMeter,dcm4che2,DICOM服务器,DICOM性能测试)