概述

主要分享下个人对Liberty版本openstack中cache使用的理解,由于作者水平有限,难免有所错误,疏漏,还望批评指正。

openstack中可以使用cache层来缓存数据,Liberty版本主要有以下几种场景:

  • 存储函数执行结果 keystone heat nova等项目把一些固定的属性和查询请求的结果放到cache里面,加速访问。
  • 存储keystone token token创建完成之后,不需要修改,会有大量的读操作,适合放到cache中
  • 存储keystonemiddleware token 为neutron,cinder,nova等各个项目缓存从keystone获得的token。
  • 存储horizon用户会话数据 主要是django支持使用

存储函数执行结果

优势在于,很多查询函数的结果是固定的,但是又比较常用,查询一次之后,按照key-value存到cache中,再次查询时不需要访问数据库,直接从内存缓存中根据key将结果取出,可以提高很多速度。或者还有一些查询请求,查询的参数千变万化,但是结果只有固定的几类,这种更适合使用cache加速。

Liberty 版本openstack主要是nova和keystone这方面用的比较多,来看nova中的一个例子:

def get_instance_availability_zone(context, instance):
"""Return availability zone of specified instance."""
host = instance.get('host')
if not host:
# 如果虚拟机还没有被分配到主机上,就把创建虚拟机时指定的zone信息取出返回
az = instance.get('availability_zone')
return az #虚拟机所在的zone取决于虚拟机所在物理机的归属的zone,所以可以生成一个
#'azcache-主机名'样式的字符串作为cache key
cache_key = _make_cache_key(host)
#获取一个连接cache的client
cache = _get_cache()
#尝试取出这个key在cache中的值,作为zone信息,可能为空,也可能直接是结果
az = cache.get(cache_key)
#取出实例对象中的availability_zone属性
az_inst = instance.get('availability_zone')
if az_inst is not None and az != az_inst:
#对象属性中有zone信息,且和cache取到的zone信息不一致,那么需要重新获取zone信息
#并且更新到cache中
az = None
if not az:
#如果cache中没有取到zone信息,或者是在上一步中zone信息被清空,重新获取zone信息
elevated = context.elevated()
az = get_host_availability_zone(elevated, host)
#更新cache
cache.set(cache_key, az)
#返回zone信息
return az

这样除第一次查询到这台物理机上的虚拟机外,查询这台物理机上的任何虚拟机所属的zone,再也不需要访问数据库,这样极大地减少了对数据库的请求数量,提高了响应速度。

这里支持的cache后端包括memcached,redis,mongondb或者是python的dict.目前主流openstack发行版推荐的选项是memcached,简单稳定,性能和功能够用。

存储keystone token

keystone中除了Fernet格式的token外,其他格式的token都需要keystone由存储起来,存储支持以下几种driver:

  • sql 将token存放在数据库中,使用这种方法需要定期清理过期token,防止token表太大影响性能。
  • memcache 将token存放到memcache中,token本身创建之后不会被修改,只会被读,所以很适合放到cache中,加速访问,放到cache中也不需要写脚本定期清理数据库中的过期token。
  • memcache_pool 在memcache的基础上,实现了memcache的连接池,可以在线程之间复用连接。

一个常见的memcache token driver的配置可能是这样的:

[token]
caching = true
provider = keystone.token.providers.uuid.Provider
driver = keystone.token.persistence.backends.memcache.Token
[memcache]
servers = controller-1:11211,controller-2:11211,controller-3:11211

memcache driver的缺点在于,memcache本身是分布式的设计,但是并不是高可用的,如果controller-1上的的cache服务被重启,这个节点上的所有token都会丢失掉,会带来一些错误。

比这更糟糕的是,如果controller1网络不可达或者宕机,那么我们会观察到几乎每个openstack api请求都会有3s以上的卡顿。这是因为openstack默认使用python-memcached访问memcache,它提供的操作keystone的client继承自Thread.local类,和构建它的线程绑定。openstack服务启动后,会启动一定数量的子进程,每个http request到达,会有一个子进程接收,孵化一个线程去处理这个请求。如果用到memcache,线程会调用python-memcached

构建一个client类,通过这个client的实例对memcache进行操作。如果访问到网络不可达的memcache节点,卡住,操作超时,将这个节点标识为30秒内不可用,在这个线程内,不会再因此而卡住,但是这个http请求结束之后,下一个http请求过来,重新孵化的线程会reinit这个client,新的client丢失了旧的client的状态,还是可能会访问到卡住的memcache节点上。

社区之所以要做memcache_pool,就是为了解决这个问题,将client统一由pool管理起来,memcache节点的状态,也由pool管理起来,这样每个子进程里只会卡第一次,所以强烈推荐使用memcache_pool驱动而不是memcache。社区将memcache_pool的代码从keystone复制到oslo_cache项目中,希望所有使用memcache的项目都通过它的memcachepool去访问,避免这个问题。其中,nova在M版本支持,heat在L版本支持。

具体的各个服务如何配置使用memcache_pool driver这里不再赘述。

存储keystonemiddleware token

我们请求任何openstack服务时,该服务都要校验请求中提供的token是否合理,这部分代码显然不是每个项目都自己实现一遍,它在keystonemiddleware项目实现,并作为filter配置在各个项目的api-paste.ini文件中,如下所示:

[filter:authtoken]
paste.filter_factory = keystonemiddleware.auth_token:filter_factory

当请求到达服务时,由keystonemiddleware访问keystone来查询请求携带的token是否合法,通常我们一个token会使用很多次,所以keystonemiddleware建议使用memcache缓存,把从keystone取到的token缓存一段时间,默认是300秒,以减少对keystone的压力,提高性能。kolla项目中nova keystonemiddleware配置示例如下:

[keystone_authtoken]
[keystone_authtoken]
auth_uri = {{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_public_port }}
auth_url = {{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_admin_port }}
auth_plugin = password
project_domain_id = default
user_domain_id = default
project_name = service
username = {{ nova_keystone_user }}
password = {{ nova_keystone_password }} memcache_security_strategy = ENCRYPT
memcache_secret_key = {{ memcache_secret_key }}
memcached_servers = {% for host in groups['memcached'] %}{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ memcached_port }}{% if not loop.last %},{% endif %}{% endfor %}

一直以来,如果不配置其中的memcached_servers的的话,每个服务每个子进程都会创建一个字典作为cache存放从keystone获得的token,但是字典内容都是相似的,如果使用统一的memcache,就不会有这方面的问题。现在master版本keystonemiddleware认为这是不合适的,会导致不一致的结果和较高的内存占用,计划在N或者O版本移除这个特性。

存储horizon用户会话数据

这个是django支持的功能,这里不作讨论,有兴趣的可以看The Django Book 2.0--中文版

总结

cache相关的具体的配置项可以参考kolla项目中的cache配置,应该还是准确合适的。

OpenStack中memcached的使用和实现的更多相关文章

  1. openstack中的环境准备

    openstack中环境准备基于Ubuntu系统 author:headsen chen   2017-10-13  11:51:50 个人原创,转载请注明作者,出处. 6 apt-get insta ...

  2. OpenStack中Keystone的基本概念理解

    原文http://www.kankanews.com/ICkengine/archives/10788.shtml Keystone简介 Keystone(OpenStack Identity Ser ...

  3. openstack中eventlet使用

    openstack中使用eventlet的协程来实现并发. 第一种,使用eventlet.GreenPool来管理绿色线程 如l3-agent在开启了8个绿色线程来处理router消息 def _pr ...

  4. .NET中MemCached使用介绍

    阅读目录 1.MemCached是什么? 2.Window中MemCached安装 3.MemCached命令 4.简单示例 MemCached是什么 MemCached是一个自由开源,高性能,分布式 ...

  5. 探索 OpenStack 之(14):OpenStack 中 RabbitMQ 的使用

    本文是 OpenStack 中的 RabbitMQ 使用研究 两部分中的第一部分,将介绍 RabbitMQ 的基本概念,即 RabbitMQ 是什么.第二部分将介绍其在 OpenStack 中的使用. ...

  6. openstack中彻底删除计算节点的操作记录

    在使用openstack的过程中,我们经常会添加好几台计算节点来部署虚拟机,在后续使用中由于某些原因,一些计算节点出现了问题,需要将这些出了问题的计算节点从openstack的控制节点中踢出去!但是很 ...

  7. OpenStack中给wsgi程序写单元測试的方法

    在 OpenStack 中, 针对web应用, 有三种方法来写单元測试 1) 使用webob生成模拟的request from __future__ import print_function imp ...

  8. openstack中iptables的使用

    openstack中nova使用了iptables实现其网络相关功能,乍看openstack的iptables表比较复杂,整理了一下iptables的filter表和nat表的结构,以一个all in ...

  9. OpenStack中部署glance的步骤

    OpenStack中部署glance的步骤(基于Ubuntu14.04系统) author:headsen  chen   2017-10-13   08:34:35 个人原创,转载请注明作者,出处, ...

随机推荐

  1. freemarker常用值格式化方法

    freemarker常用的值格式化方法: 1.${price?string('0.00')} 对price进行格式化,小数点后不足2位用0补足. 比如:price=1 输出:1.00 2.${pric ...

  2. jspf与jsp的区别

    如果想把一个jspf的文件引入(incurred)到一个jsp页面中,只能使用"@include"指令引入 如果使用<jsp:include>引入,jspf文件中的内容 ...

  3. 图片文档倾斜矫正算法 附完整c代码

    2年前在学习图像算法的时候看到一个文档倾斜矫正的算法. 也就是说能将一些文档图像进行旋转矫正, 当然这个算法一般用于一些文档扫描软件做后处理 或者用于ocr 文字识别做前处理. 相关的关键词: 抗倾斜 ...

  4. 【转】shell学习笔记(六)——流程控制之for循环

    基本语法格式: for 变量 in 列表 do 命令行(通常用到循环变量) done ********Linux Shell for循环写法总结******** for((i=1;i<</ ...

  5. form表单中get和post两种提交方式的区别

    一.form表单中get和post两种提交方式的区别? 1.get提交表单中的内容在链接处是可见的.post不可见 2.post相比于get是安全的 3.post不收限制大小,get有限制大小(黑马视 ...

  6. 布隆过滤器(Bloom Filter)详解

    直观的说,bloom算法类似一个hash set,用来判断某个元素(key)是否在某个集合中.和一般的hash set不同的是,这个算法无需存储key的值,对于每个key,只需要k个比特位,每个存储一 ...

  7. NIO基础篇(二)

    Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管理多个网络连接. 传统的 ...

  8. vue-router 二级路由

    /** * Created by 我 on 2017/12/4. */ import Vue from 'vue' //import导入 Vue(自己起的名) from 从 vue import Vu ...

  9. 小甲鱼OD学习第1讲

    这一讲我们的目标是修改Hello.exe对话框的标题和内容,如图所示 把程序放进OD,按F8一步步运行,直到程序弹出对话框为止,然后在弹出对话框位置处下断点 按Ctrl+F2重新载入程序,然后按F9直 ...

  10. 2018/1/28 RocketMq学习笔记

    RocketMq是支持Topic模式的MQ中间件,它的传输格式为topic(主题,一个product对应一个主题,),Tag(标签,其实就是副标题,是为了更好的支持集群模式而出现的,这样客户端可以指定 ...