Lors du téléchargement d'un grand nombre d'objets à partir de S3, la vitesse ne sort pas modérément quelle que soit la taille de l'objet. Quand j'écrivais en Python, je faisais de mon mieux avec ** concurrent.futures **, mais peut-être que je peux le faire avec Goroutine? J'ai pensé, j'ai fait mes débuts à Golang.
--Utilisez ListObjectV2 pour obtenir toutes les clés sous le préfixe spécifique de S3 --Téléchargez la clé acquise avec Goroutine
Hmm? Même vitesse car vous venez de frapper l'API. Si tel est le cas, je suis toujours convaincu, mais je crains un peu que ** Go soit plus lent que le langage de script **. J'ai changé mon horaire à la hâte et j'ai essayé de vérifier un peu cette question.
Donc ici et [ici](https: // Écrivez-le en vous référant à docs.aws.amazon.com/sdk-for-go/api/service/s3/#S3.ListObjectsV2).
main.go
package main
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"os"
)
func main() {
bucket := os.Getenv("BUCKET")
prefix := os.Getenv("PREFIX")
region := os.Getenv("REGION")
sess := session.Must(session.NewSession())
svc := s3.New(sess, &aws.Config{
Region: ®ion,
})
params := &s3.ListObjectsV2Input{
Bucket: &bucket,
Prefix: &prefix,
}
fmt.Println("Start:")
err := svc.ListObjectsV2Pages(params,
func(p *s3.ListObjectsV2Output, last bool) (shouldContinue bool) {
for _, obj := range p.Contents {
fmt.Println(*obj.Key)
}
return true
})
fmt.Println("End:")
if err != nil {
fmt.Println(err.Error())
return
}
}
J'écrirai ceci aussi. Avec un client de bas niveau pour répondre aux conditions avec Go.
main.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import boto3
bucket = os.environ["BUCKET"]
prefix = os.environ["PREFIX"]
region = os.environ["REGION"]
# r = boto3.resource('s3').Bucket(bucket).objects.filter(Prefix=prefix)
# [print(r.key) for r in r]
#Je l'obtiens généralement comme ci-dessus, mais je le mesure avec le code suivant pour l'envoyer à Golang
s3_client = boto3.client('s3', region)
contents = []
next_token = ''
while True:
if next_token == '':
response = s3_client.list_objects_v2(Bucket=bucket, Prefix=prefix)
else:
response = s3_client.list_objects_v2(Bucket=bucket, Prefix=prefix, ContinuationToken=next_token)
contents.extend(response['Contents'])
if 'NextContinuationToken' in response:
next_token = response['NextContinuationToken']
else:
break
[print(r["Key"]) for r in contents]
--Exécute essentiellement sur Cloud9 sur EC2 (t2.micro).
――Je ne veux pas polluer l'environnement et c'est gênant, j'ai donc tout construit avec Docker.
$ docker-compose up -d --build
Dockerfile
FROM golang:1.13.5-stretch as build
RUN go get \
github.com/aws/aws-sdk-go/aws \
github.com/aws/aws-sdk-go/aws/session \
github.com/aws/aws-sdk-go/service/s3
COPY . /work
WORKDIR /work
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main main.go
FROM python:3.7.6-stretch as release
RUN pip install boto3
COPY --from=build /work/main /usr/local/bin/main
COPY --from=build /work/main.py /usr/local/bin/main.py
WORKDIR /usr/local/bin/
docker-compose.yml
version: '3'
services:
app:
build:
context: .
container_name: "app"
tty: True
environment:
BUCKET: <Bucket>
PREFIX: test/
REGION: ap-northeast-1
Créez un bucket dans la région de Tokyo et créez-en environ 1000 avec les outils suivants.
#/bin/bash
Bucket=<Bucket>
Prefix="test"
#Création de fichier de test
dd if=/dev/zero of=testobj bs=1 count=30
#Copie du fichier maître
aws s3 cp testobj s3://${Bucket}/${Prefix}/testobj
#Dupliquer le fichier maître
for i in $(seq 0 9); do
for k in $(seq 0 99); do
aws s3 cp s3://${Bucket}/${Prefix}/testobj s3://${Bucket}/${Prefix}/${i}/${k}/${i}_${k}.obj
done
done
$ time docker-compose exec app ./main
~ Abréviation ~
real 0m21.888s
user 0m0.580s
sys 0m0.107s
$ time docker-compose exec app ./main.py
~ Abréviation ~
real 0m2.671s
user 0m0.577s
sys 0m0.104s
Go est 10 fois plus lent que Python. Pourquoi!
#Différence seulement
for i in $(seq 0 99); do
for k in $(seq 0 99); do
―― En passant, il a fallu 3-4 heures pour terminer le téléchargement. J'aurais dû faire l'outil correctement ...
$ time docker-compose exec app ./main
~ Abréviation ~
real 0m23.276s
user 0m0.617s
sys 0m0.128s
$ time docker-compose exec app ./main.py
~ Abréviation ~
real 0m5.973s
user 0m0.576s
sys 0m0.114s
Cette fois, la différence est d'environ 4 fois. Au contraire, il semble qu'il y ait une différence d'environ 18 secondes quel que soit le nombre d'objets. Hmmm.
――Je pense que je ne comprends pas les spécifications de la langue à cause des paramètres de la bibliothèque, donc j'aimerais obtenir plus d'informations. ――Si l'efficacité du ** traitement de téléchargement parallèle dans Goroutine **, qui est l'objectif initial, est bonne, il semble qu'il y ait une erreur d'environ 20 secondes, donc je vais essayer d'implémenter le reste.
Comme indiqué dans la section des commentaires, j'ai essayé de déboguer le SDK J'ai trouvé qu'il fallait beaucoup de temps pour trouver les informations d'identification IAM. La valeur par défaut du système d'exploitation "-stretch" était-elle mauvaise? Je l'ai essayé plusieurs fois par la suite, mais il n'est pas réapparu dans cet environnement, donc je vais le résoudre. C'est maussade, mais ...
@nabeken Merci!