具体实施方式
这里将详细地对示例性实施例进行说明,其示例表示在附图中。下面的描述涉及附图时,除非另有表示,不同附图中的相同数字表示相同或相似的要素。以下示例性实施例中所描述的实施方式并不代表与本发明相一致的所有实施方式。相反,它们仅是与如所附权利要求书中所详述的、本发明的一些方面相一致的装置和方法的例子。
在本发明使用的术语是仅仅出于描述特定实施例的目的,而非旨在限制本发明。在本发明和所附权利要求书中所使用的单数形式的“一种”、“所述”和“该”也旨在包括多数形式,除非上下文清楚地表示其他含义。还应当理解,本文中使用的术语“和/或”是指并包含一个或多个相关联的列出项目的任何或所有可能组合。
应当理解,尽管在本发明可能采用术语第一、第二、第三等来描述各种信息,但这些信息不应限于这些术语。这些术语仅用来将同一类型的信息彼此区分开。例如,在不脱离本发明范围的情况下,第一信息也可以被称为第二信息,类似地,第二信息也可以被称为第一信息。取决于语境,如在此所使用的词语“如果”可以被解释成为“在……时”或“当……时”或“响应于确定”。
在现有技术中,为函数接入缓存时,对函数内的业务代码的改动示例如下:
函数的原始业务代码逻辑如下:
函数名A(参数1,参数2,……)
{
业务代码;
返回业务处理结果;
}
对函数内的业务代码逻辑改动后变为:
函数名A(参数1,参数2,……)
{
If(命中缓存){
返回缓存处理结果;
}
业务代码;
将代码存入缓存;
返回业务处理结果;
}
由此可见看出,由于函数内的业务代码逻辑被改动,因此现有接入缓存方式对业务代码的侵入性强,并且如果多个函数都要接入缓存,需要将同样的代码流程分别写在每个函数内,接入过程繁琐。
为解决上述技术问题,本发明提出一种改进的函数接入缓存方法,通过检测被调用函数是否要接入缓存,若是,则获取被调用函数的函数名包含的缓存关键词和原函数名,并从预设函数配置关系表中获取原函数名对应的缓存配置,进而根据获取的缓存配置组建接入缓存的访问标识,并基于访问标识实现所述缓存关键词对应的接入缓存操作。
基于上述描述可知,函数提供方在不改动函数内的业务代码逻辑情况下,根据被调用函数便可实现函数接入缓存的识别,接入过程即简单又快速,并且代码侵入性小。函数提供方通过获取被调用函数的函数名包含的缓存关键词和原函数名,由于不同的缓存关键词可以给函数赋予不同的接入缓存操作,因此通过缓存关键词和组建出的访问标识可以灵活处理函数的缓存结果。另外,由于不同的函数对应有不同的缓存配置,因此针对不同的函数使用环境可以有一个可调节的适配场景。
下面以具体实施例对本发明提出的函数接入缓存方法进行详细阐述。
实施例一:
图1为本发明根据一示例性实施例示出的一种函数接入缓存方法的实施例流程图,所述函数接入缓存方法应用于函数提供方,函数提供方指的是用于向函数调用方提供调用请求的处理结果的设备。如图1所示,所述函数接入缓存方法包括如下步骤:
步骤101:检测被调用函数是否要接入缓存。
其中,被调用函数是函数调用方发送的调用请求指示要调用的函数。接入缓存指的是针对被调用函数的调用请求需要通过接入缓存的方式进行处理,并将处理结果返回给函数调用方。
针对步骤101的具体实现过程,如图2所示,包括以下步骤:
步骤1011:判断被调用函数所属的类是否接入缓存文件。
在执行步骤1011之前,可以通过接收来自函数调用方针对被调用函数的调用请求,并根据调用请求确定被调用函数所属的类。
其中,函数提供方拥有多种不同类的对象,每一类中又包含多个实现不同功能的函数,函数调用方在调用某一函数时,需要知道该函数属于哪个类才能进行调用,因此调用请求中会携带函数所属类的信息。
另外,由于只要某个类中函数有接入缓存的需求,那么这个类就要用到缓存,对于要用到缓存的类,均需要布置判定接入缓存的代码,因此可以将需要用到缓存的类引入一个缓存文件。
在具体实施时,traits萃取机制的作用是引入traits文件中的类都可以使用traits的方法,因此为了降低代码冗余度,提高代码的复用度,缓存文件可以采用traits文件,并在traits文件中布置用于判定接入缓存的traits方法,只要有调用方调用引入traits文件中的类的函数,便可调用该traits方法实现接入缓存的判定。
步骤1012:若是,则判断所属的类中是否有被调用函数的函数名,若有该函数名,则执行步骤1013,若没有该函数名,则执行步骤1014;
步骤1013:确定被调用函数要接入缓存;
步骤1014:确定被调用函数不要接入缓存。
需要说明的是,如果判定被调用函数不需要接入缓存,则按照正常处理流程执行,即直接调用执行该被调用函数。
步骤102:若是,则获取被调用函数的函数名包含的缓存关键词和原函数名。
在一可选的实施例中,可以利用预设的各个缓存关键词与被调用函数的函数名分别进行匹配,并将匹配成功的缓存关键词作为函数名包含的缓存关键词,进而将所述函数名所包含的缓存关键词去掉后,可以获得原函数名。
其中,函数提供方本地需要预存各种不同缓存关键词,以用于与函数调用方调用的函数名进行匹配,并且不同的缓存关键词可以对应设置不同的接入缓存操作,以使调用方通过缓存关键词灵活处理所调用函数的缓存结果,因此函数提供方根据匹配到的缓存关键词便可识别出函数调用方的具体缓存调用需求。
举例来说,缓存关键词为FromCache,表示函数调用方要求使用函数的缓存结果返回;缓存关键词为Flash,表示函数调用方要求使用新的函数执行结果刷新函数的缓存结果;缓存关键词为DelCache,表示函数调用方要求删除函数的缓存结果;缓存关键词为CacheKey,表示函数调用方要求返回缓存结果的访问标识。
另外,被调用函数的函数名所包含的原函数名指的是函数提供方本地真实存在的函数。
在具体实施时,由于_call()魔术方法的作用是当调用当前类中未声明或没权限调用的方法时,就会自动调用_call()方法,来避免错误产生,因此本发明可以采用_call()魔术方法识别被调用函数的函数名包含的缓存关键词和原函数名,即当函数调用方调用的函数并不是一个真实存在的函数时,通过调用_call()方法进行缓存关键词和原函数名的识别。
例如,假设函数调用方将函数名getUserByID改造成为getUserByIDFromCache,FromCache是用于指示函数将要使用函数的缓存结果返回,当函数提供方接收到getUserByIDFromCache的调用请求时,由于当前类中并不存在函数getUserByIDFromCache(),此时会自动调用__call()方法检测缓存关键词FromCache和原函数名getUserByID。
步骤103:从预设函数配置关系表中获取原函数名对应的缓存配置,并根据获取的缓存配置组建接入缓存的访问标识。
可选的,预设函数配置关系表中预存有各个需要接入缓存的函数(即真实存在的函数)对应的缓存配置,因此针对缓存配置获取的过程,可以从预设函数配置关系表中查找原函数名,并获取查找到的原函数名对应的缓存配置。
其中,缓存配置用于控制函数的执行结果在缓存中的存储。
可选的,缓存配置可以包括执行结果的缓存版本号、有效时长、存储的介质的介质标识。
有效时长指的是函数的执行结果在缓存中存储多久过期,例如,假设函数A中的数据更新频率低,可以为其设置较长的有效时长,函数B中的数据更新频繁,可以为其设置较短的有效时长。
缓存版本号指的是函数返回的执行结果格式发生改变的次数,如果函数返回的执行结果格式发生了改变,这时原来返回的执行结果不能再使用,但原来的执行结果设置的有效时长还未过期,这时需要变更缓存版本号来让原来的执行结果失效。从而本发明通过批量变更各个函数的缓存版本号,可以达到批量重置缓存数据的目的。
基于此,针对根据获取的缓存配置组建接入缓存的访问标识的过程,可以根据缓存版本号、被调用函数的输入参数、以及原函数名组建接入缓存的访问标识。
其中,输入参数是函数调用方在发送调用请求时定义的具体输入函数的数值。访问标识为调用缓存时使用的唯一key,也就是说,在缓存中按照访问标识存储函数的执行结果,如果函数的输入参数、函数名、缓存版本号中的任一项发生改变,组建出的访问标识便不同。
需要说明的是,缓存需要支持key-value类存储,存储介质可以是redis,mongodb,memcached等。
在一可选的具体实施方式中,由于不同函数的输入参数长度差异比较大,而缓存版本号的长度差异和函数名的长度差异并不大,如果直接进行访问标识组建,那么访问标识长度差异也比较大,而当访问标识长度超过一定长度时会被缓存引擎截断,为了避免该问题,通过将输入参数加密为固定长度的字符序列,然后将缓存版本号、原函数名、以及字符序列按照预设顺序组合为访问标识,使得访问标识长度差异不会很大,同时访问标识的加密稳定性也得到保障。
优选的,可以采用md5加密方法将各种长度的输入参数均转换为固定长度的字符长度。
可选的,访问标识key的组建格式为:cache:method:{版本号}:{函数名}:{加密后的输入参数}。
举例来说,假设函数func1的缓存版本号为v1,有效时长3600秒,介质标识为Redis的标识;函数func2的缓存版本号为v2,有效时长1200秒,介质标识为Elasticsearch的标识。
那么调用func1()时,组建得到的访问标识key是:
cache:method:v1:func1:c4ca4238a0b923820dcc509a6f75849b;
调用func2()时,组建得到的访问标识可以是:
cache:method:v2:func2:c81e728d9d4c2f636f067f89cc14862c。
由上述例子可以看出,加密后的输入参数长度均为32个字符长度。
步骤104:基于访问标识实现所述缓存关键词对应的接入缓存操作。
其中,基于上述步骤102的描述,不同缓存关键词赋予的是不同的接入缓存操作,例如,缓存关键词FromCache赋予的是使用函数的缓存结果返回;缓存关键词Flash赋予的是刷新函数的缓存结果;缓存关键词DelCache赋予的是删除函数的缓存结果;缓存关键词CacheKey赋予的是返回缓存结果的访问标识。
下面对缓存关键词Flash、DelCache、以及CacheKey的具体操作过程进行介绍:
缓存关键词Flash对应的操作过程为:通过执行原函数名对应的函数,并获取缓存配置中的介质标识,然后在所述介质标识对应的缓存中,利用得到的函数执行结果刷新访问标识对应的缓存数据,并向函数调用方返回该函数执行结果。
缓存关键词DelCache对应的操作过程为:获取缓存配置中的介质标识,从所述介质标识对应的缓存中删除访问标识对应的缓存数据。
缓存关键词CacheKey对应的操作过程为:将访问标识返回给函数调用方。
需要说明的是,对于缓存关键词FromCache的具体操作过程可以参见下述实施例的具体描述,本发明在此暂不进行详述。
至此,完成上述图1所示的处理流程,在不需要改动函数内的业务代码逻辑情况下,函数提供方根据被调用函数便可实现函数接入缓存的识别,接入过程即简单又快速,并且代码侵入性小。函数提供方通过获取被调用函数的函数名包含的缓存关键词和原函数名,由于不同的缓存关键词可以给函数赋予不同的接入缓存操作,因此通过缓存关键词和组建出的访问标识可以灵活处理函数的缓存结果。另外,由于不同的函数对应有不同的缓存配置,因此针对不同的函数使用环境可以有一个可调节的适配场景。
实施例二:
图3为本发明根据图1所示实施例示出的一种使用函数缓存结果的实现流程示意图,包括如下步骤:
步骤301:从介质标识对应的存储介质中,读取访问标识对应的函数调用结果。
其中,基于上述实施例中步骤103的描述,函数的缓存配置中包含有执行结果存储的介质的介质标识,因此在读取数据时,需要从相应的存储介质中,读取访问标识key对应的缓存数据即为函数调用结果。
需要说明的是,如果相应的存储介质中有该访问标识key,表示命中缓存,可以读取到已缓存的函数调用结果,如果相应的存储介质中没有该访问标识key,表示未命中缓存,说明可能是函数的缓存版本号发生变更,也可能是函数有新的输入参数,存储介质中还未缓存新版本号或新输入参数的执行结果,需要重新调用执行一次函数进行存储和返回。
步骤302:如果读取成功,则将读取到的函数调用结果返回给函数调用方。
步骤303:如果读取失败,则执行原函数名对应的函数以得到函数执行结果。
其中,基于上述实施例中步骤102的描述,由于被调用函数的函数名是由原函数名和缓存关键词拼接得到的,其并不是真实存在的函数,而原函数名才是真实存在的函数,因此需要将被调用函数的输入参数输入原函数名对应的函数中进行执行,以获得最新的函数执行结果。
需要说明的是,输入参数的具体数值不同,得到的执行结果不同,并且如果函数中的代码逻辑变更,即使与原来输入相同的输入参数,得到的执行结果也不同。
步骤304:将访问标识与函数执行结果存储至介质标识对应的存储介质中,并为所述函数执行结果设置缓存时间。
其中,无论函数返回的是异常的执行结果,还是正常的执行结果,在本发明中均会将其存储至对应的存储介质中,以保障服务稳定性。
例如,在实际应用中,当存在函数A->函数B->函数C这种链式调用时,如果函数B异常报错,会出现所有调用函数B的业务都抛出异常的情况,导致后续的业务无法进行,影响用户的使用体验,而如果将函数B抛出的异常执行结果也缓存下来,可以保证后续的业务继续进行,避免因服务异常造成的业务连锁崩溃问题。
在一可选的具体实施方式中,为了避免同一函数的不同执行结果采用相同的缓存时间,导致执行结果在某一刻同时失效,请求全部转发的存储层,存储层瞬时压力超载,造成缓存雪崩问题。基于上述实施例中步骤103的描述,函数的缓存配置包含有效时长,本发明采用的缓存时间设置过程可以是:如果函数执行结果为正常,则为所述函数执行结果设置有效时长加/减一个随机值的缓存时间;如果函数执行结果为空,则为所述函数执行结果设置第一预设时长的缓存时间;如果函数执行结果为异常,则为所述函数执行结果设置第二预设时长的缓存时间。
其中,第一预设时长和第二预设时长均小于缓存配置中的有效时长。对于函数返回的空执行结果,也一样进行存储,只是缓存时间固定在第一预设时长,例如600秒,对于函数返回异常执行结果,出于对业务的冗余处理,也一样进行存储,只是缓存时间固定在第二预设时长,例如300秒。
由此可见,即使函数的不同执行结果是同时存入缓存,由于相同的有效时长要加/减一个随机值,因此可以保证不同执行结果在不同时间过期,避免出现缓存雪崩的问题。另外,对于一些异常返回情况,即执行结果为空或者执行结果异常,本发明通过为执行结果设置一个较短的缓存时间,防止这类无效的请求频繁查询。
至此,完成上述图3所示的流程,在接入缓存操作是使用函数缓存结果时,直接从缓存读取访问标识对应的函数调用结果返回给函数调用方,以保证响应速度,而如果读取失败,通过重新调用执行一次函数进行执行结果返回,同时无论函数返回的是异常的执行结果,还是正常的执行结果,均会将其存储至对应的存储介质中,以此保障服务的稳定性。
与前述函数接入缓存方法的实施例相对应,本发明还提供了函数接入缓存装置的实施例。
图4为本发明根据一示例性实施例示出的一种函数接入缓存装置的结构示意图,该装置用于执行上述图1至图3任一实施例提供的函数接入缓存方法,如图4所示,该函数接入缓存装置包括:
监控模块410,用于检测被调用函数是否要接入缓存;
关键词抓取模块420,用于在检测到被调用函数要接入缓存时,获取所述被调用函数的函数名包含的缓存关键词和原函数名;
组建模块430,用于从预设函数配置关系表中获取所述原函数名对应的缓存配置,并根据获取的缓存配置组建接入缓存的访问标识;
调用模块440,用于基于所述访问标识实现所述缓存关键词对应的接入缓存操作。
上述装置中各个单元的功能和作用的实现过程具体详见上述方法中对应步骤的实现过程,在此不再赘述。
实施例三:
本发明还提供了另一种函数接入缓存的方法,图5为本发明根据一示例性实施例示出的另一种函数接入缓存方法的实施例流程图,在上述图1至图3所示实施例的基础上,该函数接入缓存方法是应用于函数调用方,如图5所示,该函数接入缓存方法包括如下步骤:
步骤501:确定待进行的接入缓存操作对应的缓存关键词。
其中,基于上述实施例中步骤102的描述,函数调用方本地也需要预存各种不同接入缓存操作对应的缓存关键词,以用于后续使用与原函数的函数名进行拼接。
步骤502:将待调用原函数的函数名和所述缓存关键词拼接成被调用函数名。
也就是说,被调用函数名由待调用原函数的函数名和缓存关键词组成。
步骤503:获取待调用原函数的输入参数,并生成包含所述被调用函数名和所述输入参数的调用请求。
其中,输入参数的具体数值根据实际应用需求得到。
举例说明,假设待调用原函数为:函数名A(参数1,参数2),如果待进行的接入缓存操作对应的缓存关键词为AFromCache,那么拼接成的被调用函数名为函数名AFromCache,对应的调用请求为:函数名AFromCache(参数1,参数2)。
步骤504:将调用请求发送至函数提供方,以使函数提供方返回所述接入缓存操作的结果。
其中,函数提供方接收到该调用请求后,便会执行上述图1至图3所示实施例的流程。
至此,完成上述图5所示流程,函数调用方通过将待进行的接入缓存操作对应的缓存关键词与待调用原函数的函数名拼接成被调用函数名,以告知函数提供方此次的调用要进行接入缓存操作,这样便可实现函数调用方自主决定是否需要接入缓存。并且函数调用方还可以通过不同的缓存关键词告知函数提供方要进行不同的接入缓存操作,以实现灵活处理所调用函数的缓存结果的目的。
与前述函数接入缓存方法的实施例相对应,本发明还提供了函数接入缓存装置的实施例。
图6为本发明根据一示例性实施例示出的另一种函数接入缓存装置的结构示意图,该装置用于执行上述图5实施例提供的函数接入缓存方法,如图6所示,该函数接入缓存装置包括:
关键词确定模块610,用于确定待进行的接入缓存操作对应的缓存关键词,
拼接模块620,用于将待调用原函数的函数名和所述缓存关键词拼接成被调用函数名;
请求生成模块630,用于获取所述待调用原函数的输入参数,并生成包含所述被调用函数名和所述输入参数的调用请求;
发送模块640,用于将所述调用请求发送至函数提供方,以使所述函数提供方返回所述接入缓存操作的结果。
上述装置中各个单元的功能和作用的实现过程具体详见上述方法中对应步骤的实现过程,在此不再赘述。
对于装置实施例而言,由于其基本对应于方法实施例,所以相关之处参见方法实施例的部分说明即可。以上所描述的装置实施例仅仅是示意性的,其中所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部模块来实现本发明方案的目的。本领域普通技术人员在不付出创造性劳动的情况下,即可以理解并实施。
本发明实施方式还提供一种与前述实施方式所提供的函数接入缓存方法对应的电子设备,以执行上述函数接入缓存方法。
图7为本发明根据一示例性实施例示出的一种电子设备的硬件结构图,该电子设备包括:通信接口601、处理器602、存储器603和总线604;其中,通信接口601、处理器602和存储器603通过总线604完成相互间的通信。处理器602通过读取并执行存储器603中与函数接入缓存方法的控制逻辑对应的机器可执行指令,可执行上文描述的函数接入缓存方法,该方法的具体内容参见上述实施例,此处不再累述。
本发明中提到的存储器603可以是任何电子、磁性、光学或其它物理存储装置,可以包含存储信息,如可执行指令、数据等等。具体地,存储器603可以是RAM(Random AccessMemory,随机存取存储器)、闪存、存储驱动器(如硬盘驱动器)、任何类型的存储盘(如光盘、DVD等),或者类似的存储介质,或者它们的组合。通过至少一个通信接口601(可以是有线或者无线)实现该系统网元与至少一个其他网元之间的通信连接,可以使用互联网、广域网、本地网、城域网等。
总线604可以是ISA总线、PCI总线或EISA总线等。所述总线可以分为地址总线、数据总线、控制总线等。其中,存储器603用于存储程序,所述处理器602在接收到执行指令后,执行所述程序。
处理器602可能是一种集成电路芯片,具有信号的处理能力。在实现过程中,上述方法的各步骤可以通过处理器602中的硬件的集成逻辑电路或者软件形式的指令完成。上述的处理器602可以是通用处理器,包括中央处理器(Central Processing Unit,简称CPU)、网络处理器(Network Processor,简称NP)等;还可以是数字信号处理器(DSP)、专用集成电路(ASIC)、现成可编程门阵列(FPGA)或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件。可以实现或者执行本申请实施例中的公开的各方法、步骤及逻辑框图。通用处理器可以是微处理器或者该处理器也可以是任何常规的处理器等。结合本申请实施例所公开的方法的步骤可以直接体现为硬件译码处理器执行完成,或者用译码处理器中的硬件及软件模块组合执行完成。
本申请实施例提供的电子设备与本申请实施例提供的函数接入缓存方法出于相同的发明构思,具有与其采用、运行或实现的方法相同的有益效果。
本申请实施方式还提供一种与前述实施方式所提供的函数接入缓存方法对应的计算机可读存储介质,请参考图8所示,其示出的计算机可读存储介质为光盘30,其上存储有计算机程序(即程序产品),所述计算机程序在被处理器运行时,会执行前述任意实施方式所提供的函数接入缓存方法。
需要说明的是,所述计算机可读存储介质的例子还可以包括,但不限于相变内存(PRAM)、静态随机存取存储器(SRAM)、动态随机存取存储器(DRAM)、其他类型的随机存取存储器(RAM)、只读存储器(ROM)、电可擦除可编程只读存储器(EEPROM)、快闪记忆体或其他光学、磁性存储介质,在此不再一一赘述。
本申请的上述实施例提供的计算机可读存储介质与本申请实施例提供的函数接入缓存方法出于相同的发明构思,具有与其存储的应用程序所采用、运行或实现的方法相同的有益效果。
本领域技术人员在考虑说明书及实践这里公开的发明后,将容易想到本发明的其它实施方案。本发明旨在涵盖本发明的任何变型、用途或者适应性变化,这些变型、用途或者适应性变化遵循本发明的一般性原理并包括本发明未公开的本技术领域中的公知常识或惯用技术手段。说明书和实施例仅被视为示例性的,本发明的真正范围和精神由下面的权利要求指出。
还需要说明的是,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、商品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、商品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、商品或者设备中还存在另外的相同要素。
以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内,所做的任何修改、等同替换、改进等,均应包含在本发明保护的范围之内。