Swift对象创建过程(PUT Object)——纠删码策略(二)

相应Object使用纠删码(EC)作为存储策略时,BaseObjectController类中PUT和GET需要调用的一些方法会被ECObjectController中相应函数覆盖。
在GET Object过程中主要是_get_or_head_response()函数被重定义,然后新增加一个函数_fix_response_headers().
在PUT Object过程中主要是_store_object()函数,以及直接或间接被此函数调用的_connect_put_node(),_transfer_data()_get_put_responses()等方法被重定义,针对纠删码(EC)特性做了相应的修改。
_store_object()函数中最大的区别在于创建链接返回puttersputters用于针对纠删码将fragments传递至object-server,其中针对putters有一些相应的处理。

    def _store_object(self, req, data_source, nodes, partition,
                      outgoing_headers):
        ......
        putters = self._get_put_connections(
            req, nodes, partition, outgoing_headers,
            policy, expect=True)

        try:
            # check that a minimum number of connections were established and
            # meet all the correct conditions set in the request
            self._check_failure_put_connections(putters, req, nodes, min_conns)

            self._transfer_data(req, policy, data_source, putters,
                                nodes, min_conns, etag_hasher)
            final_phase = True
            need_quorum = False
            min_resp = 2
            putters = [p for p in putters if not p.failed]
            # ignore response etags, and quorum boolean
            statuses, reasons, bodies, _etags, _quorum = 
                self._get_put_responses(req, putters, len(nodes),
                                        final_phase, min_resp,
                                        need_quorum=need_quorum)
        ......

其中建立链接的方法_get_put_connections()调用_connect_put_node()方法在EC中被重定义:

def _connect_put_node(self, node_iter, part, path, headers,
                          logger_thread_locals):
        headers.pop('Content-Length', None)
        headers.pop('Etag', None)

        self.app.logger.thread_locals = logger_thread_locals
        for node in node_iter:
            try:
                putter = ECPutter.connect(
                    node, part, path, headers,
                    conn_timeout=self.app.conn_timeout,
                    node_timeout=self.app.node_timeout)
                self.app.set_node_timing(node, putter.connect_duration)
                return putter
            except InsufficientStorage:
                self.app.error_limit(node, _('ERROR Insufficient Storage'))
            except PutterConnectError as e:
                self.app.error_occurred(
                    node, _('ERROR %(status)d Expect: 100-continue '
                            'From Object Server') % {
                                'status': e.status})
            except (Exception, Timeout):
                self.app.exception_occurred(
                    node, _('Object'),
                    _('Expect: 100-continue on %s') % path)

其中ECPutter是专门针对纠删码分块后数据进行上传的类,其connect类方法会返回一个ECPutter类对象。纠删码会将数据编码为若干个fragments,每个ECPutter负责传输相应的fragments到相应的object-server上。不同的fragment之间通过boundary进行标示区分。
纠删码(n,k)是将数据分为若干个分片,编码后存放于n+k个不同的结点,object ring中选出的用于存放数据的nodes个数因等于n+k,即len(nodes) = n + k。这样,proxy obj controller和每个nodes之间均会尝试建立起http链接,相应代码为_get_put_connections()中GreenPile并发执行_connect_put_node()。在检查成功建立链接数符合规定后,上传数据。每个connection上传输的数据由chunk_transformer()进行整合打包,使其符合纠删码分片规范。
最后接收响应,从中挑选最优者返回即可。

原文地址:https://www.cnblogs.com/qiyukun/p/4819770.html