发明内容
为解决现有技术的缺陷,本发明提出一种基于Web服务器的医学影像快速加载方法。
本发明采用如下技术方案实现:一种医学影像快速加载方法,其包括如下步骤:
A、由Web浏览器向Web服务器发出医学影像加载的HTTP请求;
B、由Web服务器解析HTTP请求,依据该医学影像的StudyUID通过Hash算法让响应的处理进程处理此请求,该处理进程判断医学影像是否已经加载,如果没有加载,Web浏览器从Web服务器中获取医学影像,并将医学影像保存到缓存中,如果医学影像已经加载过,则Web浏览器直接从缓存中获取医学影像。
其中,步骤B具体包括:
Web服务器收到Web浏览器发出的HTTP请求后,会随机指派给php-cgi子进程处理;
Php-cgi子进程区分HTTP请求的类型,对于需要加载医学影像的HTTP请求,Php-cgi子进程会依据医学影像的StudyUID来寻找固定的WebCacheChild子进程进行处理;
WebCacheChild子进程判断该医学影像是否已经加载过,如果加载过,直接从缓存中获取该医学影像返回,如没有加载过,再到Web医学影像存储服务载入医学影像并返回。
其中,当Php-cgi子进程接收到医学影像加载的HTTP请求时,通过Hash算法找到该医学影像的StudyUID对应的WebCacheChild子进程的进程ID,然后通过GetCurrendProcessId函数获取该进程ID对应的WebCacheChild子进程。
其中,如果WebCacheChild子进程的状态为psSuspend,说明进程可以执行该任务,状态改为psExecute。
其中,WebCacheChild子进程通过在缓存中查询医学影像来判断该医学影像是否已经加载过。
其中,Web服务器在运行的时候会为每个进程分配不同的内存区域,不同的进程具有独立的数据空间,且不同的进程通过共享内存区进行数据传递。
其中,通过系统函数CreateFileMapping创建一个共享内存区,并通过系统函数MapViewOfFile将共享内存区影射到进程地址中。
其中,通过系统函数OpenFileMapping打开管理进程创建的共享内存区。
与现有技术相比,本发明具有如下有益效果:
本发明通过进程调度策略和缓冲机制实现多用户的并发、避免影像的重复加载,从而有效的改善了医学影像加载失败或加载延迟等问题,有利于节约资源、提高医学影像的加载速度。
具体实施方式
本发明提出一种基于Web服务器的医学影像快速加载方法,其中,提供Web服务(Web Server)的Web服务器采用多进程并发处理方式对医学影像(或简称为“影像”)进行加载处理。Web服务器具有Web服务进程(Web Server Process)、数据交换区(SharedMemory)、处理任务进程(Task Process)和管理进程(Manage Process),由管理进程来对资源进行有效的分配,如图1所示。
因为系统(本申请中提到的系统,指Web服务器)在运行的时候会为每个进程分配不同的内存区域,对不同进程来说,它们具有独立的数据空间,要进行数据传递需要分配一个共享内存区(Shared Memory)。首先在启动主管理进程的时候可以通过系统函数CreateFileMapping创建一个共享内存区,通过系统函数MapViewOfFile将共享内存区影射到进程地址中。在系统运行过程中,管理进程需要管理两种类型的进程,一种为网络通信进程,别一种为数据处理任务进程。因为两种进程的调度策略完全不同,所以在实际操作中,应该分别进行考虑。
首先我们先描述网络通信进程调度策略:为了实现管理主进程对其进行合理调度,应该定义两个数据结构,分别记录管理主进程的属性信息、进程运行状态信息,同时定义进程的状态,将两个结构影射到共享内存中
进程状态定义表如下表1所示:
表1
网络通信子进程属性信息如下:
网络通信管理主进程属性信息的数据结构:
将二个结构影射到共享内存区中,如图2所示。
实现了对进程状态的记录后还需要定义一组用于进程间通信的消息命令。其中,进程消息定义如下表2所示:
表2
对消息定义完成后就可以实现进程的调度工作:管理主进程启动后将进程消息句柄记录在属性信息中。为了避免启动任务进程影响系统的运行效率,在启动管理主进程后将预先启动三个网络通信进程,使用CreateProcess启动进程,函数调用结束后返回进程ID号,找出子进程信息列表中未记录进程信息的位置,将内容写入该位置,同时将进程设置为psInit状态表示该任务进程正在启动中,还不能进行网络通信。
通信进程启动后通过系统函数OpenFileMapping打开管理进程创建的共享内存区,通过系统函数MapViewOfFile将内存区影射到该进程地址中,这样通信进程就可以访问进程信息列表中的信息。使用GetCurrendProcessId获取该进程ID找出列表中记录该进程的位置,将进程状态修改为psOpen,说明进程已经启动成功,可以执行任务。同时使用PostMessage向管理主进程发出WM_PROCESS_OPEN消息,通知管理主进程可以为该进程分配任务,进程进入等待状态。
管理进程接收到WM_PROCESS_OPEN消息后选择其中一个进程作为执行进程,向该进程发送WM_PROCESS_EXECUTE消息。
通信进程接收到WM_PROCESS_EXECUTE消息后启动完成端口网络监听模式,接收客户端的处理请求。当通信进程进入执行状态后生存期将开始计时,进程运行一段时间,到达生存期后当前执行的通信进程将向管理进程发出WM_PROCESS_SUSPEND消息,同时关闭完成端口网络监听,进程状态修改成psSupsend状态。网络监听虽然关闭,但该进程有可能还存在关闭监听端口前用户未处理完成的连接,所以进程不马上关闭,而是等待所有用户处理完成后再关闭进程。
管理进程接收到通信进程的WM_PROCESS_SUSPEND消息后需要马上选择一个挂起的通信进程发送WM_PROCESS_EXECUTE消息启动执行状态,接替网络通信任务。
管理进程定时检测通信进程数量,如果进程数量少于三个,将自动启动一个新进程用与等待执行通信任务,如图3所示。
以上为通信进程的调度策略,使用该方法可以保正网络通信的持续稳定工作,不会因运行时间长导致运行问题。
描述了通信进程的调度策略后,我们再描述处理进程的调度策略。同样我们为处理进程也定义三个数据结构,分别记录管理主进程属性信息、进程选择属性信息及处理子进程的数据交换信息,同时定义进程的状态,将三个结构影射到共享内存中,这样进程间就可以知道各自的状态,以便如何进行下一步的操作。
进程状态定义表3:
表3
处理子进程属性信息结构:
进程选择属性信息:
管理主进程属性信息结构:
将三个结构影射到共享内存区中,如图4所示。
管理主进程启动后将进程消息句柄记录在属性信息中。为了避免启动任务进程影响系统的运行效率,在启动管理主进程后应该预先启动若干个处理子进程,这些子进程主要包含两个类型:Php-cgi子进程和WebCacheChild子进程。Web server收到Web浏览器(又简称为“浏览器”)发出的HTTP请求后,会随机指派给php-cgi进程处理,Php-cgi子进程收到一个任务请求后,区分请求的类型,对于需要加载医学影像的请求,Php-cgi进程会依据医学影像的StudyUID来寻找固定的WebCacheChild子进程进行处理;WebCacheChild子进程获取到医学影像加载请求后,首先在缓存里判断该医学影像是否已经加载过,如果加载过,直接从缓存中获取该医学影像返回,如没有加载过,再到Web医学影像存储服务载入医学影像并返回。这些进程均使用CreateProcess启动,函数调用结束后返回进程ID号,找出子进程信息列表中未记录进程信息的位置,将内容写入该位置,同时将进程设置为psInit状态表示该任务进程正在启动中,还不能接收任务处理。如图5所示,显示了医学影像请求和响应流程的业务处理流程的框图。
如图6所示,处理子进程启动后通过系统函数OpenFileMapping打开管理进程创建的共享内存区C和D,共享内存C负责子进程A和通信管理进程之间的进程调度信息共享,通过MapViewOfFile将内存区影射到该进程地址中,这样Php-cgi处理子进程就可以访问进程信息列表中的信息。使用GetCurrendProcessId获取该进程ID找出列表中记录该进程的位置,将进程状态修改为psSuspend,说明进程已经启动成功,可以执行任务。同时使用PostMessage向管理主进程发出WM_PROCESS_OPEN消息,通知管理主进程可以为该进程分配任务。共享内存D主要负责Php-cgi子进程与WebCacheChild子进程之间的进程调度信息共享,参数的传递与数据返回。当Php-cgi子进程接收到医学影像加载的HTTP请求时,通过Hash算法找到该医学影像的StudyUID对应的WebCacheChild子进程的进程ID,然后通过GetCurrendProcessId函数获取该进程ID找出列表中记录该进程的位置,如果该进程状态为psSuspend,说明进程可以执行该任务,状态改为psExecute,WebCacheChild子进程通过共享内存D获取到参数后,从该进程管理的缓存中查询医学影像,如果加载了医学影像则直接返回,如果没有加载医学影像则再从Web服务器获取医学影像后返回。
因为Web服务是依据Web浏览器的HTTP请求随机选择php-cgi进程来处理,判断医学影像是否已经加载,如果没有加载过,医学影像需要从Web服务器中获取,并保存到缓存中,如果医学影像已经加载过,则直接从缓存中获取医学影像。
当我们需要对医学影像进行多次操作时,Web浏览器会发送多个请求给web服务,web服务会依据这些请求随机挑选php-cgi进程进行处理,如果处理该医学影像新的请求的php-cgi进程与上次处理这个影像请求的php-cgi进程不是同一个进程,则会造成影像在缓存中的重复加载和影像在影像服务中的重复获取,这将极大的浪费资源和降低Web服务的响应速度。为此,我们会根据影像的StudyUID采用hash算法在现有的WebCacheChild子进程数中选定一个固定进程ID对应的WebCacheChild子进程处理该医学影像的影像加载请求,只要在初始处理时在缓存中加载过一次该医学影像,则在处理后续请求时,该医学影像可以直接从缓存中读取,从而可以避免医学影像的重复加载,节约资源与提高处理效率。
结合图7和图8所示,管理主进程进入等待任务请求状态,实时检测管道进程属性信息表变量Request属性值,如果值为1表示需要分配一个资源给服务线程来处理任务。
当Web服务接收到一个任务请求时,首先判断处理子进程属性信息结构,该线程是否已经分配了处理资源,如果已经分配了资源,直接向处理进程发出处理请求,如果未分配资源,将管道进程属性信息变量Request值设为1,向管理主进程发出请求,管理进程为该线程分配资源,将Result设置为0~N的值,指定处理子进程属性信息具体的位置,同时向分配进程发出WM_PROCESS_EXECUTE消息,通知进程进入执行状态。如果所有的进程都处于处理状态,管理进程直接启动一个新进程来执行任务。
处理进程接收到处理任务,从处理子进程属性信息表中读取数据,进行处理,处理结束后向任务线程返回处理结果,分别填写:DataState为1,表示输出状态;Size表示输出数据大小;Data为数据内容。如果处理错误则在DataState值等于-1时处理错误。如果Data定义的最大空间不能放下输出的数据,可以采用多次填入数据的方法来实现大数据的输出,采用IsLastFragment来识别数据是否传输完成。
任务线程判断DataState状态如果值为1,说明任务处理完成读取Data数据,将内容返回给Web浏览器,结束任务。如果值为-1,说明处理错误,将进程状态设置为psError,结束任务。管理进程定期检测各进程状态,发现有psError状态进程,将其关闭。
为了提高线程与进程交互效率,避免任务线程每次处理都要向管理进程申请资源,所以当进程任务处理完后,并没有直接退出执行状态,仍然记录对应线程信息,延迟一段时间,等待该线程的下一次处理任务。
延迟一段时间,如果未接收到对应线程任务,处理子进程重新进入psSuspend状态将挂起时候记录在信息列表结构变量SuspendTime中,同时发管理进程发出WM_PROCESS_SUSPEND消息,通知管理进程该处理进程可以接收下一个线程任务。我们为每个任务进程设置了一个生存期,然后通过与SuspendTime时间进行判断来确认是否已经超过了进程的生存期。如果进程已经超过生存期结束进程,向管理进程发出WM_PROCESS_CLOSE消息。
由于每个进程都有一定的生存期,也就是说过一段时间后所有的旧进程都会被关闭,如果没有了任务进程,就无法接收任务请求,所以我们设置了一个初始默认启动进程数,如果进程小于指定数量,管理进程会启动新的任务进程来补充处理任务。使用定期更换进程的方法可以进一步提高系统的稳定性。
当系统关闭的时候管理进程会向各处理子进程发出WM_PROCESS_STOP消息,要求关闭所有处理。
使用该方法,Web服务程序内的线程任务只负责将任务输入数据拷入到数据交换区,然后等待处理结果,处理结束后再从数据交换区拷出输出数据返回结Web浏览器,服务进程内部环节简单,稳定性高。
综上,使用本申请的方法,特别是需对医学影像进行多次操作时,医学影像不会因此请求次数的多少而重复加载,医学影像只需加载一次,这样就有效的节约了有限的内存资源,提高了Web服务的影响速度。
以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。