第一次指定纠删码策略,修改了一部分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. P3990 [SHOI2013]超级跳马

    传送门 首先不难设\(f[i][j]\)表示跳到\((i,j)\)的方案数,那么不难得到如下转移 \[f[i][j]=\sum\limits_{k=1}^{\frac n2}f[i-2k+1][j-1 ...

  2. ACM_走楼梯Ⅱ

    走楼梯Ⅱ Time Limit: 2000/1000ms (Java/Others) Problem Description: 有一楼梯共N+1级,刚开始时你在第一级,若每次能走M级(1<=M& ...

  3. ASP.NET MVC 生成验证码

    using System.Web.Mvc; using System.Drawing; using System; using System.Drawing.Imaging; using Models ...

  4. service: no such service mysqld 与MySQL的开启,关闭和重启

    1.问题原因与解决办法 因为修改了MySQL临时文件的目录后,使用service mysqld restart重启MySQL出现如下错误: service: no such service mysql ...

  5. hbase本地调试环境搭建

    1,前言 想要深入的了解hbase,看hbase源码是必须的.以下描述了搭建hbase本地调试环境的经历 2,安装步骤 2.1,启动hbase 1,安装java和IDE IntelliJ,下载源码等. ...

  6. Shell脚本,简单& 强大

      摘自<码农增刊Linus与Linux>,章节:你可能不知道的Shell.   最近阅读完这本书,觉得其中有很多不错的内容,这是其中的一个Shell小甜点,拿来和大家一起分享一下,增加了 ...

  7. LN : leetcode 207 Course Schedule

    lc 207 Course Schedule 207 Course Schedule There are a total of n courses you have to take, labeled ...

  8. 【工具】Github

    项目目录结构设计与git远程仓库的建立 git码云仓库建立:在码云网站上新建组织和项目. 配置sshkey认证和公钥:命令行ssh-keygen -t rsa -C "xxxxx@xxxxx ...

  9. 梦想CAD控件关于标注的系统变量说明

    主要用到函数说明: IMxDrawDimension::SetDimVarDouble 设置标注属性的实数类型变量值,详细说明如下: 参数 说明 [in] LONG iType 该属性的类形值 dVa ...

  10. docker常用命令理解

    docker help Commands: attach Attach local standard input, output, and error streams to a running con ...