Mam kilka zasobników pamięci, które publikują powiadomienia w temacie Pub / Sub, gdy pliki zostaną przesłane. Następnie mam funkcję chmury zasubskrybowaną w temacie Pub / Sub, która kopiuje te pliki do ich końcowych zasobników docelowych. To wszystko działa dobrze w przypadku większości plików, ale gdy mam duże pliki (> 1 GB), nie można ich skopiować. Zasobniki źródłowe są wieloregionalne, a zasobniki docelowe są regionalne i bliskie.

Mój kod to zasadniczo:

client = storage.Client()
src_bucket = client.get_bucket(src_bucket_name)
src_blob = src_bucket.get_blob(src_filename)
dst_bucket = client.get_bucket(dst_bucket_name)
dst_blob = dst_bucket.blob(dst_filename)

dst_blob.rewrite(src_blob)

Początkowo funkcja chmury przekraczała limit czasu po 60 sekundach, więc założyłem, że to problem, ale potem przekroczyłem limit czasu funkcji chmury do 540 sekund, ale funkcja nadal wygasa. Funkcja ponawia próbę przez 20 minut, więc widzę, że problem się powtarza. Po przekroczeniu limitu czasu funkcji chmury nie powiodło się, przeczytałem dokumentację obiektu blob i zobaczyłem, że blob.rewrite ma również domyślny limit czasu wynoszący 60 sekund, więc również przekroczyłem limit czasu do 540 sekund, ale to nadal upływa limit czasu.

W tym momencie nie jestem pewien, czego mi brakuje. Czy to problem z przekroczeniem limitu czasu? A może ma to coś wspólnego z publikowaniem wielu wiadomości przez Pub / Sub, więc mógłbym mieć wiele funkcji w chmurze próbujących jednocześnie wykonać tę samą kopię? A może jest lepszy sposób automatycznego przenoszenia dużych plików między zasobnikami?

2
L. MacKenzie 12 marzec 2020, 20:08

2 odpowiedzi

Najlepsza odpowiedź

Najpierw trochę o tym, co dzieje się pod maską:

Operacja GCS przepisanie to operacja online. Gdy żądanie ponownego zapisania potwierdzi powodzenie, przepisywanie zostało zakończone i nowa operacja jest gotowa. Wadą jest to, że użytkownik musi przytrzymać otwarte połączenie nadpisywania podczas kopiowania. Jednak połączenie nie trwa wiecznie. Jeśli operacja zajmie więcej niż, powiedzmy, 30 sekund, żądanie ponownego zapisania może zakończyć się jako niekompletne. W takim przypadku zwróci token przepisywania, którego klient musi użyć, aby wznowić żądanie, w przeciwnym razie nie będzie dalszych postępów.

W Python, wygląda mniej więcej tak:

rewrite_token = False
while True:
  rewrite_token, bytes_rewritten, bytes_to_rewrite = dst_blob.rewrite(
      src_blob, token=rewrite_token)
  print(f'Progress so far: {bytes_rewritten}/{bytes_to_rewrite} bytes.')
  if not rewrite_token:
     break

Nie ma to znaczenia w przypadku mniejszych obiektów lub obiektów, w których usługa nie musi wykonywać żadnej pracy, aby przenieść dane. Jednak w przypadku dużych operacji musisz sprawdzić, czy wznowienie jest potrzebne.

To powiedziawszy, przekroczenie limitu czasu nie jest tym, czego oczekiwałbym od twojego kodu. To inny rodzaj porażki. Czy na pewno wyświetlany błąd to przekroczenie limitu czasu?

2
Brandon Yarbrough 12 marzec 2020, 17:35

Zauważyłem, że w liniach 2 i 4 twojego kodu masz client.get_bucket - w dokumentach GCP na ten temat nie wspominają o metodzie get_bucket: https://cloud.google. com / storage / docs / renaming-copying-moving-objects # storage-copy-object-python

(Będziesz musiał kliknąć kartę „Przykłady kodu”, a następnie wybrać „Python”, aby zobaczyć, o czym mówię).

Czy Twój kod działa lokalnie w Twoim własnym środowisku Python? Wiem, że to głupie pytanie, ale czasami ludzie po prostu idą prosto do chmury. ¯ \ _ (ツ) _ / ¯

0
ingernet 12 marzec 2020, 17:23