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')
'''