版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 (作者:张华 发表于:2018-08-30)

问题

cinder-volumes在删除volume时很慢, 并且此时create volume的其他操作也无反应, 也无日志.

理论

green thread的概念就是之间不共享数据, 每个green thread有自己的私有的数据对象, 并且非阻塞, 一个green thread的I/O没准备就下其他的green thread跟上. 从而实现在一个进程上高效地跑大量非阻塞的greenthread.
所以greenthread的哲学就是不共享数据对象的, 但greenthread也可以通过tpool.Proxy来共享数据对象, 例如: 使用eventlet.pools.Pool机制还构建httplib2.Http实例池在不同greenthread之间作一定程度共享 (见我五年前的一篇博客 - https://blog.csdn.net/quqi99/article/details/9114577 ). 但是这种共享有一个问题, 当pool里的native thread抛错了但不显示返回的话似乎会造成native thread无法yield从而导致所有green thread也被阻塞. 下面测试程序也可以说明这一点:

import thread
import eventlet
import time
orig = time
from eventlet import tpooleventlet.monkey_patch()class MyException(Exception):passclass FOO(object):def foo(self, char, starting_ident):id=thread.get_ident()print "native {} exec foo({})".format(char, id)try:raise MyException()finally:# REPLACE with pass to reproduce failure
#             returnpassdef stuff(char):print "entering green thread"while True:print "green exec foo({})".format(char)f = tpool.Proxy(FOO())f.foo(char, thread.get_ident())print "green finished foo({})".format(char)time.sleep(1)if __name__ == "__main__":g = eventlet.greenthread.spawn(stuff, 'A')g = eventlet.greenthread.spawn(stuff, 'B')print "done"while True:time.sleep(1)

rados.Rados实例来自python-rbd, 它本身又会spawn native thread去连接rados.
每个green thread都实例化一个rados.Rados进而启动一个native thread的话. 这些native thread之间是通过python解释器进程来同步数据的, native thread也不是非阻塞的. 所以当一个native thread在运行长任务不yield的话, 其他的green threads都没有机会运行, 所以此时无法对image做任何操作. 所以有这个patch (https://review.openstack.org/#/c/175555/ ) 引入了tpool.Proxy.
但是这个patch (https://review.openstack.org/#/c/197710/)又将它revert了, 理由是spawn出来的non-block native thread都去导入python module会造成死锁(According to Python documentation, code can
lead to a deadlock if the spawned thread directly or indirectly attempts
to import a module. ). 所以在_connect_to_rados这块又回到之前每个green thread都会实例化一个rados.Rados进而启动一个native thread的老方式, 但可以通过配置rados_connect_timeout缓解之前的问题( 一个green thread在超时时间内还连不就yield让其他green thread运行).
但是只是将_connect_to_rados这块改回老方式了, 还有其他使用tppool的方式, 如_get_usage_info就是通过tpool的方式:

    def RBDProxy(self):return tpool.Proxy(self.rbd.RBD())def _get_usage_info(self):total_provisioned = 0with RADOSClient(self) as client:for t in self.RBDProxy().list(client.ioctx):with RBDVolumeProxy(self, t, read_only=True) as v:...
class RBDVolumeProxy(object):def __init__(self, driver, name, pool=None, snapshot=None,read_only=False, remote=None, timeout=None):client, ioctx = driver._connect_to_rados(pool, remote, timeout)if snapshot is not None:snapshot = utils.convert_str(snapshot)try:self.volume = driver.rbd.Image(ioctx,utils.convert_str(name),snapshot=snapshot,read_only=read_only)self.volume = tpool.Proxy(self.volume)except driver.rbd.Error:LOG.exception("error opening rbd image %s", name)driver._disconnect_from_rados(client, ioctx)raise

如上代码:
- RBDProxy会通过tpool.Proxy采用非阻塞的native thread方式spawn rbd.RBD.
- RBDVolumeProxy也会通过tpool.Proxy采用非阻塞的native thread方式spawn rbd.RBD.
- _get_usage_info会周期性运行, 此时如果删除一个volume, 那么RBDVolumeProxy可能就会找不着image, 从而报下面的错: Image volume-1f3aa3d5-5639-4a68-be07-14f3214320c6 is not found. _get_usage_info /usr/lib/python2.7/dist-packages/cinder/volume/drivers/rbd.py
- 要知道 RBDVolumeProxy是一个native thread, 里面出了ImageNotFound异常又没有显示返回就会造成我们上面说的greenthread的问题. 这个green thread阻塞, 其他的green thread还能正常yield, 但其他green thread接着也会遇到这个ImageNotFound异常, 这样被阻塞的green thread越来越多 (如何验证了, 可以在上述测试代码里再加一个greenthread里跑一个死循环, 你会发现其他green thread死了不影响这个死循环的green thread)
- 解决方法就是最好设置rbd_exclusive_cinder_pool=True避免调用上面的_get_usage_info
- 我提了一个bug - https://bugs.launchpad.net/cinder/+bug/1789828
具体日志如下:

2018-08-29 06:57:41.604 1586622 DEBUG cinder.volume.drivers.rbd [req-f885ea4a-3e98-4aad-bb3f-102240aebca1 10cbcda6a7854fa79cfc37dc1945cb6d 5d5d0f0ab738467f8ca813dd41432afa - a51502c6e125414fbba0cc95decd86c5 a51502c6e125414fbba0cc95decd86c5] deleting rbd volume volume-2d5951be-25bf-4313-a706-593664f6cd2e delete_volume /usr/lib/python2.7/dist-packages/cinder/volume/drivers/rbd.py:977
2018-08-29 06:57:41.610 1586622 ERROR cinder.volume.drivers.rbd [req-f885ea4a-3e98-4aad-bb3f-102240aebca1 10cbcda6a7854fa79cfc37dc1945cb6d 5d5d0f0ab738467f8ca813dd41432afa - a51502c6e125414fbba0cc95decd86c5 a51502c6e125414fbba0cc95decd86c5] error opening rbd image volume-005a04e7-a113-4ebb-bd77-1d9d3221d8f2: ImageNotFound: [errno 2] error opening image volume-005a04e7-a113-4ebb-bd77-1d9d3221d8f2 at snapshot None
2018-08-29 06:57:41.610 1586622 ERROR cinder.volume.drivers.rbd Traceback (most recent call last):
2018-08-29 06:57:41.610 1586622 ERROR cinder.volume.drivers.rbd   File "/usr/lib/python2.7/dist-packages/cinder/volume/drivers/rbd.py", line 147, in __init__
2018-08-29 06:57:41.610 1586622 ERROR cinder.volume.drivers.rbd     read_only=read_only)
2018-08-29 06:57:41.610 1586622 ERROR cinder.volume.drivers.rbd   File "rbd.pyx", line 1392, in rbd.Image.__init__ (/build/ceph-B2ToPL/ceph-12.2.4/obj-x86_64-linux-gnu/src/pybind/rbd/pyrex/rbd.c:13545)
2018-08-29 06:57:41.610 1586622 ERROR cinder.volume.drivers.rbd ImageNotFound: [errno 2] error opening image volume-005a04e7-a113-4ebb-bd77-1d9d3221d8f2 at snapshot None
2018-08-29 06:57:41.610 1586622 ERROR cinder.volume.drivers.rbd
2018-08-29 06:57:41.612 1586622 DEBUG cinder.volume.drivers.rbd [req-f885ea4a-3e98-4aad-bb3f-102240aebca1 10cbcda6a7854fa79cfc37dc1945cb6d 5d5d0f0ab738467f8ca813dd41432afa - a51502c6e125414fbba0cc95decd86c5 a51502c6e125414fbba0cc95decd86c5] Image volume-005a04e7-a113-4ebb-bd77-1d9d3221d8f2 is not found. _get_usage_info /usr/lib/python2.7/dist-packages/cinder/volume/drivers/rbd.py:409

测试

1, 创建100个volume的脚本

#!/bin/bash -eu
. ~/stsstack-bundles/novarcv3_project
openstack project list| grep " admin "| awk '{print $2}'| xargs -l openstack quota set --volumes 200TOKEN="`openstack token issue| grep ' id '| awk '{print $4}'`"
c_ep="`curl -s -XGET -H "X-Auth-Token: $TOKEN" "$OS_AUTH_URL/auth/catalog"| jq --raw-output '.catalog[] | select(.name | contains("cinderv3")).endpoints[] | select(.interface | contains("admin")).url'`"
echo "Cinder endpoint is $c_ep"for i in {0..100}; do
(payload="`cat << EOF | python | sed 's/"/\\"/g'
import json
vol = {"volume": { "size": 1, "name": "vol"}}
print json.dumps(vol)
EOF`"
curl -s -X POST -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" -d "$payload" ${c_ep}/volumes) &
done

2, 删除这100个volume

openstack volume list| egrep -v "^\+-+|ID"| awk '{print $2}'| xargs openstack volume delete

3, ceph-mon节点上观察volume的个数

watch -n 1 'rbd -p cinder-ceph ls| wc -l'

4, cinder-volume节点上观察cinder-volume进程下创建的线程数

watch -n 1 'ps -eLf| egrep "[c]inder-volume"| wc -l'

为什么cinder-volume在删除volume时无反应 (by quqi99)相关推荐

  1. MySQL删除数据库时无响应解决办法

    今天在删除远程主机上MySQL中的一个数据库时,遇到了这样一个问题. 执行drop database语句的时候,远程主机一直在响应,无法正常删除.登录到远程主机上删除也无响应. 这个问题的解决办法如下 ...

  2. 解决删除Volume报错的问题

    很久没有遇到过删除Volume出错使得Volume处于Error_Deleting状态的情况了,昨天删除一个Volume时又出现了这个问题,这里顺便把解决方法记录一下. 注意我这里针对的是后端采用is ...

  3. 解决删除Volume报错的问题(二)

    删除Volume又遇到新的错误,日志开到debug后看到以下的内容. Clear capabilitiesvolume volume-4e1817be-9b8c-4834-ad90-baf24ef61 ...

  4. vector用erase删除元素时,为什么被删元素的析构函数会被调用更多次?

    vector用erase删除元素时,为什么被删元素的析构函数会被调用更多次? 分类: C++2011-08-18 14:55 720人阅读 评论(0) 收藏 举报 vectoriteratorexce ...

  5. MacOS 如何删除启动时的客人用户?

    问题描述:如何删除启动时的客人用户? 系统更新后就忽然出现了一个客人用户,我已经在"用户与群组"里关闭了客人用户,也重启了好几次,但每次启动还是会出现客人用户...... 解释 - ...

  6. 「SAP技术」SAP MM 批次管理的物料创建DN时无存储地点就不能输入批次值?

    「SAP技术」SAP MM 批次管理的物料创建DN时无存储地点就不能输入批次值? 1, 如下交货单80018169(SO#10002993),行项目里storage location为空,batch字 ...

  7. Windows删除文件时显示找不到该项目

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Hanniel/article/details/78346209 当在Windows删除文件时出现找不 ...

  8. windows10如何删除文件时提示?(回收站--右键属性--显示删除确认对话框)

    1.鼠标右键单击桌面上的回收站图标,在弹出的菜单中选择'属性'; 2.在弹出的属性对话框中将'显示删除确认对话框'前的复选框打上√; 3.点击应用按钮,至此,删除文件时就会弹出删除提示了; 参考文章: ...

  9. 向顺序容器vector、string、deque、list、forward_list中插入\删除元素时迭代器、引用、指针的变化

    1.插入元素 (1)对于vector.string来说,当在某个位置插入元素后,如果内存空间重新分配,则指向任何位置的迭代器.指针.引用都会失效: 如果内存空间没有重新分配,则在插入位置之前的迭代器. ...

最新文章

  1. FPGA的配置引脚以及配置过程
  2. 准备把以前在百毒博客写的一些文章搬运过来
  3. phpstrtotime()对于31日求上个月有问题
  4. 设计模式之_动态代理_01
  5. 如何在bootstap中修改checkbox的样式
  6. 活动目录数据库授权恢复
  7. Process和ProcessBuilder入门【原】
  8. Beego 学习笔记9:Boostrap使用介绍
  9. VI操作--跳到最后一行和跳到最后一行的最后一个字符
  10. [vue require动态引入组件、变量]
  11. 微课|中学生可以这样学Python(7.3.3节):成员方法、类方法、静态方法
  12. 老李分享:HTTP协议之协议头
  13. hdu1078 FatMouse and Cheese(记忆化搜索)
  14. Springboot的工作机制:5 总结
  15. textbox++问题 汇总 如:assert len 0 builtin_function_or_method() int()
  16. Plugin Alliance DS Audio THORN for Mac(电子音乐合成器插件) v1.2.0破解版
  17. android9支持的tf卡格式,老手机福音 三星安卓9.0测试存储卡装应用功能
  18. 【Windows】谷歌浏览器独立多开
  19. c/s模型和b/s模型
  20. ESP32基于arduino和风天气获取代码

热门文章

  1. 软件工程基础课-个人项目-数独
  2. 了解抖音小店店铺装修功能以及条件
  3. mongo数据库创建用户
  4. (Hankson的逆问题)
  5. SAP 玻璃原片单位问题处理
  6. 风控Python绘图技法代码示例
  7. Java实现 蓝桥杯VIP 算法提高 分苹果
  8. 远程桌面教程及指定主机远程连接方法
  9. centos使用xfreerdp登录报错
  10. 算法开启队列转栈武魂