相应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()
函数中最大的区别在于创建链接返回putters
,putters
用于针对纠删码将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()
进行整合打包,使其符合纠删码分片规范。
最后接收响应,从中挑选最优者返回即可。