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