swift bug 调试记(wsgi.input)
第一次指定纠删码策略,修改了一部分swift代码后,执行PUT object,就被一个bug拦住。产生bug代码段如下:
try:
with ChunkReadTimeout(self.client_timeout):
mime_documents_iter = iter_mime_headers_and_bodies(
request.environ['wsgi.input'],
mime_boundary, self.network_chunk_size)
_junk_hdrs, obj_input = next(mime_documents_iter)
except ChunkReadTimeout:
return HTTPRequestTimeout(request=request)
在执行第三行iter_mime_headers_and_bodies()
过程中出错,代码会最终定位至eventlet.wsgi的Input类中_chunked_read()
函数,抛出一个ValueError异常。异常全文如下:
ValueError: invalid literal for int() with base 16: ''
而Input类中_chunked_read()
函数相关代码如下:
def _chunked_read(self, rfile, length=None, use_readline=False):
......
while self.chunk_length != 0:
......
if maxreadlen > 0:
......
else:
self.chunk_length = int(rfile.readline().split(b";", 1)[0], 16)
self.position = 0
if self.chunk_length == 0:
rfile.readline()
except greenio.SSL.ZeroReturnError:
pass
return b''.join(response)
Google了一阵后,大致了解这个问题,一步步尝试解决。
eventlet版本原因导致?
首先利用apt-cache命令查看了本机上安装的eventlet版本信息。apt-cache用于查看相应软件包确切名称及详细信息。
apt-cache show python-eventlet
果然,显示Version: 0.9.7-0ubunutu1
,而在swift项目中requirement.txt内容如下:
dnspython>=1.9.4
eventlet>=0.16.1,!=0.17.0
greenlet>=0.3.1
netifaces>=0.5,!=0.10.0,!=0.10.1
pastedeploy>=1.3.3
simplejson>=2.0.9
six>=1.9.0
xattr>=0.4
PyECLib==1.0.7
明确规定eventlet版本为0.16.1以上。马上通过源码安装eventlet 0.16.1版本,重新运行swift服务。结果……依旧抛出异常!
人为比较了一下两个版本eventlet.wsgi,发现Input
类具体实现确实有区别,但没能解决我的问题。我甚至尝试直接修改eventlet相应库文件,但依旧无效。两版本eventlet最大区别字符串前加b,具体解释可见字符串知识。
配置错误?
这个猜想主要根据List Openstack上关于此错误的一些回答。
然而当我尝试调整object-server.conf中间eventlet_debug
后,异常依旧。
回归错误本身
多方尝试无果,重新回来思考这个错误。
其实错误行代码本身提示,便是在读取某个类似文件的对象一行后,尝试用“;”进行切分,取切分后生成列表的第一个元素,但问题是切分后列表的第一个元素为空,根本无法以16进制形式转换为整数。
这个readline()为空的问题究竟如何产生?难道是six模块版本太老?或是真的是配置错误?还是我删掉了一些必要的代码?抑或是我用dd命令生成的测试文件有问题?
多方尝试,耗费整整一天,依然无果。第二天升级编译python-six模块,并利用其它大文件做PUT object测试,问题依旧。在耗费两天毫无进展,自己都快发疯时,注意到了一个问题,那便是proxy server会返回状态码503然后输出如下信息:
Object PUT returning 503, 1/5 required connections
在源码中查询搜索了这条错误信息,发现只有在_check_min_conn()
函数使用默认msg参数时,会输出这样的错误信息。而这样的调用仅在_check_failure_put_connections()
函数的最末发生过一次!!!
到这里,总算发现解决问题的曙光。根本问题就出在纠删码策略PUT object过程中_store_object()
调用_check_failure_put_connections()
函数时(line. 2200)。我重读了这部分代码,发现_check_min_conn()
函数中检查链接过程,实际上是将纠删码策略存取成功所需最新链接数min_conns和成功建立的链接conns数量相比较,后者要大于等于前者。即:
len(conns) >= min_conns
其中min_conns = policy.quroum_size
,与选用的存储策略相关,quorum_size
在相应的存储策略中均有定义(NRW策略)。比如我选用(4,2)RS码进行编码,即有:quorum_size = 4 + 2/2 = 5
。而所有连接建立成功情况下,len(conns)
值应为选定存放数据的结点数,应为6,其中nodes初始值由object_ring给出。但在我修改后的代码中,仅成功创建了一个链接,即len(conns) == 1
。
追根溯源
我终于明白是怎么回事。最初我看到了标示不同数据段的boundary,便理所当然认为proxy obj controller 和 object server之间仅会建立起一个链接,然后将所有的数据段传输上去,在我修改后的代码中,所有的数据放在一个http链接上进行传输,自始至终只成功建立了一个http链接。所有的一切,源于我对swift纠删码策略的一个错误认知:将boundary进行分区的在网络上进行传输的数据段(fragments)和要放置在一个具体结点上的相应数据块(由许多fragments组成)混淆了,boundary是用来区分不同网络数据段,并不是用来区分传输至不同object-server的多个数据块!!!
要保证纠删码策略正常,proxy和每个object-server间必须建立起相应的链接,而我只建立成功了一个链接,object-server端仍旧在等待真正的对象数据传输过去,而proxy obj controller这边确因为_check_min_conn()
不合格而返回503,接下来的数据传输过程自然无从谈起,object-server苦等良久,却得不到需要的数据,这也就解释了为何对request.environ['wsgi.input']
中数据处理到后来因为空而报错!也就是:
ValueError: invalid literal for int() with base 16: ''
后尝试注释掉obj controller中_check_min_conn()
,代码果真一路向下正常运行,顿感心情舒畅。
关于最初在网络上搜索到的同类问题,我亦怀疑问题并不是出在接收数据方,而是数据发送方。没有具体研究过,仅写出我的经验,供参考。
参考:
[1]List Openstack上关于此问题的回答
[2]launchpad上关于此问题的研究
[3]nova中出现的类似错误
[4]ssync-reciver中类似问题
swift bug 调试记(wsgi.input)的更多相关文章
- 记一次 springboot 参数解析 bug调试 HandlerMethodArgumentResolver
情况描述 前端输入框输入中文的横线 -- ,到后台接收时变成了 &madsh;$mdash 正常应该显示成这样: bug调试思路记录 最开始完全没有向调试源码方面想,试了不少方法,都没解决,没 ...
- geotrellis使用(七)记录一次惨痛的bug调试经历以及求DEM坡度实践
眼看就要端午节了,屌丝还在写代码,话说过节也不给轻松,折腾了一天终于解决了一个BUG,并完成了老板安排的求DEM坡度的任务,那么就分两段来表. 一.BUG调试 首先记录一天的BUG调试,简单copy了 ...
- geotrellis使用(十二)再记录一次惨痛的伪BUG调试经历(数据导入以及读取瓦片)
Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html 目录 前言 BUG还原 查找BUG 解决方案 总结 后记 一.前 ...
- 最难忘的Bug调试经历
摘要:目前,著名的社区问答网站Quora上出现一个很火的讨论:你调试过最难的Bug是什么?大家纷纷留言,把自己最痛苦的一次调试经验写下来. 相信每位程序员都有过一段不堪回首地Bug调试经历,程序员一听 ...
- Android分组子级的不同视图布局之BUG奇遇记
Android分组子级的不同视图布局之BUG奇遇记 最近在使用按日期分类列表,二级条目可能不一样,于是就想到了ExpandableListView. ExpandableListView的布局显示分割 ...
- 论 BUG调试与(程序猿)初学者
作为一枚程序猿,BUG调试是最基本的技能,对于初学者更是重中之重.个人而言,要想为自己的程序猿生涯更上一层楼,就得知道什么是BUG调试,而且还必须知道怎么调好BUG.那么BUG究竟是什么呢?在我之前的 ...
- Bug调试(lldb)
原文网址:http://www.cnblogs.com/Twisted-Fate/p/4760156.html 今天博主有一些Bug调试的需求,遇到了一些困难点,在此和大家分享,希望能够共同进步. X ...
- bug调试宝典
bug调试技巧 宝典之一 : 坚信一个原则,程序不会说谎,一定是有原因的 多数的错误表现看起来莫明奇妙,甚至不可思议 但当我们找到问题后会发现:其实问题的根源是如此简单.如此的合乎道理. 这就要求我们 ...
- 记一次诡异的bug调试——————关于JDK1.7和JDK1.8中HashSet的hash(key)算法的区别
现象: 测试提了一个bug,我完全复现不了,但是最吊诡的是在其他人的机器上都可以复现.起初以为是SVN合并后出现的冲突,后来经过对比法排查: step 1: 我本地开两个jetty,一个跑合并之前的版 ...
随机推荐
- bzoj 1679: [Usaco2005 Jan]Moo Volume 牛的呼声【枚举】
直接枚举两两牛之间的距离即可 #include<iostream> #include<cstdio> #include<algorithm> using names ...
- http2及server push
本文主要研究下java9+springboot2+undertow2启用http2及server push maven <parent> <groupId>org.spri ...
- excel poi 取单元格的值
/** * 取单元格的值 * * @param cell 单元格对象 * @param treatAsStr 为true时,当做文本来取值 (取到的是文本,不会把“1”取成“1.0”) * @retu ...
- Java多线程——线程之间的协作
Java多线程——线程之间的协作 摘要:本文主要学习多线程之间是如何协作的,以及如何使用wait()方法与notify()/notifyAll()方法. 部分内容来自以下博客: https://www ...
- LN : leetcode 231 Power of Two
lc 231 Power of Two 231 Power of Two Given an integer, write a function to determine if it is a powe ...
- Objective-C设计模式——生成器Builder(对象创建)
生成器 生成器,也成为建造者模式,同样是创建对象时的设计模式.该模式下有一个Director(指挥者),客户端知道该类引用用来创建产品.还有一个Builder(建造者),建造者知道具体创建对象的细节. ...
- HTML空格占位
它叫不换行空格,全称No-Break Space,它是最常见和我们使用最多的空格,大多数的人可能只接触了 ,它是按下space键产生的空格.在HTML中,如果你用空格键产生此空格,空格是不会累加的 ...
- LR接口测试---基于http协议之get/post
get请求代码: //=====================get interface======================== 以http状态码方式: //获取返回的HTTP状态码判断请求 ...
- Python操作远程数据库
我的项目要往数据库中插入create_time和update_time,那就势必要引用现在的系统时间,经过大量的查找,终于发现往python是没有对应时间datetime的相关通配符的,那么我们要怎么 ...
- python计算auc指标
1.安装scikit-learn 1.1Scikit-learn 依赖 Python (>= 2.7 or >= 3.3), NumPy (>= 1.8.2), SciPy (> ...