1.本发明涉及微服务架构的消息推送技术领域,尤其是一种用于微服务架构的消息推送方法、装置、计算设备与可读存储介质。
背景技术:2.随着业务发展,单体应用的架构已经不能支撑庞大的后端业务,因此服务端微服务化是必然趋势。而对于微服务的拆分,动辄拆分出几十个或上百个微服务,服务之间的通信方式不局限于同步通信,还包含了异步消息通信。异步消息通信可在一定程度上提升应用的吞吐量、降低应用的耦合度,但也增加了开发和维护的复杂度。基于消息的异步通信开发,除了本身的业务逻辑之外,还需要考虑消息传递的顺序性、消息的重复消费、消息的丢失、以及消息的重试等。
3.以旅行商城系统为例,可以根据不同的业务场景将旅行商城系统拆分为不同的服务,如机票服务、酒店服务、火车票服务、订单服务、优惠系统、以及支付系统等,而不同服务直接的状态同步、消息通知等均需借助于异步消息通信来实现。异步消息通信可以降低服务之间的耦合度,提升应用的吞吐量,保证数据的最终一致性。借助于异步消息通信机制,可以保证订单状态的最终一致性,并提升活动抢券的并发量。
4.业界通常借助于mq服务器来实现异步消息通信,主流的mq服务有rabbitmq、rocketmq、以及kafka等。而不同的消息服务器的特性不同,java操作方式也不尽相同,主流客户端框架有spring-amqp、spring-kafka等。对于消息重试,业界主要靠自定义while循环或借助于spring-retry实现。
5.对于服务间的异步消息推送,业界主要借助于mq服务器来实现,而连接mq服务器的客户端框架主要有spring-amqp和spring-kafka等。spring封装了amqp协议,对外提供了一组高度封装的api,允许任何pojo作为消息体进行消息传播。spring框架做到了开发人员对于amqp协议的无感知,在一定程度上简化了异步消息推送的操作,但是,由于不同的消息服务器特性不同,用法也不同,如rabbitmq主要涉及交换机、路由键、以及队列等概念,而kafka主要涉及消费组、分区、以及队列等概念,开发人员需要充分掌握这些特性,还需要掌握各种mq的应用特点、客户端集成框架原理、以及消息重试机制等;因此,将spring框架应用在复杂的微服架构中实现消息推送,并未做到使开发人员对于mq服务器无感知,对开发人员的技术要求仍然很高。
技术实现要素:6.为此,本发明提供了一种消息推送方法、装置、计算设备与可读存储介质,以力图解决或者至少缓解上面存在的至少一个问题。
7.根据本发明的一个方面,提供了一种消息推送方法,适用于应用开发框架,所述方法包括步骤:响应于用户的消息推送请求,对所述框架扫描到的带有注解的消息推送组件进行解析,得到所述消息推送组件的注解信息,所述注解信息包括配置信息;根据所述注解
信息为所述消息推送组件生成动态代理对象,并将所述动态代理对象注入到所述框架对应的容器中;以及执行所述消息推送组件对应的真实推送逻辑,完成消息推送。
8.可选地,在根据本发明的消息推送方法中,所述配置信息包括交换机和路由键。
9.可选地,在根据本发明的消息推送方法中,所述的对所述框架扫描到的带有注解的消息推送组件进行解析的步骤包括:利用所述框架进行组件扫描;当扫描到预定的扫描触发组件时,开始进行推送组件扫描,得到带有注解的消息推送组件;以及对所述带有注解的消息推送组件进行解析,得到所述注解中的配置信息。
10.可选地,在根据本发明的消息推送方法中,所述的根据所述注解信息为所述消息推送组件生成动态代理对象的步骤包括:将所述注解信息封装为动态代理对象的信息描述体,以此生成动态代理对象。
11.可选地,在根据本发明的消息推送方法中,所述的执行所述消息推送组件对应的真实推送逻辑的步骤包括:从所述框架对应的容器中获取对象;当所述对象为消息推送组件的动态代理对象,并且所述对象所对应的组件推送方法为默认方法时,执行所述默认方法;以及当所述对象为消息推送组件的动态代理对象,并且所述对象所对应的组件推送方法不是默认方法时,从方法缓存中获取并执行所述组件推送方法对应的方法调用器,以调取对应的推送方法,执行所述推送方法。
12.可选地,在根据本发明的消息推送方法中,所述的执行所述消息推送组件对应的真实推送逻辑的步骤还包括:当所述对象非消息推送组件的动态代理对象时,执行目标方法。
13.可选地,在根据本发明的消息推送方法中,所述应用开发框架为springboot框架;所述框架对应的容器为spring容器;所述注解包括:@rabbitpusher、@kafkapusher、@rabbitpush以及@kafkapush。
14.根据本发明的另一方面,提供了一种消息推送系统,包括:系统服务器,适于执行如上所述的方法;以及与所述系统服务器通信连接的若干个mq服务器。
15.根据本发明的另一方面,还提供了一种计算设备,包括:至少一个处理器和存储有程序指令的存储器;当程序指令被处理器读取并执行时,使得计算设备执行如上的消息推送方法。
16.根据本发明的再一方面,还提供了一种存储有程序指令的可读存储介质,当程序指令被计算设备读取并执行时,使得计算设备执行如上的消息推送方法。
17.根据本发明的消息推送方法、装置、计算设备与可读存储介质,能够实现以下有益效果中的至少一种:
18.开发人员只需要写一个简单的java组件,并选取相应的注解来修饰推送组件,无需提供推送的具体实现,真正做到开发人员对spring-ampq无感知,有效避免了开发人员编写、调试冗余的模板代码,降低了开发难度,提升了开发效率;
19.消息推送方法的成品形式为一个标准的spring boot starter,微服务只需要引入其maven依赖即可使用,starter内置了mq的常用配置,如消息序列化方式、重试机制、超时时间等配置,也支持自定义配置,支持不同mq的特性,满足了个性化需求的同时,也提高了上述消息推送方法的可移植性。
附图说明
20.为了实现上述以及相关目的,本文结合下面的描述和附图来描述某些说明性方面,这些方面指示了可以实践本文所公开的原理的各种方式,并且所有方面及其等效方面旨在落入所要求保护的主题的范围内。通过结合附图阅读下面的详细描述,本公开的上述以及其它目的、特征和优势将变得更加明显。遍及本公开,相同的附图标记通常指代相同的部件或元素。
21.图1示出了根据本发明一个实施例的消息推送系统100的示意图;
22.图2示出了根据本发明一个实施例的计算设备200的示意图;
23.图3示出了根据本发明一个实施例的消息推送方法300的流程图;
24.图4示出了根据本发明一个实施例的消息推送扫描的时序图;
25.图5示出了根据本发明一个实施例的starter整体架构图。
具体实施方式
26.下面将参照附图更详细地描述本公开的示例性实施例。虽然附图中显示了本公开的示例性实施例,然而应当理解,可以以各种形式实现本公开而不应被这里阐述的实施例所限制。相反,提供这些实施例是为了能够更透彻地理解本公开,并且能够将本公开的范围完整的传达给本领域的技术人员。
27.现有的消息推送技术除了要求开发人员掌握各种消息服务器特性和用法之外,还存在其他问题,例如:消息队列中的消息格式不统一,加大了系统对接和维护的难度;可移植性差,多个微服务引用需要不同的依赖包,并需要进行重复配置;对于消息推送过程中的消息重试,业界主要通过由开发人员编写while循环或借助于spring提供的spring-retry组件来实现。自定义while循环方式虽然灵活,但需要编写大量臃肿的代码。spring-retry使用方式更为优雅,只需要注解声明重试机制即可,但是需要编写大量重复的try-catch模板代码,而其核心推送代码却只有一行,例如:
[0028][0029][0030]
对于异常捕获,也需要编写大量冗余的模板代码,分散了开发人员注意力,降低了开发效率。
[0031]
针对现有微服务架构中的消息推送方法需要开发人员掌握各种消息服务器特性
和用法,导致开发难度大的问题,本发明提供了一种用于微服务架构的消息推送方法,只需要自定义注解即可,开发难度低,可移植性好。
[0032]
本发明的消息推送方法在计算设备中执行。计算设备可以是任意具有存储和计算能力的设备,其例如可以实现为服务器、工作站等,也可以实现为桌面计算机、笔记本计算机等个人配置的计算机,或者实现为手机、平板电脑、智能可穿戴设备、物联网设备等终端设备,但不限于此。
[0033]
图1示出了根据本发明一个实施例的消息推送系统100的示意图。
[0034]
如图1所示,消息推送系统100包括系统服务器110以及若干个mq服务器120,这里的若干个mq服务器120可以是不同的mq服务器。系统服务器110分别与若干个mq服务器120之间通信连接,例如通过有线或无线的方式网络连接。
[0035]
应当指出,本发明对系统服务器110的具体种类不作限制。例如,系统服务器110可以实现为桌面电脑、笔记本电脑、处理器芯片、手机、平板电脑等计算设备,但不限于此,也可以是驻留在计算设备上的应用程序。
[0036]
在本发明的实施例中,系统服务器110适于执行消息推送方法。本发明的消息推送方法300将在下文中详述。
[0037]
在一个实施例中,本发明的系统服务器110可以实现为一种计算设备,使得本发明的消息推送方法可以在计算设备中执行。
[0038]
图2示出了根据本发明一个实施例的计算设备200的结构图。如图2所示,在基本的配置202中,计算设备200典型地包括系统存储器206和一个或者多个处理器204。存储器总线208可以用于在处理器204和系统存储器206之间的通信。
[0039]
取决于期望的配置,处理器204可以是任何类型的处理,包括但不限于:微处理器(up)、微控制器(uc)、数字信息处理器(dsp)或者它们的任何组合。处理器204可以包括诸如一级高速缓存210和二级高速缓存212之类的一个或者多个级别的高速缓存、处理器核心214和寄存器216。示例的处理器核心214可以包括运算逻辑单元(alu)、浮点数单元(fpu)、数字信号处理核心(dsp核心)或者它们的任何组合。示例的存储器控制器218可以与处理器204一起使用,或者在一些实现中,存储器控制器218可以是处理器204的一个内部部分。
[0040]
取决于期望的配置,系统存储器206可以是任意类型的存储器,包括但不限于:易失性存储器(诸如ram)、非易失性存储器(诸如rom、闪存等)或者它们的任何组合。系统存储器106可以包括操作系统220、一个或者多个应用222以及程序数据224。应用222实际上是多条程序指令,其用于指示处理器204执行相应的操作。在一些实施方式中,应用222可以布置为在操作系统上使得处理器204利用程序数据224进行操作。
[0041]
计算设备200还可以包括储存接口总线234。储存接口总线234实现了从储存设备232(例如,可移除储存器236和不可移除储存器238)经由总线/接口控制器230到基本配置202的通信。操作系统220、应用222以及数据224的至少一部分可以存储在可移除储存器236和/或不可移除储存器238上,并且在计算设备200上电或者要执行应用222时,经由储存接口总线234而加载到系统存储器206中,并由一个或者多个处理器204来执行。
[0042]
计算设备200还可以包括有助于从各种接口设备(例如,输出设备242、外设接口244和通信设备246)到基本配置202经由总线/接口控制器230的通信的接口总线240。示例的输出设备242包括图形处理单元248和音频处理单元250。它们可以被配置为有助于经由
一个或者多个a/v端口252与诸如显示器或者扬声器之类的各种外部设备进行通信。示例外设接口244可以包括串行接口控制器254和并行接口控制器256,它们可以被配置为有助于经由一个或者多个i/o端口258和诸如输入设备(例如,键盘、鼠标、笔、语音输入设备、触摸输入设备)或者其他外设(例如打印机、扫描仪等)之类的外部设备进行通信。示例的通信设备246可以包括网络控制器260,其可以被布置为便于经由一个或者多个通信端口264与一个或者多个其他计算设备262通过网络通信链路的通信。
[0043]
网络通信链路可以是通信介质的一个示例。通信介质通常可以体现为在诸如载波或者其他传输机制之类的调制数据信号中的计算机可读指令、数据结构、程序模块,并且可以包括任何信息递送介质。“调制数据信号”可以这样的信号,它的数据集中的一个或者多个或者它的改变可以在信号中以编码信息的方式进行。作为非限制性的示例,通信介质可以包括诸如有线网络或者专线网络之类的有线介质,以及诸如声音、射频(rf)、微波、红外(ir)或者其它无线介质在内的各种无线介质。这里使用的术语计算机可读介质可以包括存储介质和通信介质二者。
[0044]
在根据本发明的计算设备200中,应用222包括执行消息推送方法300的多条程序指令,这些程序指令可以指示处理器204执行本发明的消息推送方法300,以便计算设备200执行本发明的消息推送方法300。
[0045]
根据本发明实施例的一种消息推送方法300包括步骤:响应于用户的消息推送请求,对springboot扫描到的带有注解的消息推送接口进行解析,得到所述消息推送接口定义的接口推送方法;将解析到的接口推送方法封装为bean(的信息描述体,将所述信息描述体注册到spring容器中;以及为解析到的接口生成动态代理对象,并将所述动态代理对象注入到所述spring容器中;以及根据所述spring容器执行所述接口推送方法的真实逻辑,完成消息的推送。
[0046]
图3示出了根据本发明一个实施例的消息推送方法300的流程图。方法300在计算设备(例如前述计算设备200)中执行,应用环境为springboot框架(作为应用开发框架的一种示例)。如图3所示,方法300始于步骤s310。
[0047]
为便于理解,下文中将主要采用springboot(或称springboot框架)作为应用开发框架的示例来举例描述本发明实施例的消息推送方法的实现方式,但应当理解的是,本发明的实施例并不限于此。
[0048]
在步骤s310中,响应于用户的消息推送请求,对springboot扫描到的带有注解的消息推送组件进行解析,得到所述消息推送组件的注解信息,所述注解信息包括交换机和路由键。
[0049]
需要说明的是,本实施例的组件主要指代接口。
[0050]
在一个实施例中,开发人员可以自定义如@xxxpusher形式的注解用来修饰接口,例如@rabbitpusher、@kafkapusher、@rabbitpush、以及@kafkapush等,每个接口都对应一套符合真实推送逻辑的消息推送代码,这里的消息推送代码可以采用现有技术的消息推送代码。开发人员不需要编写这些代码,在后续步骤中,方法300会自动生成并执行这些代码,完成消息的推送。
[0051]
在步骤s310中,用户根据实际需要从带有@xxxpusher形式注解的接口中选取一个,并指定推送队列、路由规则、以及重试机制等常规配置参数。以订单作为消息的实例,用
户可以选择@rabbitpusher,并注明交换机为e_rabbitmq_order,路由键为rk_rabbitmq_order,还可以设定重试次数为3次,其中,交换机和路由键是必要参数,用户需要编写的代码如下:
[0052]
@rabbitpush(exchange="e_rabbitmq_order",routingkey="rk_r abbitmq_order",retrytimes=3)
[0053]
public boolean pushorder(order order)
[0054]
可见,推送一个订单信息,只需要编写以上两行代码即可,与现有技术相比,开发难度大大降低。
[0055]
如果要同时推送订单、订单状态、以及报表导入请求,那么,用户需要编写的代码如下:
[0056][0057][0058]
接下来,系统100启动springboot,利用springboot对所有的组件进行扫描。由于springboot默认只扫描其自身规定好的一些组件,而本实施例的上述带有注解修饰的组件不在其扫描范围内,因此,需要预先定义一个扫描触发组件,即beandefinitionregistar组
件,当springboot扫描到beandefinitionregistar组件类时,会触发对上述带有注解修饰的组件的扫描动作,扫描过程中需要回调beandefinitionregistrar组件的扫描程序。扫描到带有注解的消息推送组件后,对带有注解的消息推送组件进行解析,解析的具体方式可采用常规的方法实现,解析过程完成后,即可得到注解中的配置信息,例如交换机和路由键,根据交换机和路由键可以知晓将消息推送到哪个队列。
[0059]
图4示出了根据本发明一个实施例的推送接口扫描的时序图。如图4所示,组件扫描过程利用了springboot,首先启动springboot应用,springboot应用启动后自动创建spring容器(作为应用开发框架对应的容器的示例),并完成容器标准初始化。接下来,springboot进行扫描,当扫描到自定义的beandefinitionregistar组件时,触发推送组件扫描,即,推送组件的扫描过程正式开始。扫描过程中,回调beandefinitionregistrar,执行pusherregistar,扫描本次消息推送所使用的推送组件,即步骤s310中用户选定的推送组件。
[0060]
接下来,在步骤s320中,根据注解信息为消息推送组件生成动态代理对象,并将动态代理对象注入到所述spring容器中。
[0061]
在一个实施例中,spring容器创建单实例bean,在创建单实例bean的过程中,将解析到的注解信息封装为动态代理对象的信息描述体,即beandefinition,这里的bean即指代推送组件,这样就生成了动态代理对象,然后将beandefinition注册到spring容器中,这里的注册是指在spring容器中登记一下动态代理对象。
[0062]
在一个实施例中,借助于jdk动态代理为消息推送组件生成动态代理对象。
[0063]
步骤s310和步骤320实际上是代码转化的过程。在方法300开始前,系统100内部已经设定了每个可选的消息推送组件所对应的消息推送代码,步骤s310和步骤320结束后,系统100便自动生成了用户所选择的推送组件所对应的消息推送代码。
[0064]
接下来,在步骤s330中,执行所述消息推送组件对应的真实推送逻辑,完成消息推送。调用推送组件的实质是调用推送组件的动态代理方法,执行真正的推送逻辑。
[0065]
在一个实施例中,可以按照下述过程执行消息推送的真实逻辑。首先,从spring容器中获取bean,需要说明的是,spring容器中可能会存在若干个bean,其中,一部分bean来源于带注解修饰的消息推送组件,即步骤s310中用户选择的消息推送组件,另一部分则来自其他常规的推送组件,不同的推送组件对应不同的推送逻辑。接下来,需要判断bean对应于哪类推送组件后,然后调用bean所对应的真实逻辑并执行真实逻辑,具体为:判断所获取的bean是否为消息推送组件的动态代理对象,判断依据为rabbit是否带有注解修饰,如果rabbit是没有注解修饰,则说明bean来源于常规的推送组件,不是消息推送组件的动态代理对象时,此时,执行目标方法,这里的目标方法指代与bean所对应的组件推送方法;如果rabbit带有注解修饰,则说明bean来源于步骤s310中用户选择的消息推送组件,属于动态代理对象,此时,需要进一步判断bean所对应的组件推送方法是否为默认方法,这里的默认方法指代java语法规范中的默认方法,如果是默认方法,则执行默认方法,如果不是默认方法,则从方法缓存中获取推送解耦的方法调用器,即methodinvoker,并执行methodinvoker,调用相应的组件推送方法的真实逻辑(即,常规的推送方法中,开发人员编写的用于执行消息推送任务的程序),完成消息的推送。
[0066]
消息推送逻辑的执行部分封装了消息推送的实现层,将消息内容进行了统一封
装,将消息常用且和业务无关的参数进行统一处理,如消息唯一自增id和消息时间戳等参数。
[0067]
方法300将rabbitmq的操作封装为符合spring boot开发规范的starter,实现了代码解耦。对于其他类型的服务器,例如kafka等,mq的操作可以采用与方法300相同的方式封装为starter。
[0068]
图5示出了根据本发明一个实施例的starter整体架构图。如图5所示,sboot-starter-parent为自定义starter顶级模块儿,用来定义公用的依赖和版本信息等;sboot-starter-mq为mq系列starter公用模块儿,提供自动化配置功能;sboot-starter-rabbitmq为基于rabbitmq的声明式推送实现模块;sboot-starter-kafka为基于kafka消息服务器的声明式推送实现模块;sboot-starter-xxx为扩展模块,例如扩展为rocketmq、activemq等。图中箭头示出了各模块之间的依赖和继承关系。
[0069]
本发明实施例的消息推送方法300为微服务架构中的消息推送提供了一种新的形式,所推送消息为声明式消息,即,带有注解修饰的消息,开发人员只需要选择推送接口,并指定推送队列、路由规则、以及重试机制等配置信息,无需提供推送的具体实现,便可完成不同mq服务器的消息推送。相比传统的消息推送方式,本发明实施例的消息推送方法300具以下优势:
[0070]
开发人员只需要写一个简单的java接口,并选取推送的接口方法,然后使用推送注解修饰接口中的方法即可,无需提供推送的具体实现,真正做到开发人员对spring-ampq无感知,降低了开发难度,并且有效避免了开发人员编写、调试冗余的模板代码,提升了开发效率。
[0071]
将推送的声明注解与实现分离,使开发人员更专注于业务逻辑,而无需关心消息推送实现细节,易于系统的集成化设计。
[0072]
推送逻辑的执行部分封装了消息推送的实现层,将消息内容进行了统一封装,将消息常用且和业务无关的参数进行统一处理,统一的消息格式便于不同系统之间的对接,也利于后期的升级维护。
[0073]
消息推送方法的成品形式为一个标准的spring boot starter,微服务只需要引入其maven依赖即可使用,starter内置了mq的常用配置,如消息序列化方式、重试机制、超时时间等配置,也支持自定义配置,支持不同mq的特性,满足了个性化需求的同时,也提高了上述消息推送方法的可移植性。
[0074]
可灵活配置消息的重试次数、重试间隔、以及异常机制等。
[0075]
这里描述的各种技术可结合硬件或软件,或者它们的组合一起实现。从而,本发明的方法和设备,或者本发明的方法和设备的某些方面或部分可采取嵌入有形媒介,例如可移动硬盘、u盘、软盘、cd-rom或者其它任意机器可读的存储介质中的程序代码(即指令)的形式,其中当程序被载入诸如计算机之类的机器,并被所述机器执行时,所述机器变成实践本发明的设备。
[0076]
在程序代码在可编程计算机上执行的情况下,计算设备一般包括处理器、处理器可读的存储介质(包括易失性和非易失性存储器和/或存储元件),至少一个输入装置,和至少一个输出装置。其中,存储器被配置用于存储程序代码;处理器被配置用于根据该存储器中存储的所述程序代码中的指令,执行本发明的自动校验方法。
[0077]
以示例而非限制的方式,可读介质包括可读存储介质和通信介质。可读存储介质存储诸如计算机可读指令、数据结构、程序模块或其它数据等信息。通信介质一般以诸如载波或其它传输机制等已调制数据信号来体现计算机可读指令、数据结构、程序模块或其它数据,并且包括任何信息传递介质。以上的任一种的组合也包括在可读介质的范围之内。
[0078]
在此处所提供的说明书中,算法和显示不与任何特定计算机、虚拟系统或者其它设备固有相关。各种通用系统也可以与本发明的示例一起使用。根据上面的描述,构造这类系统所要求的结构是显而易见的。此外,本发明也不针对任何特定编程语言。应当明白,可以利用各种编程语言实现在此描述的本发明的内容,并且上面对特定语言所做的描述是为了披露本发明的优选实施方式。
[0079]
在此处所提供的说明书中,说明了大量具体细节。然而,能够理解,本发明的实施例可以在没有这些具体细节的情况下被实践。在一些实例中,并未详细示出公知的方法、结构和技术,以便不模糊对本说明书的理解。
[0080]
类似地,应当理解,为了精简本公开并帮助理解各个发明方面中的一个或多个,在上面对本发明的示例性实施例的描述中,本发明的各个特征有时被一起分组到单个实施例、图、或者对其的描述中。然而,并不应将该公开的方法解释成反映如下意图:即所要求保护的本发明要求比在每个权利要求中所明确记载的特征更多特征。本领域那些技术人员应当理解在本文所公开的示例中的设备的模块或单元或组件可以布置在如该实施例中所描述的设备中,或者可替换地可以定位在与该示例中的设备不同的一个或多个设备中。前述示例中的模块可以组合为一个模块或者此外可以分成多个子模块。
[0081]
本领域那些技术人员可以理解,可以对实施例中的设备中的模块进行自适应性地改变并且把它们设置在与该实施例不同的一个或多个设备中。可以把实施例中的模块或单元或组件组合成一个模块或单元或组件,以及此外可以把它们分成多个子模块或子单元或子组件。除了这样的特征和/或过程或者单元中的至少一些是相互排斥之外,可以采用任何组合对本说明书(包括伴随的权利要求、摘要和附图)中公开的所有特征以及如此公开的任何方法或者设备的所有过程或单元进行组合。除非另外明确陈述,本说明书(包括伴随的权利要求、摘要和附图)中公开的每个特征可以由提供相同、等同或相似目的的替代特征来代替。
[0082]
此外,本领域的技术人员能够理解,尽管在此所述的一些实施例包括其它实施例中所包括的某些特征而不是其它特征,但是不同实施例的特征的组合意味着处于本发明的范围之内并且形成不同的实施例。此外,所述实施例中的一些在此被描述成可以由计算机系统的处理器或者由执行所述功能的其它装置实施的方法或方法元素的组合。因此,具有用于实施所述方法或方法元素的必要指令的处理器形成用于实施该方法或方法元素的装置。此外,装置实施例的在此所述的元素是如下装置的例子:该装置用于实施由为了实施该发明的目的的元素所执行的功能。
[0083]
如在此所使用的那样,除非另行规定,使用序数词“第一”、“第二”、“第三”等等来描述普通对象仅仅表示涉及类似对象的不同实例,并且并不意图暗示这样被描述的对象必须具有时间上、空间上、排序方面或者以任意其它方式的给定顺序。
[0084]
尽管根据有限数量的实施例描述了本发明,但是受益于上面的描述,本技术领域内的技术人员明白,在由此描述的本发明的范围内,可以设想其它实施例。此外,应当注意,
本说明书中使用的语言主要是为了可读性和教导的目的而选择的,而不是为了解释或者限定本发明的主题而选择的。