• 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中类似问题

  • 相关阅读:
    Different AG groups have the exactly same group_id value if the group names are same and the ‘CLUSTER_TYPE = EXTERNAL/NONE’
    An example of polybase for Oracle
    use azure data studio to create external table for oracle
    Missing MSI and MSP files
    You may fail to backup log or restore log after TDE certification/key rotation.
    Password is required when adding a database to AG group if the database has a master key
    Use KTPASS instead of adden to configure mssql.keytab
    ardunio+舵机
    android webview 全屏100%显示图片
    glide 长方形图片显示圆角问题
  • 原文地址:https://www.cnblogs.com/qiyukun/p/4816676.html
Copyright © 2020-2023  润新知