Object的下載需要涉及從多個data server拿到component並組合再一起,流程如下圖所示
由於我們有metadata,所以能直接知道Object的components存放在哪個data server,如getObj所示
def getObj(name, version):
metadata = DB.getMetadata(name, version)
hash = metadata['hash']
dataSize = metadata['size']
locate = metadata['locate']
locate.sort(key=lambda x: x[1]) # x[1] is idx
data = b''
for server, idx, size in locate:
try:
res = requests.get(f"http://{server}:{PORT}/partition/{hash}-{idx}", timeout=1)
if res.status_code == 201:
return -1
else:
data += res.content
except Exception as e:
print('request error: %s' % e, flush=True)
data += b'x'*size
return combineData(data)
如果遇到一個data server有問題,就填充x,我們支持最多兩個server出問題,最後再combineData,把奇偶校驗值decode我們原來的資料
理解完在Download前是怎麼把Components合成一個Object之後,我們來看怎麼下載續傳
start = request.args.get('start')
data = getObj(obj_name, version)
data = data[start:]
def gen():
chunk = 10
for i in range(0,len(data),chunk):
yield bytes(data[i:i+chunk])
return Response(gen(), mimetype='text/xml')
我們可以看到我們還需要傳遞一個參數 - start,指定從哪裡開始下載,然後為了維持下載的連續性,我們把object分成塊狀,一次只傳遞10個bytes,如果不這麼做的話,有10GB的Data,會把Buffer給塞滿,容易造成網路下載異常,明天講上傳的部分