第一次指定纠删码策略,修改了一部分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)的更多相关文章

  1. 记一次 springboot 参数解析 bug调试 HandlerMethodArgumentResolver

    情况描述 前端输入框输入中文的横线 -- ,到后台接收时变成了 &madsh;$mdash 正常应该显示成这样: bug调试思路记录 最开始完全没有向调试源码方面想,试了不少方法,都没解决,没 ...

  2. geotrellis使用(七)记录一次惨痛的bug调试经历以及求DEM坡度实践

    眼看就要端午节了,屌丝还在写代码,话说过节也不给轻松,折腾了一天终于解决了一个BUG,并完成了老板安排的求DEM坡度的任务,那么就分两段来表. 一.BUG调试 首先记录一天的BUG调试,简单copy了 ...

  3. geotrellis使用(十二)再记录一次惨痛的伪BUG调试经历(数据导入以及读取瓦片)

    Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html 目录 前言 BUG还原 查找BUG 解决方案 总结 后记 一.前 ...

  4. 最难忘的Bug调试经历

    摘要:目前,著名的社区问答网站Quora上出现一个很火的讨论:你调试过最难的Bug是什么?大家纷纷留言,把自己最痛苦的一次调试经验写下来. 相信每位程序员都有过一段不堪回首地Bug调试经历,程序员一听 ...

  5. Android分组子级的不同视图布局之BUG奇遇记

    Android分组子级的不同视图布局之BUG奇遇记 最近在使用按日期分类列表,二级条目可能不一样,于是就想到了ExpandableListView. ExpandableListView的布局显示分割 ...

  6. 论 BUG调试与(程序猿)初学者

    作为一枚程序猿,BUG调试是最基本的技能,对于初学者更是重中之重.个人而言,要想为自己的程序猿生涯更上一层楼,就得知道什么是BUG调试,而且还必须知道怎么调好BUG.那么BUG究竟是什么呢?在我之前的 ...

  7. Bug调试(lldb)

    原文网址:http://www.cnblogs.com/Twisted-Fate/p/4760156.html 今天博主有一些Bug调试的需求,遇到了一些困难点,在此和大家分享,希望能够共同进步. X ...

  8. bug调试宝典

    bug调试技巧 宝典之一 : 坚信一个原则,程序不会说谎,一定是有原因的 多数的错误表现看起来莫明奇妙,甚至不可思议 但当我们找到问题后会发现:其实问题的根源是如此简单.如此的合乎道理. 这就要求我们 ...

  9. 记一次诡异的bug调试——————关于JDK1.7和JDK1.8中HashSet的hash(key)算法的区别

    现象: 测试提了一个bug,我完全复现不了,但是最吊诡的是在其他人的机器上都可以复现.起初以为是SVN合并后出现的冲突,后来经过对比法排查: step 1: 我本地开两个jetty,一个跑合并之前的版 ...

随机推荐

  1. 1617: [Usaco2008 Mar]River Crossing渡河问题(dp)

    1617: [Usaco2008 Mar]River Crossing渡河问题 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1219  Solved:  ...

  2. Sql 主键设置

    1.开发数据库时常用命名规范 1>.使用不包含数字的单数表名,如果必要的话可以增加模块名前缀. 2>.对于主键的命名,使用表名+ID的形式. 3>.作为外键的列的名字应该与它们所对应 ...

  3. 支持多种格式的播放器js代码

    FLV需要播放器,其它视频格式直接插入相应的代码即可. ------------------------------------- /**   *视频播放 by zhensheng@   *参数说明  ...

  4. 利用freemarker导出页面格式复杂的excel

    刚开始大家可能会利用poi生成简单的excel,但是遇到需要生成复杂的excel,poi导出excel就比较困难,这时候可以利用freemarker来渲染实现实现生成复杂的excel, 首先,将exc ...

  5. jquery滚轮事件

    // jquery 兼容的滚轮事件 $(document).on("mousewheel DOMMouseScroll", function (e) { var delta = ( ...

  6. Server 2008 R2 事件查看器实现日志分析

    在 windows server 2008 R2 中,可以通过点击 "开始" -> "管理工具" -> "事件查看器" ,来打开 ...

  7. Detectron:Pytorch-Caffe2-Detectron的一些跟进

            pytorch官网:http://pytorch.org/上只有PyTroch的ubuntu和Mac版本,赤裸裸地歧视了一把Windows低端用户. 1. Caffe源码:Caffe源 ...

  8. Codeforces_765_D. Artsem and Saunders_(数学)

    D. Artsem and Saunders time limit per test 2 seconds memory limit per test 512 megabytes input stand ...

  9. RabbitMQ系列(八)--顺序消费模式和迅速消息发送模式

    MQ使用过程中,有些业务场景需要我们保证顺序消费,而如果一个Producer,一个Queue,多个Consumer的情况下是无法保证顺序的 举例: 1.业务上产生三条消息,分别是对数据的增加.修改.删 ...

  10. php总结回顾

    做人不能一直埋着头往前跑,还要偶尔停下来看下来时的路.所以今天就来回顾下之前的吧 下面依次介绍 [一]TP加载流程 ①应用入口文件index.php→②tp公共入口文件ThinkPHP.php→③核心 ...