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

 

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