本公开涉及计算机技术领域,尤其涉及一种镜像构建方法与装置、电子设备、计算机可读存储介质。
背景技术:
持续集成是在源代码变更后自动检测、拉取、构建和(在大多数情况下)进行单元测试的过程。持续集成的目标是快速确保开发人员新提交的变更是好的,并且适合在代码库中进一步使用。
在通过持续集成构建镜像时,采用宽约束条件(例如,应用代码所依赖的依赖包的版本有多个)安装依赖包时,依赖包的更新升级导致对同一份源码执行持续集成最终生成的镜像中所安装的依赖包不同。对于应用代码bug修复的场景,可能导致应用代码无法正常运行。因此,依赖包安装的可控性及可重入性较低。
技术实现要素:
本公开的目的在于提供一种镜像构建方法与装置、电子设备、计算机可读存储介质,进而至少在一定程度上克服由于现有技术的限制和缺陷而导致的在构建镜像时依赖包安装的可控性及可重入性较低的问题。
本公开的其他特性和优点将通过下面的详细描述变得显然,或部分地通过本公开的实践而习得。
根据本公开的第一方面,提供一种镜像构建方法,包括:
获取包含依赖信息的应用代码,所述依赖信息包含所述应用代码所依赖的目标依赖包及所述目标依赖包对应的版本约束条件;
根据所述目标依赖包对应的版本约束条件,确定所述目标依赖包的相关依赖信息,所述相关依赖信息包括:所述目标依赖包所依赖的基础依赖包;
根据所述相关依赖信息,安装所述基础依赖包及所述目标依赖包,得到依赖层镜像;
安装所述应用代码,得到应用层镜像。
可选的,本公开实施例的镜像构建方法,还包括:
获取所述应用代码的类型;
在所述应用代码为第一类型时,或,在所述应用代码为第二类型,且所述应用代码为首次构建时,执行所述根据所述目标依赖包对应的版本约束条件,确定所述目标依赖包的相关依赖信息的步骤;
在所述应用代码为第二类型,且所述应用代码为非首次构建时,获取已构建的依赖层镜像,执行所述安装所述应用代码,得到应用层镜像的步骤。
可选的,本公开实施例的镜像构建方法,还包括:
在所述目标依赖包或所述基础依赖包发生变化时,如果所述应用代码为第一类型,对所述依赖层镜像进行更新;如果所述应用代码为第二类型,不对所述依赖层镜像进行更新。
可选的,所述根据所述目标依赖包对应的版本约束条件,确定所述目标依赖包的相关依赖信息,包括:
根据所述目标依赖包对应的版本约束条件,确定所述目标依赖包的版本;
对所述版本的目标依赖包进行递归检索,得到所述目标依赖包的相关依赖信息,所述相关依赖信息中的基础依赖包包括:所述版本的目标依赖包直接依赖的第一基础依赖包以及间接依赖的第二基础依赖包。
可选的,所述相关依赖信息还包括:所述基础依赖包的可安装版本;
所述根据所述相关依赖信息,安装所述基础依赖包及所述目标依赖包,包括:
根据所述基础依赖包的可安装版本,对所述基础依赖包进行安装;
根据所述目标依赖包的版本,对所述目标依赖包进行安装。
可选的,本公开实施例的镜像构建方法,还包括:
判断所述相关依赖信息中是否存在针对任一基础依赖包的版本冲突;
在不存在版本冲突时,执行所述根据所述相关依赖信息,安装所述基础依赖包及所述目标依赖包的步骤;
在存在版本冲突时,显示异常提示信息。
可选的,本公开实施例的镜像构建方法,还包括:
在所述应用代码更新时,重新安装所述应用代码,得到更新的应用层镜像。
根据本公开的第二方面,提供一种镜像构建装置,包括:
应用代码获取模块,用于获取包含依赖信息的应用代码,所述依赖信息包含所述应用代码所依赖的目标依赖包及所述目标依赖包对应的版本约束条件;
相关依赖信息确定模块,用于根据所述目标依赖包对应的版本约束条件,确定所述目标依赖包的相关依赖信息,所述相关依赖信息包括:所述目标依赖包所依赖的基础依赖包;
依赖层镜像确定模块,用于根据所述相关依赖信息,安装所述基础依赖包及所述目标依赖包,得到依赖层镜像;
应用层镜像确定模块,用于安装所述应用代码,得到应用层镜像。
可选的,本公开实施例的镜像构建装置,还包括:
代码类型获取模块,用于获取所述应用代码的类型;
所述相关依赖信息确定模块,具体用于在所述应用代码为第一类型时,或,在所述应用代码为第二类型,且所述应用代码为首次构建时,根据所述目标依赖包对应的版本约束条件,确定所述目标依赖包的相关依赖信息;
依赖层镜像获取模块,用于在所述应用代码为第二类型,且所述应用代码为非首次构建时,获取已构建的依赖层镜像。
可选的,本公开实施例的镜像构建装置,还包括:
依赖层镜像第一处理模块,用于在所述目标依赖包或所述基础依赖包发生变化时,如果所述应用代码为第一类型,对所述依赖层镜像进行更新;
依赖层镜像第二处理模块,用于在所述目标依赖包或所述基础依赖包发生变化时,如果所述应用代码为第二类型,不对所述依赖层镜像进行更新。
可选的,所述相关依赖信息确定模块,包括:
版本确定单元,用于根据所述目标依赖包对应的版本约束条件,确定所述目标依赖包的版本;
递归检索单元,用于对所述版本的目标依赖包进行递归检索,得到所述目标依赖包的相关依赖信息,所述相关依赖信息中的基础依赖包包括:所述版本的目标依赖包直接依赖的第一基础依赖包以及间接依赖的第二基础依赖包。
可选的,所述相关依赖信息还包括:所述基础依赖包的可安装版本;
所述依赖层镜像确定模块,具体用于根据所述基础依赖包的可安装版本,对所述基础依赖包进行安装;根据所述目标依赖包的版本,对所述目标依赖包进行安装。
可选的,本公开实施例的镜像构建装置,还包括:
判断模块,用于判断所述相关依赖信息中是否存在针对任一基础依赖包的版本冲突;
所述依赖层镜像确定模块,具体用于在不存在版本冲突时,根据所述相关依赖信息,安装所述基础依赖包及所述目标依赖包;
异常提示模块,用于在存在版本冲突时,显示异常提示信息。
可选的,本公开实施例的镜像构建装置,还包括:
应用层镜像更新模块,用于在所述应用代码更新时,重新安装所述应用代码,得到更新的应用层镜像。
根据本公开的第三方面,提供一种电子设备,包括:处理器;以及存储器,用于存储所述处理器的可执行指令;其中,所述处理器配置为经由执行所述可执行指令来执行上述任意一项所述的方法。
根据本公开的第四方面,提供一种计算机可读存储介质,其上存储有计算机程序,所述计算机程序被处理器执行时实现上述任意一项所述的方法。
本公开的示例性实施例具有以下有益效果:
本公开的示例性实施例提供的镜像构建方法及装置中,在持续集成过程中通过将依赖包的安装从应用代码的安装中独立出来,可以单独构建依赖层镜像和应用层镜像。这样,可以根据实际应用场景对依赖层镜像和应用层镜像分别进行更新,从而可以提升依赖包安装的可预知性、可控性,避免应用代码无法正常运行的问题。
应当理解的是,以上的一般描述和后文的细节描述仅是示例性和解释性的,并不能限制本公开。
附图说明
此处的附图被并入说明书中并构成本说明书的一部分,示出了符合本公开的实施例,并与说明书一起用于解释本公开的原理。显而易见地,下面描述中的附图仅仅是本公开的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
图1示出了本公开实施例中镜像构建方法的一种流程图;
图2示出了本公开实施例中镜像构建方法的又一种流程图;
图3示出了本公开实施例中镜像构建装置的一种结构示意图;
图4示出了用于实现本公开实施例的电子设备的计算机系统的结构示意图。
具体实施方式
现在将参考附图更全面地描述示例实施方式。然而,示例实施方式能够以多种形式实施,且不应被理解为限于在此阐述的范例;相反,提供这些实施方式使得本公开将更加全面和完整,并将示例实施方式的构思全面地传达给本领域的技术人员。所描述的特征、结构或特性可以以任何合适的方式结合在一个或更多实施方式中。
需要说明的是,本公开中,用语“包括”、“配置有”、“设置于”用以表示开放式的包括在内的意思,并且是指除了列出的要素/组成部分/等之外还可存在另外的要素/组成部分/等;用语“第一”、“第二”等仅作为标记使用,不是对其对象数量或次序的限制。
目前,对于基于python语言开发的应用,通过持续集成构建docker镜像的方法为:将应用的外部依赖对应的约束条件记录在应用代码中,然后将该应用代码安装到镜像中,并依照其中描述的宽约束条件进行外部依赖包的安装。最后,将构建的结果镜像用于部署,镜像本身是一个不可变文件,从而使基于该镜像启动的实例每次内部运行的代码及依赖相同,实现应用代码部署的可重入。其中,docker一个开放源代码软件项目,让应用程序部署在软件货柜下的工作可以自动化进行,借此在linux操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化的自动管理机制。
然而,在使用宽约束条件安装依赖包时,当对历史版本的应用进行修复时,由于无法得知外部依赖包的变化是否对应用的功能产生影响,可能由于版本的不兼容导致应用代码无法正常运行。
为了解决上述问题,本公开实施例提供了一种镜像构建方法与装置、电子设备、计算机可读存储介质,可以提高依赖包安装的可控性及可重入性。
下面首先对本公开实施例的镜像构建方法进行详细介绍。
参见图1,图1示出了本公开实施例中镜像构建方法的一种流程图,可以包括以下步骤:
步骤s110,获取包含依赖信息的应用代码,依赖信息包含应用代码所依赖的目标依赖包及目标依赖包对应的版本约束条件。
步骤s120,根据目标依赖包对应的版本约束条件,确定目标依赖包的相关依赖信息,相关依赖信息包括:目标依赖包所依赖的基础依赖包。
步骤s130,根据相关依赖信息,安装基础依赖包及目标依赖包,得到依赖层镜像。
步骤s140,安装应用代码,得到应用层镜像。
本公开实施例的镜像构建方法,在持续集成过程中通过将依赖包的安装从应用代码的安装中独立出来,可以单独构建依赖层镜像和应用层镜像。这样,可以根据实际应用场景对依赖层镜像和应用层镜像分别进行更新,从而可以提升依赖包安装的可预知性、可控性,避免应用代码无法正常运行的问题。
参见图2,图2示出了本公开实施例中镜像构建方法的又一种流程图,可以包括以下步骤:
步骤s210,获取包含依赖信息的应用代码及应用代码的类型。
本公开实施例中,应用代码是指应用软件的代码,可以是python代码,或者java代码等。应用代码中的依赖信息可以以文件的形式提交到该应用代码对应的代码版本库中。应用代码可以在其他软件的基础上开发,那么,应用代码依赖的其他软件可以称为目标依赖包。也就是说,仅仅安装应用代码,应用软件是无法使用的,在安装应用代码和目标依赖包之后,该应用软件才可以使用。
依赖信息指的是该应用代码所依赖的信息,包括:应用代码所依赖的目标依赖包及目标依赖包对应的版本约束条件。目标依赖包的数量可以是一个,也可以是多个。在目标依赖包的数量为多个时,针对每个目标依赖包,对应有版本约束条件,也就是支持的版本范围。各个目标依赖包及对应的版本约束条件可以记录在文档中。例如,在requirements.txt文档中,目标依赖包包含四个,分别为:requests-toolbelt、captcha、moprofiler和line-profiler,对应的版本约束条件可以分别是:>=0.9.1、==0.2.4、~=1.0.2和空,其中,空表示没有版本的限制。
在本公开的一种实现方式中,应用代码的类型可以根据应用场景分为:第一类型(内部开发类型)和第二类型(外部上线类型)。第一类型指应用代码供内部开发使用,没有对外使用;第二类型指代码已经对外上线,已经对外使用。当然,也可以根据其他情况进行划分,在此不做限定。应用代码类型的获取方法可以有多种,例如,可以根据应用代码所在分支的标签信息确定,或者也可以根据应用代码中包含的配置文件确定等。
步骤s220,确定应用代码的类型,并判断应用代码是否是首次构建。
本公开实施例中,可以根据应用代码的类型以及是否首次构建,进行不同的处理。在应用代码为第一类型时,或,在应用代码为第二类型,且应用代码为首次构建时,可以执行步骤s230。在应用代码为第二类型,且应用代码为非首次构建时,执行步骤s270。也就是,对于第一类型的应用代码,不论是否是首次构建,均可以执行步骤s230。而对于第二类型的应用代码,由于考虑到已经对外使用,可以根据是否首次构建进行不同的处理。
步骤s230,根据目标依赖包对应的版本约束条件,确定目标依赖包的相关依赖信息。
本公开实施例中,目标依赖包也可能依赖于其他依赖包,目标依赖包所依赖的其他依赖包可以称为基础依赖包。因此,相关依赖信息包括:目标依赖包所依赖的基础依赖包。
由于基础依赖包也可能依赖于其他依赖包,即依赖包之间可能层层依赖,在此,也可以把基础依赖包所依赖的其他依赖包称为基础依赖包,这样,基础依赖包包括:目标依赖包直接依赖的第一基础依赖包以及间接依赖的第二基础依赖包。
具体的,首先可以根据目标依赖包对应的版本约束条件,确定目标依赖包的版本。例如,对于requests-toolbelt>=0.9.1,确定requests-toolbelt的版本可以为0.9.1、0.9.2及以上版本等。对于captcha==0.2.4,可以确定captcha的版本为0.2.4。
之后,可以对该版本的目标依赖包进行递归检索,得到目标依赖包的相关依赖信息。
本公开实施例中,可以对每个目标依赖包进行递归检索。例如,对0.9.1版本的requests-toolbelt进行检索,得到requests-toolbelt的基础依赖包及基础依赖包的版本约束条件。并按照与目标依赖包相同的处理方式,确定基础依赖包的版本,并对该版本的基础依赖包进行检索。以此类推,直至得到的最下层的基础依赖包没有依赖,其中,最上层为目标依赖包。至此,可以得到目标依赖包的相关依赖信息。其中,相关依赖信息还可以包括:基础依赖包(第一基础依赖包及第二基础依赖包)的可安装版本,可安装版本表示可以安装的基础依赖包的版本。
其中,requirements.txt对应的相关依赖信息可以是逐层表示的,最上层最靠近左边第一列,层级越下,距离左侧第一列越远。例如,对于0.2.4版本的captcha,所依赖的基础依赖包为pillow,pillow为第一基础依赖包,并且pillow的版本约束条件是:可以安装任何版本的pillow,当前要安装的版本可以为6.1.0。
再比如,对于moprofiler~=1.0.2,表示moprofiler的版本可以约等于1.0.2,在此,确定moprofiler的版本为1.1.0,1.1.0版本的moprofiler的依赖包包括:line-profiler、memory-profiler和pyaop,line-profiler、memory-profiler和pyaop均为第一基础依赖包,line-profiler的版本约束条件是:>=2.1.2,当前要安装的版本可以是2.1.2。2.1.2版本的line-profiler又依赖于ipython,ipython为第二基础依赖包,ipython的版本约束条件是:>=0.13,当前要安装的版本可以是5.8.0。由于moprofiler的基础依赖包较多,在此不一一列举。
可以理解的是,上述相关依赖信息也可以表示为树形结构,最上层为目标依赖包,逐层向下,下一层是上一层的依赖包。
步骤s240,判断相关依赖信息中是否存在针对任一基础依赖包的版本冲突。
本公开实施例中,相关依赖信息中包含目标依赖包和多个基础依赖包,针对单个依赖包(目标依赖包或基础依赖包),可能存在两条或两条以上的信息,例如,包括:six[required:any,installed:1.12.0]、six[required:any,installed:1.12.0]以及six[required:>=1.9.0,installed:1.12.0],针对同一个基础依赖包six,对应的版本约束条件有多个,而且是不同的。如果三个版本约束条件之间存在交集,表示不存在冲突。如果三个版本的约束条件之间没有交集,说明存在冲突,此时,是不能根据目标依赖包和基础依赖包构建依赖层镜像,执行步骤s260,即显示异常提示信息,异常提示信息可以是“版本冲突”等。
步骤s250,根据相关依赖信息,安装基础依赖包及目标依赖包,得到依赖层镜像。
在不存在版本冲突时,可以根据相关依赖信息,直接安装基础依赖包及目标依赖包。可选的,可以根据基础依赖包的可安装版本,对基础依赖包进行安装;根据目标依赖包的版本,对目标依赖包进行安装。
本公开实施例中,如果应用代码为第一类型,由于第一类型的应用代码供内部开发使用,没有对外使用,在目标依赖包或基础依赖包发生变化时,可以对依赖层镜像进行更新。这样,即使可能导致应用代码无法正常运行,也不会对用户造成影响。
相反地,如果应用代码为第二类型,而第二类型的应用代码已经对外使用,如果对依赖层镜像进行更新,可能导致应用代码无法正常运行,这样,用户将无法使用应用软件。因此,在应用代码为第二类型时,可以不对依赖层镜像进行更新。可见,本公开可以实现依赖层镜像更新或不更新的需求。
步骤s270,获取已构建的依赖层镜像。
本公开实施例中,在应用代码为第二类型时,如果应用代码已经构建过依赖层镜像,可以直接在已构建的依赖层镜像的基础上,构建应用层镜像,从而可以提高构建效率。
步骤s280,安装应用代码,得到应用层镜像。
本公开实施例中,由于依赖包的安装和应用代码的安装是独立的,因此,在应用代码更新时,重新安装应用代码即可,得到更新的应用层镜像。可见,本公开实施例的镜像构建方法可以提高对依赖包的可控性及可重入性。
本公开实施例的镜像构建方法,在持续集成过程中通过将依赖包的安装从应用代码的安装中独立出来,可以单独构建依赖层镜像和应用层镜像。这样,可以根据实际应用场景对依赖层镜像和应用层镜像分别进行更新,从而可以提升依赖包安装的可预知性、可控性,避免应用代码无法正常运行的问题。通过直接使用已构建的依赖层镜像继续构建,从而提高了构建效率。并且,可以根据代码类型,实现依赖层镜像更新或不更新的需求,进一步提高应用代码的可用性。
应当注意,尽管在附图中以特定顺序描述了本公开中方法的各个步骤,但是,这并非要求或者暗示必须按照该特定顺序来执行这些步骤,或是必须执行全部所示的步骤才能实现期望的结果。附加的或备选的,可以省略某些步骤,将多个步骤合并为一个步骤执行,以及/或者将一个步骤分解为多个步骤执行等。
进一步的,本示例实施方式中,还提供了一种镜像构建装置300,参见图3,图3示出了本公开实施例的镜像构建装置的一种结构示意图,包括:
应用代码获取模块310,用于获取包含依赖信息的应用代码,依赖信息包含应用代码所依赖的目标依赖包及目标依赖包对应的版本约束条件;
相关依赖信息确定模块320,用于根据目标依赖包对应的版本约束条件,确定目标依赖包的相关依赖信息,相关依赖信息包括:目标依赖包所依赖的基础依赖包;
依赖层镜像确定模块330,用于根据相关依赖信息,安装基础依赖包及目标依赖包,得到依赖层镜像;
应用层镜像确定模块340,用于安装应用代码,得到应用层镜像。
可选的,本公开实施例的镜像构建装置,还包括:
代码类型获取模块,用于获取应用代码的类型;
相关依赖信息确定模块,具体用于在应用代码为第一类型时,或,
在应用代码为第二类型,且应用代码为首次构建时,根据目标依赖包对应的版本约束条件,确定目标依赖包的相关依赖信息;
依赖层镜像获取模块,用于在应用代码为第二类型,且应用代码为非首次构建时,获取已构建的依赖层镜像。
可选的,本公开实施例的镜像构建装置,还包括:
依赖层镜像第一处理模块,用于在目标依赖包或基础依赖包发生变化时,如果应用代码为第一类型,对依赖层镜像进行更新;
依赖层镜像第二处理模块,用于在目标依赖包或基础依赖包发生变化时,如果应用代码为第二类型,不对依赖层镜像进行更新。
可选的,相关依赖信息确定模块,包括:
版本确定单元,用于根据目标依赖包对应的版本约束条件,确定目标依赖包的版本;
递归检索单元,用于对该版本的目标依赖包进行递归检索,得到目标依赖包的相关依赖信息,相关依赖信息中的基础依赖包包括:该版本的目标依赖包直接依赖的第一基础依赖包以及间接依赖的第二基础依赖包。
可选的,相关依赖信息还包括:基础依赖包的可安装版本;
依赖层镜像确定模块,具体用于根据基础依赖包的可安装版本,对基础依赖包进行安装;根据目标依赖包的版本,对目标依赖包进行安装。
可选的,本公开实施例的镜像构建装置,还包括:
判断模块,用于判断相关依赖信息中是否存在针对任一基础依赖包的版本冲突;
依赖层镜像确定模块,具体用于在不存在版本冲突时,根据相关依赖信息,安装基础依赖包及目标依赖包;
异常提示模块,用于在存在版本冲突时,显示异常提示信息。
可选的,本公开实施例的镜像构建装置,还包括:
应用层镜像更新模块,用于在应用代码更新时,重新安装应用代码,得到更新的应用层镜像。
上述装置中各模块/单元的具体细节在方法部分的实施例中已经详细说明,因此不再赘述。
应当注意,尽管在上文详细描述中提及了用于动作执行的设备的若干模块或者单元,但是这种划分并非强制性的。实际上,根据本公开的实施方式,上文描述的两个或更多模块或者单元的特征和功能可以在一个模块或者单元中具体化。反之,上文描述的一个模块或者单元的特征和功能可以进一步划分为由多个模块或者单元来具体化。
在本公开的示例性实施例中,还提供一种电子设备,包括:处理器;用于存储处理器可执行指令的存储器;其中,所述处理器被配置为执行本示例实施方式中任一所述的方法。
图4示出了用于实现本公开实施例的电子设备的计算机系统的结构示意图。需要说明的是,图4示出的电子设备的计算机系统400仅是一个示例,不应对本公开实施例的功能和使用范围带来任何限制。
如图4所示,计算机系统400包括中央处理单元401,其可以根据存储在只读存储器402中的程序或者从存储部分408加载到随机访问存储器403中的程序而执行各种适当的动作和处理。在随机访问存储器403中,还存储有系统操作所需的各种程序和数据中央处理单元401、只读存储器402以及随机访问存储器403通过总线404彼此相连。输入/输出接口405也连接至总线404。
以下部件连接至输入/输出接口405:包括键盘、鼠标等的输入部分406;包括诸如阴极射线管(crt)、液晶显示器(lcd)等以及扬声器等的输出部分407;包括硬盘等的存储部分408;以及包括诸如局域网(lan)卡、调制解调器等的网络接口卡的通信部分409。通信部分409经由诸如因特网的网络执行通信处理。驱动器410也根据需要连接至输入/输出接口405。可拆卸介质411,诸如磁盘、光盘、磁光盘、半导体存储器等等,根据需要安装在驱动器410上,以便于从其上读出的计算机程序根据需要被安装入存储部分408。
特别地,根据本公开的实施例,上文参考流程图描述的过程可以被实现为计算机软件程序。例如,本公开的实施例包括一种计算机程序产品,其包括承载在计算机可读介质上的计算机程序,该计算机程序包含用于执行流程图所示的方法的程序代码。在这样的实施例中,该计算机程序可以通过通信部分409从网络上被下载和安装,和/或从可拆卸介质411被安装。在该计算机程序被中央处理单元401执行时,执行本申请的装置中限定的各种功能。
在本公开的示例性实施例中,还提供一种计算机可读存储介质,其上存储有计算机程序,所述计算机程序被处理器执行时实现上述任意一项所述的方法。
需要说明的是,本公开所示的计算机可读存储介质例如可以是—但不限于—电、磁、光、电磁、红外线、或半导体的系统、装置或器件,或者任意以上的组合。计算机可读存储介质的更具体的例子可以包括但不限于:具有一个或多个导线的电连接、便携式计算机磁盘、硬盘、随机访问存储器、只读存储器、可擦式可编程只读存储器(eprom或闪存)、光纤、便携式紧凑磁盘只读存储器(cd-rom)、光存储器件、磁存储器件、或者上述的任意合适的组合。在本公开中,计算机可读存储介质可以是任何包含或存储程序的有形介质,该程序可以被指令执行系统、装置或者器件使用或者与其结合使用。而在本公开中,计算机可读的信号介质可以包括在基带中或者作为载波一部分传播的数据信号,其中承载了计算机可读的程序代码。这种传播的数据信号可以采用多种形式,包括但不限于电磁信号、光信号或上述的任意合适的组合。计算机可读的信号介质还可以是计算机可读存储介质以外的任何计算机可读介质,该计算机可读介质可以发送、传播或者传输用于由指令执行系统、装置或者器件使用或者与其结合使用的程序。计算机可读介质上包含的程序代码可以用任何适当的介质传输,包括但不限于:无线、电线、光缆、射频等等,或者上述的任意合适的组合。
本领域技术人员在考虑说明书及实践这里公开的发明后,将容易想到本公开的其他实施例。本申请旨在涵盖本公开的任何变型、用途或者适应性变化,这些变型、用途或者适应性变化遵循本公开的一般性原理并包括本公开未公开的本技术领域中的公知常识或惯用技术手段。说明书和实施例仅被视为示例性的,本公开的真正范围和精神由权利要求指出。
应当理解的是,本公开并不局限于上面已经描述并在附图中示出的精确结构,并且可以在不脱离其范围进行各种修改和改变。本公开的范围仅由所附的权利要求来限。