本发明涉及网络激活技术领域,具体涉及一种基于双轨保证生产机制的自动网络激活系统。
背景技术:
运营商全业务运营时期,融合业务、套餐业务等复杂业务不断推出,要求后端对新业务能快速激活,特别是与用户感知极强的移动、复机业务,时效性要求更高。网络激活系统作为运营商开通线、停复机线的重要生产系统,负责后端网元的快速激活。它的稳定性与高效性影响到整个开通线、停复机线的效率。
现网的网络激活系统基本存在两类模式,一是偏向依赖传统关系型数据库,二是偏向依赖内存数据库。下面简要分析下这两类模式下的不足之处。
依赖传统关系型数据库,即由传统数据库来支撑整个工单的执行。传统数据库就是整个网络激活系统的核心所在,传统数据库不仅作为静态数据的存储地,工单执行过程中产生的热数据也需要实时存放到传统关系型数据库中,并且这些热数据支撑着工单下一步的施工。但是随着运营商业务的拓展以及网络激活系统承载工单量的不断增加,在可预见的未来传统数据库会成为整个网络激活系统的性能瓶颈。
依赖内存数据库,即由传统数据库和内存数据库配合,共同支撑整个工单的执行。系统静态数据由传统数据库维护,工单执行过程全程在内存数据库中实现,产生的热数据也是先保存在内存数据库中,然后异步保存到传统数据库,传统数据库偏向承担着数据落地的作用。这样是会提高整个工单的执行效率,但是对内存数据库(如:redis)的稳定性要求极高,一旦内存数据库异常,同样会导致整个系统的瘫痪。
综合以上,会发现,这两种模式下都是对某单一类型数据库依赖极强,一旦数据库出现宕机或者其他异常,整个工单执行都会受此影响,直接影响到用户前台业务开通以及停复机业务的施工。而在日常的实际生产运维中,这种数据库宕机也是偶有发生的。所以这两种模式下,都存在一定的安全隐患,影响到整个系统的稳定。长时间宕机无法恢复情况下,极容易引起用户的投诉。为此,提出一种基于双轨保证生产机制的自动网络激活系统。
技术实现要素:
本发明所要解决的技术问题在于:如何更好地结合传统数据库与内存数据库的优缺点,保证在某一数据库异常的状况下系统能够实现稳定运行,提供了一种基于双轨保证生产机制的自动网络激活系统。
本发明是通过以下技术方案解决上述技术问题的,本发明包括:
工单接收模块,用于进行报文接收、报文持久化、报文解析、节点验证、定单对象生成工作;
工单分解模块,用于进行定单对象获取、规则解析、工单生成、数据持久化工作;
工单调度模块,用于进行工单调度、子单调度工作;
网元施工模块,用于进行指令构造、网元交互、结果解析工作;
工单报竣模块,用于进行回复器生成、回单唯一性控制、回单报文构造工作;
内存数据库通道,用于通过内存数据库优先支撑工单流转;
传统数据库通道,用于在所述内存数据库出现异常时,通过传统数据库支撑工单继续流转;
工单清除模块,用于处理工单完成后或者工单异常转入传统数据库通道之后,将内存数据库中的工单缓存数据清除;
在所述内存数据库通道中,所述工单接收模块通过内存数据库定单队列与所述工单分解模块进行交互,所述工单分解模块通过内存数据库工单施工队列与所述工单调度模块进行交互,所述工单调度模块分别通过内存数据库网元施工队列、内存数据库网元施工完成队列与所述网元施工模块进行交互,所述工单调度模块通过内存数据库工单完成队列与所述工单报竣模块进行交互;
在所述传统数据库通道中,所述工单接收模块通过传统数据库中间表与所述工单分解模块进行交互,所述工单分解模块通过传统数据库中间表与所述工单调度模块进行交互,所述工单调度模块通过传统数据库中间表分别与所述网元施工模块、所述工单报竣模块进行交互。
更进一步的,所述工单接收模块的工作流程包括以下步骤:
s11:接收上游系统报文请求;
s12:校验报文关键节点信息;
s13:持久化消息;
s14:构造定单对象放入定单队列。
更进一步的,在所述工单接收模块的工作流程中,若传统数据库异常,不影响工单执行,工单照常在内存数据库中执行,并将该模块内涉及到操作传统数据库的sql语句即持久化消息sql语句保存到hbase中,并标记为消息表备份sql,等传统数据库恢复正常再从hbase中获取对应sql语句进行消息表数据恢复;若内存数据库出现异常,即表现为入定单队列异常,此时向sws_redis_error表记录一条数据,sws_redis_error表为传统数据库的表,此表中记录的全部是入定单队列异常的定单,后续工单分解模块在传统数据库通道中取单线程轮询扫描sws_redis_error表中记录为入定单队列异常未处理的数据,此异常数据中记录的内存数据库通道中的异常工单后续进入所述工单分解模块传统数据库通道中,此后该工单全部在各模块的传统数据库通道中完成整个工单的流转。
更进一步的,所述工单分解模块包括内存数据库工单分解单元、传统数据库工单分解单元、工单分解数据同步单元;
所述内存数据库工单分解单元的工作流程包括以下步骤:
s21:从定单队列中取定单对象;
s22:规则分解生成工单对象、子单对象、工单参数对象;
s23:将工单对象、子单对象、工单参数对象存放在内存数据库缓存区,其余后续单元均可操作此工单对象的数据;
s24:将工单对象、子单对象、工单参数对象同时放入工单分解模块传统数据库数据同步队列,后续由工单分解数据同步单元从该队列获取到工单对象、子单对象、工单参数对象,并在传统数据库持久化工单对象、子单对象、工单参数对象,保证在传统数据库中该工单记录得到保存;
s25:判断工单是否为失败单,失败单不再继续处理;
s26:将非失败单工单号放入工单施工队列;
所述传统数据库工单分解单元用于扫描读取sws_redis_error表中入定单队列异常的数据并生成定单对象,生成的定单对象进入传统数据库通道流转;
所述工单分解数据同步单元用于从工单分解模块传统数据库数据同步队列中获取工单对象、子单对象、工单参数对象,并在传统数据库持久化工单对象、子单对象、工单参数对象,保证传统数据库中该工单记录得到保存。
更进一步的,在所述内存数据库工单分解单元的工作流程中,若与内存数据库缓存交互异常,则记录到传统数据库缓存清除中间表中,通知所述工单清除模块清除工单相关缓存,并将数据同步至传统数据库,同时记录到sws_redis_error表中;若传统数据库中插入数据异常,此时内存数据库缓存已经生成,将产生的sql语句拼接完成放入指定的传统数据库异常恢复队列,待传统数据库恢复后,通过系统页面数据恢复按钮操作,将异常恢复队列中的数据重新导入到传统数据库中。
更进一步的,所述工单调度模块包括内存数据库工单调度单元、传统数据库工单调度单元、工单调度数据同步单元;
所述内存数据库工单调度单元的工作线程分为两类,分别为工单调度线程与子单调度线程;
所述工单调度线程包括以下步骤:
s31:从工单施工队列中取工单号;
s32:根据工单号从内存数据库缓存中获取工单详细信息;
s33:判断该工单下未完成子单数量,如果未完成子单数量为0,则丢入工单完成队列,由工单报竣模块进行后续处理;如果未完成子单数量不为0,则将未完成子单加入子单对应的网元施工队列;
s34:将工单调度过程中产生的sql语句丢入工单调度模块传统数据库数据同步队列,由工单调度数据同步单元后续从该队列获取sql语句同步到传统数据库中;
所述子单调度线程包括以下步骤:
s41:从网元施工完成队列取出子单号;
s42:将该子单号从内存数据库缓存中的执行子单集合中删除;
s43:根据当前子单状态处理后置子单,当前子单执行成功,更新后置子单列表,并判断该子单对应的工单下是否仍有未完成子单,若无未完成子单,将该子单号对应的工单号丢入工单完成队列,后续由工单报竣模块继续处理该工单,若存在未完成子单,继续调度未完成子单,将未完成的子单丢入对应网元施工队列;当前子单执行失败,将当前子单和后置子单状态修改为待人工;
s44:将子单调度过程中产生的sql语句丢入工单调度模块传统数据库数据同步队列,由工单调度数据同步单元后续从该队列获取sql语句同步到传统数据库中;
所述传统数据库工单调度单元的工单业务操作逻辑与所述内存数据库工单调度单元相同,区别在于步骤s31的起始取单操作改为从传统数据库wo_redis_error表取单,wo_redis_error表为传统数据库中的表,该中间表记录包含了放入工单施工队列异常的工单号或放入网元施工完成队列异常的子单号以及内存数据库工单调度单元操作过程中异常的工单号或子单号。传统数据库工单调度单元完成工单处理后,该工单的后续流程全部进入各模块的传统数据库通道执行;
所述工单调度数据同步单元用于从工单调度模块传统数据库数据同步队列获取sql语句同步到传统数据库中,保证内存数据库工单调度单元产生的sql语句在传统数据库执行生效,使该工单在传统数据库得到记录。
更进一步的,在所述内存数据库工单调度单元的两类工作线程中,若执行过程中任一步骤时与内存数据库交互异常,则将该工单记录到wo_redis_error表中,标记为内存数据库工单调度环节异常单或内存数据库子单调度环节异常单,此后该工单后续流程由传统数据库工单调度单元处理。
更进一步的,所述网元施工模块包括内存数据库网元施工单元、传统数据库网元施工单元、网元施工数据同步单元;
所述内存数据库网元施工单元的工作流程包括以下步骤:
s51:从网元施工队列获取子单号;
s52:根据子单号去内存数据库缓存中查询获取对应子单相关信息(工单信息、子单信息、工单参数信息);
s53:根据子单信息、提前加载的指令模板转换为实时指令报文;
s54:通过网元交互,执行指令,对结果进行解析;
s55:记录指令执行成功或失败的相关信息(指令,网元返回报文等),将子单号丢入网元施工完成队列,由工单调度模块子单调度线程继续处理;
s56:将网元施工过程中产生的sql语句丢入网元施工模块传统数据库数据同步队列,由网元施工数据同步单元后续从该队列获取sql语句同步到传统数据库中;
所述传统数据库网元施工单元的工单业务操作逻辑与所述内存数据库网元施工单元相同,区别在于步骤s51的起始取单操作改为从传统数据库中间表wo_redis_error取单,该表中记录包含了丢入网元施工队列异常的子单号或内存数据库工单调度单元工单调度线程处理异常的子单号;网元施工模块完成此工单的处理后,该工单的后续流程全部走各模块的传统数据库通道执行;
所述网元施工数据同步单元用于从网元施工模块传统数据库数据同步队列获取sql语句并同步到传统数据库中。
更进一步的,在所述内存数据库网元施工单元的工作流程中,若执行过程中任一步骤时与内存数据库交互异常,则将该工单记录到wo_redis_error表中,标记为内存数据库网元施工环节异常单,此后该工单后续流程由传统数据库网元施工单元处理。
更进一步的,所述工单报竣模块包括内存数据库工单报竣单元、传统数据库工单报竣单元、工单报竣数据同步单元;
所述内存数据库工单报竣单元的工作流程包括以下步骤:
s61:从工单完成队列中取出工单号;
s62:判断内存数据库缓存中工单对象是否存在,如果不存在,将工单号插入传统数据库wo_redis_error表中,记录为内存数据库工单报竣环节异常单,后续该工单处理流程切换至传统数据库通道,如果存在,继续进行;
s63:根据工单来源创建不同的回复器,如停复机线,为修改原始crm(客户关系管理)表中数据状态进行报竣,服务开通线通过http接口等进行回复;
s64:如果回复成功,判断传统数据库中工单信息是否存在,以工单分解拆分工单后插入的最后一张工单参数表是否有数据为依据,如果有数据则说明传统数据库中数据已插入,只进行修改(此时工单参数表即使数据不全,工单报竣模块也不会进行修改,因此工单分解此时仍会继续进行补全),如果传统数据库中不存在数据,则将内存数据库缓存中所有工单数据获取到进行传统数据库同步操作;
s65:将工单报竣过程中产生的sql语句丢入工单报竣模块传统数据库数据同步队列,由工单报竣数据同步单元后续从该队列获取sql语句同步到传统数据库中;
所述传统数据库工单报竣单元的工单业务操作逻辑与所述内存数据库工单报竣单元相同,区别在于步骤s61的起始取单操作改为从wo_redis_error表取标记为内存数据库工单报竣环节异常单的记录;
所述工单报竣数据同步单元用于从工单报竣模块传统数据库数据同步队列获取sql语句,并同步到传统数据库中。
在所述内存数据库工单报竣单元的工作流程中,若执行过程中任一步骤时与内存数据库交互异常,则将该工单记录到wo_redis_error表中,并标记为内存数据库工单报竣环节异常单,此后该工单后续流程由传统数据库工单报竣单元处理。
本发明相比现有技术具有以下优点:该基于双轨保证生产机制的自动网络激活系统,模块间交互通过消息队列实现,并且系统采用分层结构,最大限度的降低了系统模块间的耦合度,提高了系统的鲁棒性;充分利用内存数据库和传统数据库的优点,降低了系统对数据库的单一依赖,保证了当任一数据库出现异常时,基于另一个数据库依然能支撑网络激活工单继续流转,不会导致系统瘫痪;给系统的数据库故障提供了充分的恢复时间,降低了用户的直接感知影响,使用户体验得到很大提升。
附图说明
图1是本发明中各模块之间的交互示意图;
图2是本发明中双轨制工单流程走向示意图;
图3是本发明中工单接收模块的工单执行示意图;
图4是本发明中工单分解模块的工单执行示意图;
图5是本发明中网元施工模块的工单执行示意图。
具体实施方式
下面对本发明的实施例作详细说明,本实施例在以本发明技术方案为前提下进行实施,给出了详细的实施方式和具体的操作过程,但本发明的保护范围不限于下述的实施例。
如图1~5所示,本实施例提供一种技术方案:一种基于双轨保证生产机制的自动网络激活系统,主要设计思路如下:
(1)网络激活seda理念新设计
分析现网的网络激活工单处理流程,按照seda理念重新进行整合与设计,划分为工单接收、工单分解、工单调度、网元施工、工单报竣等执行单元,由传统的j2ee软件体系改造为轻量型分布式云化架构。工单接收模块功能包括报文接收、报文持久化、报文解析、节点验证;工单分解模块功能包括规则解析、工单生成(工单、子单、工单参数)、数据持久化;工单调度模块功能包括工单调度、子单调度;网元施工模块功能包括指令构造、网元交互、结果解析;工单报竣模块功能包括回复器生成、回单唯一性控制、回单报文构造等。
新增消息队列(redislist),各模块间交互通过消息队列实现。采用这种分层结构,最大限度降低系统模块间耦合度,提高系统的鲁棒性。同时这种低耦合性也为后面实现双轨提供了保证。
(2)网络激活双通道设计
总体思路:整个工单处理流程保证每个模块优先从内存数据通道(redis缓存、redis队列)完成,并将工单数据异步保存到传统数据库保存。在本实施例中,redis即为内存数据库。redis异常情况下核心任务是通过数据处理保证工单流程转入传统数据库通道,由传统数据库支撑工单继续流转;若传统数据库异常其实并不影响工单流转,核心任务是保证sql语句的留存,等待传统数据库正常后再将sql语句记录重新执行来恢复工单的数据记录。
做出如下设计:工单接收模块为起始模块,无需分包处理。工单分解模块拆解成三个功能模块,分别为工单分解-redis模块、工单分解-db模块、工单分解-数据同步模块;工单调度模块拆解成三个功能模块,分别为工单调度-redis模块、工单调度-db模块、工单调度-数据同步模块;网元施工模块拆解成三个功能模块,分别为网元施工-redis模块、网元施工-db模块、网元施工-数据同步模块;工单报竣模块拆解成三个功能模块,分别为工单报竣-redis模块、工单报竣-db模块、工单报竣-数据同步模块。
在本实施例中,工单分解-redis模块为内存数据库工单分解单元,工单分解-db模块为传统数据库工单分解单元,工单分解-数据同步模块为工单分解数据同步单元;工单调度-redis模块为内存数据库工单调度单元,工单调度-db模块为传统数据库工单调度单元,工单调度-数据同步模块为工单调度数据同步单元;网元施工-redis模块为内存数据库网元施工单元,网元施工-db模块为传统数据库网元施工单元,网元施工-数据同步模块为网元施工数据同步单元;工单报竣-redis模块为内存数据库工单报竣单元,工单报竣-db模块为传统数据库工单报竣单元,工单报竣-数据同步模块为工单报竣数据同步单元。
下面为各模块的施工流程:
1)工单接收模块
具体施工流程如下所示:
接收上游系统报文请求;
报文关键节点信息校验;
消息持久化;
构造定单对象放入定单队列;
若传统数据库异常,不影响工单执行,工单照常在内存数据库中执行,并将该模块内涉及到操作传统数据库的sql语句即持久化消息sql语句保存到hbase中,并标记为消息表备份sql,等传统数据库恢复正常再从hbase中获取对应sql语句进行消息表数据恢复;
如果redis异常,即入定单队列异常,向sws_redis_error表记录一条数据,标记为入定单队列异常,然后通过工单分解-db模块即扫描此表数据,此表记录的redis异常工单后续全部走传统数据库通道。
下面是对sws_redis_error表内容的说明:
表1sws_redis_error表
2)工单分解模块
2.1、工单分解-redis模块
其具体施工流程如下所示:
定单队列取定单对象;
规则分解生成工单对象(工单、工单参数、子单);规则分解主要是利用开源软件drools做二次开发,通过drools实现规则集中管理,具体包括业务识别规则、子单拆分规则、业务过滤规则、子单合并规则、子单校验规则,将自动网络激活系统内各种各样的业务规则与代码分离,实现业务逻辑快速变化支撑;
将工单对象、子单对象、工单参数对象存放在redis缓存区,其余后续模块均可操作此工单对象的数据,将工单对象、子单对象、工单参数对象同时放入工单分解模块传统数据库数据同步的队列,后续由工单分解-数据同步模块从该队列获取到工单对象、子单对象、工单参数对象,并在传统数据库持久化这些对象,保证传统数据库该工单记录得到保存;
判断工单是否为失败单,失败单不再继续处理;
将非失败单工单号放入工单施工队列;
工单对象放入数据同步的异步队列,由工单分解-数据同步模块更新传统数据库消息表的状态为已分解,并在传统数据库持久化工单对象;
若与redis缓存交互异常,则记录到传统数据库缓存清除中间表中,通知工单清除模块清除工单相关缓存(工单清除模块用于处理工单完成后或者工单异常转入传统数据库通道之后,将内存数据库中的工单缓存数据清除,防止内存数据库中垃圾数据过多),并将数据同步至传统数据库,同时记录到sws_redis_error异常表中;
若传统数据库中插入数据异常,此时redis缓存已经生成,将生成的sql语句拼接完成放入指定的传统数据库异常恢复队列,待传统数据库恢复后,通过系统页面数据恢复按钮操作,将异常恢复队列中的数据重新导入到传统数据库中;
redis与传统数据库同时宕机的情况不考虑。
2.2、工单分解-db模块
工单分解-db模块的工单业务操作逻辑同工单分解-redis模块,不同之处在于起始取单操作改为从传统数据库中间表取单,通知下一个处理模块同样通过传统数据库中间表,不再通过redis队列。
2.3、工单分解-数据同步模块
从工单分解模块传统数据库数据同步队列取到sql语句,保证工单分解-redis模块产生的sql语句在传统数据库执行生效。
3)工单调度模块
3.1、工单调度-redis模块
工单调度分为工单调度线程和子单调度两类线程;
其中工单调度线程如下:
从工单施工队列中取工单号;
根据工单号从redis缓存获取工单详细信息;
判断该工单下未完成子数量;如果未完成子单数量为0,则丢入工单完成队列,由工单报竣模块进行后续处理;如果未完成子单数量不为0,则将未完成子单加入子单对应的网元施工队列;
将工单调度过程中产生的sql语句丢入工单调度模块传统数据库数据同步队列,由工单调度-数据同步模块同步到传统数据库中;
执行过程中任何一步redis交互异常,则将该工单记录到wo_redis_error表,标记为工单调度模块工单调度线程异常,此后该工单后续流程由工单调度-db模块处理;
下面是对wo_redis_error表内容的说明:
表2wo_redis_error表
子单调度线程如下:
从网元施工完成队列取出子单号;
将该子单号从redis缓存中的执行子单集合中删除;
根据当前子单状态处理后置子单,当前子单执行成功,更新后置子单列表,并判断该子单对应的工单下是否仍有未完成子单,若无未完成子单,将该子单号对应的工单号丢入工单完成队列,后续由工单报竣模块继续处理该工单,若存在未完成子单,继续调度未完成子单,将未完成的子单丢入对应的网元施工队列;当前子单执行失败,将当前子单和后置子单状态修改为待人工;
执行过程中任何一步与redis交互异常,则将该工单记录到wo_redis_err0r表,标记为工单调度模块子单调度线程异常,此后该工单后续流程由工单调度-db模块处理;
3.2、工单调度-db模块
工单调度-db模块工单业务操作逻辑同工单调度-redis模块,不同之处在于起始取单操作改为从传统数据库中间表取单,通知下一个处理模块同样通过传统数据库中间表,不再通过redis队列;
3.3、工单调度-数据同步模块
从工单调度模块传统数据库数据同步队列取到sql语句,保证工单调度-redis模块产生的sql语句在传统数据库执行生效。
4)网元施工模块
4.1、网元施工-redis模块
其具体施工流程如下所示:
从网元施工队列获取子单号;
根据子单号去redis缓存中查询获取对应子单相关信息(工单信息、子单信息、工单参数信息);
根据子单信息、提前加载的指令模板等信息转换为实时指令报文;
通过网元交互,执行指令,对结果进行解析;
记录指令执行成功或失败的相关信息(指令,网元返回报文等),将子单号丢入网元施工完成队列,由工单调度模块子单调度线程继续处理;
执行过程中任何一步与redis交互异常,记录该工单到wo_redis_error表,标记为网元施工模块redis异常,后续由网元施工-db模块处理;
4.2、网元施工-db模块
网元施工-db模块工单业务操作逻辑同网元施工-redis模块,不同之处在于起始取单改为从传统数据库中间表取单,通知下一个处理模块同样通过传统数据库中间表,不再通过redis队列;
4.3、网元施工-数据同步模块
从网元施工模块传统数据库数据同步队列取到sql语句,保证网元施工-redis模块产生的sql语句在传统数据库执行生效。
5)工单报竣模块
5.1、工单报竣-redis模块
其具体施工流程如下所示:
从工单完成队列中取出工单号;
判断redis缓存中工单对象是否存在;如果不存在,工单号插入缓存异常中间表,切换至纯数据库模块(此处是否应该为传统数据库模块);如果存在,继续进行;
根据工单来源创建不同的回复器;如停复机线,为修改原始crm表中数据状态进行报竣;服务开通线通过http接口等进行回复;
如果回复成功,判断传统数据库中工单信息是否存在,以工单分解拆分工单后插入的最后一张工单参数表是否有数据为依据,如果有数据则说明传统数据库中数据已插入,只进行修改(此时工单参数表即使数据不全,工单报竣模块也不会进行修改,因此工单分解此时仍会继续进行补全);如果传统数据库中不存在数据,则将redis缓存中所有工单数据获取进行传统数据库同步操作;
执行过程中任何一步与redis交互异常,记录该工单到wo_redis_error表,标记为工单报竣模块redis异常,后续由工单报竣-db模块处理;
5.2、工单报竣-db模块
工单报竣-db模块工单业务操作逻辑同工单报竣-redis模块,不同之处在于起始取单操作改为从传统数据库中间表取单,不再通过redis队列;
5.3、工单报竣-数据同步模块
从工单报竣模块传统数据库数据同步队列取到sql语句,保证工单报竣-redis模块产生的sql语句在传统数据库执行生效。
需要说明的是,hbase不同于一般的关系型数据库,它是一个适合于非结构化数据存储、面向列的的开源数据库,可以给行数据定义各种不同的列,达到简化设计和升级的成本。此处使用hbase来临时保存系统各环节持久化传统数据库异常的sql语句,以待传统数据库正常后获取sql语句重新执行,保证传统数据库的工单记录不丢失。
综上所述,本实施例的基于双轨保证生产机制的自动网络激活系统,模块间交互通过消息队列实现,并且系统采用分层结构,最大限度的降低了系统模块间的耦合度,提高了系统的鲁棒性;充分利用内存数据库和传统数据库的优点,降低了系统对数据库的单一依赖,保证了当任一数据库出现异常时,基于另一个数据库依然能支撑网络激活工单继续流转,不会导致系统瘫痪;给系统的数据库故障提供了充分的恢复时间,降低了用户的直接感知影响,使用户体验得到很大提升,值得被推广使用。
此外,术语“第一”、“第二”仅用于描述目的,而不能理解为指示或暗示相对重要性或者隐含指明所指示的技术特征的数量。由此,限定有“第一”、“第二”的特征可以明示或者隐含地包括至少一个该特征。在本发明的描述中,“多个”的含义是至少两个,例如两个,三个等,除非另有明确具体的限定。
在本说明书的描述中,参考术语“一个实施例”、“一些实施例”、“示例”、“具体示例”、或“一些示例”等的描述意指结合该实施例或示例描述的具体特征、结构、材料或者特点包含于本发明的至少一个实施例或示例中。在本说明书中,对上述术语的示意性表述不必须针对的是相同的实施例或示例。而且,描述的具体特征、结构、材料或者特点可以在任一个或多个实施例或示例中以合适的方式结合。此外,在不相互矛盾的情况下,本领域的技术人员可以将本说明书中描述的不同实施例或示例以及不同实施例或示例的特征进行结合和组合。
尽管上面已经示出和描述了本发明的实施例,可以理解的是,上述实施例是示例性的,不能理解为对本发明的限制,本领域的普通技术人员在本发明的范围内可以对上述实施例进行变化、修改、替换和变型。