opensatck中oslo.cache模块的使用

openstack中关于oslo.cache模块,主要用于读取缓存中的数据

需要用到的模块包括oslo.cache和dogpile.cache模块

下面通过demo代码来具体说明oslo.cache模块是怎么使用的:

1. cache.conf文件,这个文件主要是一些配置信息

[cache]
memcache_servers = 127.0.0.1:11211
enabled = true
#选择相应的存储后端,不同的存储后端,对应的不同的类型,后面代码中会有演示说明
#backend = dogpile.cache.memory
backend = oslo_cache.memcache_pool

#下面是自己的配置项,可以通过oslo.config模块来配置
[feature]
caching = True
cache_time = 7200

2.cacheutils.py文件,这个文件类似于cache_utils.py文件,对oslo.cache模块进行了二次封装。这里主要是demo代码,可以脱离opensatck环境运行!

from oslo_cache import core as cache 
from oslo_config import cfg 
import sys

WEEK = 604800

CONF = cfg.CONF	#get the CONF obejct!

下面是配置“feature”配置组,“cache”配置组不用单独配置,后面可以直接调用API进行处理!
caching = cfg.BoolOpt('caching',default = True)
cache_time = cfg.IntOpt('cache_time',default=3600)

feature_group = cfg.OptGroup(
		name = 'feature',
		title = 'feature name'
)

CONF.register_group(feature_group)
CONF.register_opts([caching,cache_time],feature_group)


#load config file here
CONF(sys.argv[1:],default_config_files=['cache.conf'])

#cache.configure函数可以直接对cache配置组进行配置,配置过程也类似于上面的feature配置,具体可以查看oslo.cache中的代码!
cache.configure(CONF)  #confiure the cache group!

#下面的函数就是返回region类对象,传入的参数是CONF
#cache.configure_cache_region(CONF,region)是配置存储后端
def _get_default_cache_region(expiration_time):
    region = cache.create_region()
    if expiration_time != 0:
        CONF.cache.expiration_time = expiration_time
    cache.configure_cache_region(CONF,region)
    print("***CONF.cache.backend is %s"%(CONF.cache.backend))
    print("####configure the backend is %s"%(region.backend))
    return region

def _get_custom_cache_region(expiration_time=WEEK,
                            backend=None,
                            url=None):
    region = cache.create_region()
    region_params = {}
    if expiration_time != 0:
        region_params['expiration_time'] = expiration_time

    if backend == 'oslo_cache.dict':
        region_params['arguments'] = {'expiration_time':expiration_time}
    elif backend == 'dogpile.cache.memcached':
        region_params['arguments'] = {'url':url}
    else:
        print('old style configuration can use only dictionary or memcached backends')
    
    region.configure(backend,**region_params)
    return region

#CacheClient类就是对region的二次封装,而region中的方法,是对后端类对象方法的二次封装,后面会具体说明
class CacheClient():

    def __init__(self,region):
        self.region = region
    
    def get(self,key):
        value = self.region.get(key)
        if value == cache.NO_VALUE:
            return None
        return value
    
    def get_or_create(self,key,creator):
        return self.region.get_or_create(key,creator)
    
    def set(self,key,value):
        return self.region.set(key,value)

    def add(self,key,value):
        return self.region.get_or_create(key,lambda : value)
    
    def delete(self,key):
        return self.region.delete(key)

    def get_multi(self,keys):
        values = self.region.get_multi(keys)
        return [None if value is cache.NO_VALUE else value for value in values]
    
    def delete_multi(self,keys):
        return self.region.delete_multi(keys)

def _warn_if_null_backend():
    if CONF.cache.backend == 'dogpile.cache.null':
        print("Cache enabled with backend dogpile.cache.null.")

#这个方法就是返回一个CacheClient类对象,这个CacheClient类对象,已经进行初始化了,可以直接调用其中的method对数据进行存储和读取!
def get_client(expiration_time=0):
    """Used to get a caching client."""
    # If the operator has [cache]/enabled flag on then we let oslo_cache
    # configure the region from configuration settings.
    if CONF.cache.enabled:
        _warn_if_null_backend()
        print('_get_default_cache_region')
        print('%s'%(_get_default_cache_region(expiration_time=expiration_time)))
        return CacheClient(
                _get_default_cache_region(expiration_time=expiration_time))
    # If [cache]/enabled flag is off, we use the dictionary backend
    print('_get_custom_cache_region')
    return CacheClient(
            _get_custom_cache_region(expiration_time=expiration_time,
                                     backend='oslo_cache.dict'))

#if __name__=='__main__':
print("the caching is %s and the cache_time is %s"%(CONF.feature.caching,CONF.feature.cache_time))
#print('enable = %s and backend = %s'%(CONF.cache.enabled,CONF.cache.backend))

上面代码中,会调用cache.configure_cache_region(conf, region)函数配置存储后端,下面就这个函数进行详细的说明是如何进行配置的

configure_cache_region(conf, region)函数位于oslo_cache/core.py文件中,里面调用的是
        region.configure_from_config(config_dict,
                                     '%s.' % conf.cache.config_prefix)
config_dict是一个字典,里面是关于配置文件中的参数
config_prefix是oslo.cache
configure_from_config函数位于dogpile/cache/region.py文件中
在这个文件中调用返回的是:
return self.configure( #第一个参数是指定存储后端的名称,这里是dogpile.cache.memcached
            config_dict["%sbackend" % prefix],#prefix是cache.oslo.
            expiration_time=config_dict.get(
                "%sexpiration_time" % prefix, None
            ),
            _config_argument_dict=config_dict,
            _config_prefix="%sarguments." % prefix,
            wrap=config_dict.get("%swrap" % prefix, None),
            replace_existing_backend=config_dict.get(
                "%sreplace_existing_backend" % prefix, False
            ),
        )
下面我们再看一下self.configure函数:
在这个函数中,会调用:
backend_cls = _backend_loader.load(backend)
self.backend = backend_cls(arguments or {})
最后return self,即返回region自身!
这里的backend_cls就是后端存储类对象,然后用参数对其进行初始化!
如果在cache.conf文件中配置
[cache]
memcache_servers = 127.0.0.1:11211
enabled = true
#backend = dogpile.cache.memory
backend = oslo_cache.memcache_pool
则可以看到cache.region.backend是如下类型的对象:
configure the backend is <oslo_cache.backends.memcache_pool.PooledMemcachedBackend object at 0x7f46bb3b2d68> 
如果backend = dogpile.cache.memory,则是:
configure the backend is <dogpile.cache.backends.memory.MemoryBackend object at 0x7f7ace9541d0>
如果都不进行配置的话,
####configure the backend is <dogpile.cache.backends.null.NullBackend object at 0x7f872a8d30b8>

可以看到的是,cache中封装的是region对象的add,set ,get等方法,region对象又是封装backend中的方法!

oslo_cache.backends.memcache_pool.PooledMemcachedBackend是位于oslo_cache/backends/memcache_pool.py文件中的PooledMemcachedBackend类对象!

3.app.py文件,这个文件主要是demo代码,演示如何对缓存数据进行设置和读写的

import cacheutils
import functools

'''
nova首先创建了一个memoize装饰器,在该装饰器中首先调用get_client()获取一个CacheClient对象,
然后调用该函数的get()方法获取指定key的值,如果查不到则将该值保存到缓存中,
'''
_CACHE_TIME = 7 * 24 * 60 * 60
_CACHE = None
cl = None
cl2 = None
def memorize(func):
    @functools.wraps(func)
    def memorizer(context,image_id):
        global _CACHE	#这里用的是全局变量,不然的话,创建新的连接的时候,无法得到原来的值
        if not _CACHE:
            _CACHE = cacheutils.get_client(expiration_time=_CACHE_TIME)
            print('_CACHE is %s'%_CACHE)
        key="%s"%(func.__name__)
        key=str(key)
        value=_CACHE.get(key)
        if value is None:
            print('value is none!')
            value = func(context,image_id)
            val = _CACHE.set(key,value)
            value=_CACHE.get(key)
            print('the set return value is %s'%val)
            print('_CACHE.region = %s'%(_CACHE.region))
        return value
    return memorizer

@memorize
def id_to_glance_id(context,image_id):
    return context[image_id]

@memorize
def glance_id_to_id(context,glance_id):
    if not glance_id:
        return
    try:
        return context[galnce_id]
    except exception.NotFound:
        LOG.error('cannot find the values!')
'''
def myfun(key,value):
    global cl
    if not cl:
        cl = cacheutils.get_client(expiration_time=_CACHE_TIME)
    key=str(key)
    cl.delete(key)
    val = cl.add(key,value)
    print('cl.add return value: val = %s'%val)
    print('key = %s'%key)
    VAL = cl.get(key)
    print('VAL1 is %s'%VAL)
    cl.set(key,'jihhhhsnna')
    VAL = cl.get(key)
    print('VAL2 is %s'%VAL)
    cl1 = cacheutils.get_client(expiration_time=_CACHE_TIME)
    #cl.delete(key)
    VAL = cl1.get(key)
    print('cl1 VAL3 is %s'%VAL)
    #print("####the backend is %s"%(cl1.region.backend))
    

def myfun2(key):
    global cl2
    if not cl2:
        cl2 = cacheutils.get_client(expiration_time=_CACHE_TIME)
    key=str(key)
    print('key = %s'%key)
    Val = cl.get(key)
    print('value2 is %s'%Val)
'''
if __name__ == '__main__':
	image_id = 1234
	context = {1234:'this is image_id:1234'}
	value = id_to_glance_id(context,image_id)
	print('the value is %s'%value)
'''
	myfun('mykey',90)
	myfun2('mykey')
'''

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章