Strategieën voor beheren van afbeeldingen/uploads

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
Ik ben bezig met het implementeren van het verwerken van geuploade afbeeldingen op een website. Hierbij stel ik me een aantal vragen omtrent het bewaren van deze bestanden en hoe de database (mysql in mijn geval) er mee moet omgaan.

Mijn huidige strategie is afbeeldingen bijhouden in een `image` tabel, met de kolommen `path`, `width`, `height`, `sizeName` en `mimeType`. `sizeName` bevat een door de configuratie bepaalde naam als "small", "medium" en "large". De redenering hierachter is dat ik een geuploade afbeelding in meerdere groottes wil bewaren, zoals de `product` tabel die een many-to-many relatie (`product_has_image`) met de `image` tabel heeft.

Met deze strategie heb ik een aantal problemen. Het eerste probleem is dat niet elke afbeelding per se een `sizeName` nodig heeft omdat sommige afbeeldingen slechts 1 grootte hebben (het bewaren van de oorspronkelijk geuploade afbeelding bijvoorbeeld, als je later andere groottes wilt genereren). Misschien de `sizeName` kolom verwijderen en plaatsen binnen de associatie tabel `product_has_image` en een unique index op combinatie `product_id` en `size_name` zetten?

Een andere vraag die ik me stel is hoe ik best omga met het indelen en verwijderen van bestanden. Een mogelijk idee voor de indeling is elk bestand een unieke naam geven in hex notatie, en deze verdelen over 2 niveaus van directories om te vermijden dat deze directories te groot worden (filesystem performance). Bijvoorbeeld bestand `4a5e4f5610c24f5a41d53aa1e1213cb2.jpg` gaat in directory `4a/5e/4a5e4f5610c24f5a41d53aa1e1213cb2.jpg` waarbij de eerste 2 en de volgende 2 karakters gebruikt worden als directories. Dit zou de afbeeldingen maximaal spreiden over 16^4 directories.

Het synchroniseren van de bestanden met de `image` tabel lijkt me een moeilijkere kwestie. Wat ik wil vermijden is dat bij het verwijderen van een record uit de `image` tabel het bestand achterblijft wegens een databasefout. Dit geldt ook voor een fout bij het inserten van een `image` record waar de bij afbeelding "referentieloos" achterblijft.

De oplossing voor het opslaan van een bestand lijkt me relatief eenvoudig; maak het opslaan deel van de database transactie en verwijder het bestand bij de rollback indien er een fout optreedt. Het verwijderen lijkt me iets ingewikkelder. Ik zou binnen de transactie eerst het bestand kunnen verwijderen zodat het nooit zonder referentie achterblijft bij een databasefout tijdens het verwijderen van een `image` record. Dit betekent wel dat ik bij een fout het bestand "magisch" terug tot leven moet roepen.

Tot slot stel ik me de vraag hoe ik met lege directories van verwijderde bestanden moet omgaan. Aangezien de bestanden hoogswaarschijnlijk in de cloud (s3) opgeslagen zullen worden, lijkt het me niet zo verstandig na elke verwijdering van een bestand de directory tree en zijn de inhoud af te lopen om te checken of ze leeg zijn. Ik neem aan dat de lege directories achterlaten weinig problemen veroorzaakt?

-----------

Ik geef bij veel van mijn probleemstellingen waarschijnlijk reeds zelf het antwoord, maar ik zou voornamelijk gewoon wat feedback willen of ik op het juiste denkpad zit en waar er plaats is voor verbetering :*). Bedankt!

Beste antwoord (via egonolieux op 19-06-2019 23:48)


  • Douweegbertje
  • Registratie: Mei 2008
  • Laatst online: 14:52

Douweegbertje

Wat kinderachtig.. godverdomme

egonolieux schreef op woensdag 19 juni 2019 @ 21:51:
[...]


Bedankt voor de suggesties, juist enkele vraagjes: :)

Ik neem aan dat het ook mogelijk is te verhinderen dat de oorspronkelijke afbeelding rechtstreeks opgevraagd wordt? Bijvoorbeeld een 404 sturen als de "dimensions" query string parameter afwezig is in de lambda. Dit is om te voorkomen dat gebruikers direct de mogelijks gigantische onbewerkte afbeelding opvragen.

Mijn volgende vraag is in welke mate het aan te raden is de afbeelding bij het uploaden te bewerken vóór deze naar S3 te sturen. Stel nu dat een gebruiker een afbeelding upload met een hele boel whitespace/transparantie er rond (die getrimd moet worden), of de afbeelding is verkeerd georienteerd. Ik neem aan dat deze aanpassingen best eerst op eigen server gebeuren? Of is dit wat je oa bedoelt met server side formaten bepalen etc?

De virusscanner is inderdaad een goede tip. Welke tools lijken je het best door deze job? clamav?
Volgens mij is het meer deze flow:

- Uploaden door de gebruiker
- Trimmen, orientatie whatever laten uitvoeren vanuit je 'applicatie'
- Je hebt nu je 'raw' image
- Upload naar een bucket (side note; iedereen heeft het hier over AWS, maar in feite zijn alle buckets compatible met elkaar. M.a.w. het is een API voor objects, je kan hier net zo goed elke andere bucket voor gebruiken. Zorg dat je misschien geen vendor lock krijgt ;)
- Zie code example:https://github.com/amazon-archives/serverless-image-resizing/blob/master/lambda/index.js
- User request whatever.nl/50x50/foo.png
- Lamda pakt hem over en checkt of hij er is, zo ja -> serve, zo niet -> resize.
* zie ook de code m.b.t. afmetingen ;)

Dit is 'on the fly', technisch gezien zou je ook gewoon een watcher op je bucket kunnen zetten en per definitie je sizes kunnen maken voordat een user een request doet.. Soort cache warmer :)

Voor lokaal werken zou je:
- Een clone van je bucket kunnen maken
- Je lib die je gebruikt zo inrichten dat je met 1 var kan kiezen wat er met een image gebeurt. Ik heb bijv. een dev env. waar ik 100% dezelfde code kan gebruiken lokaal maar dat hij alles lokaal uitvoert. Voor prod is het een bucket. Aan de programmeer kant merk ik hier niets van
- Voor puur reads zou je kunnen spelen met redirects, m.a.w. een htaccess bijv om alles van images vanuit acceptance op te halen...

Wat IMO helpt is om gewoon eens hier mee te spelen. Het is soms even wennen dat cloud native :+ Hele concepten over files / data werkt soms totaal anders dan je denkt / gewend bent. Soms 'fucked' het met je brein om het mooi te zeggen, maar de uitwerking is vaak zoveel makkelijker en mooier :)

Alle reacties


Acties:
  • +3 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Het opslaan van sizeNames is niet echt nodig, lijkt me? Als een plaatje geresized kan worden voor een bepaalde maat dan hoef je alleen het origineel op te slaan en resize (en cache) je de benodigde afbeelding on the fly. Als je toch met S3 werkt zou je eventueel hiernaar kunnen kijken. Er zijn natuurlijk ook oplossingen die dat gewoon op je eigen server doen, zo is er voor Symfony bijvoorbeeld de LiipImagineBundle die je eigenlijk dit hele verhaal uit handen neemt. Ik denk dat dat soort oplossingen er voor elk bekend framework wel zijn.

Over filesystem optimalisatie hoef je je volgens mij niet heel erg druk te maken, dat regelt S3 wel voor je. Al kost je eigen voorstel natuurlijk niet heel veel moeite, dus je voorstel kan zeker ook geen kwaad.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
De voornaamste reden dat ik de verschillende groottes wou opslaan bij het uploaden, is omdat ik gebruik wou maken van een CDN om deze afbeeldingen aan te bieden. Ik was niet op de hoogte dat je image resizing kon doen met AWS ;).

Hoewel AWS voor deze toepassing een nieuw gegeven voor mij is, voel ik me niet direct geneigd dit te gebruiken omdat ik ook in development afbeeldingen dynamisch zou willen resizen (hangt er van af hoe goed localstack te integreren valt?). Daarnaast lijkt het er niet op dat AWS optimalisatie met tools als jpegoptim/optipng aanbiedt.

Hoe dan ook wil ik S3 (of een andere clouddienst) gebruiken om de originele bestanden in productie op te slaan. Mijn idee is hier Flysystem voor te gebruiken, zodat mijn project afgezien van configuratie niet specifiek afhankelijk is van een clouddienst.

Ik zou voor maximale flexibiliteit de afbeeldingen op mijn eigen server kunnen resizen (met een oplossing zoals LiipImageBundle) en mijn server als origin in cloudfront instellen. Ik weet niet zeker of dit haalbaar is qua performance/latency omdat cloudfront eerst naar mijn server moet gaan, en mijn server vervolgens naar S3. Als alles direct via cloudfront/S3 loopt, zijn deze extra tussenstappen niet nodig.

Het ziet er naar uit dat ik tussen flexibiliteit of latency moet kiezen?

Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 02-10 09:22

TheNephilim

Wtfuzzle

egonolieux schreef op maandag 17 juni 2019 @ 06:41:
Ik zou voor maximale flexibiliteit de afbeeldingen op mijn eigen server kunnen resizen (met een oplossing zoals LiipImageBundle) en mijn server als origin in cloudfront instellen. Ik weet niet zeker of dit haalbaar is qua performance/latency omdat cloudfront eerst naar mijn server moet gaan, en mijn server vervolgens naar S3. Als alles direct via cloudfront/S3 loopt, zijn deze extra tussenstappen niet nodig.

Het ziet er naar uit dat ik tussen flexibiliteit of latency moet kiezen?
Dat gebeurd alleen de eerste keer dat een afbeelding ingeladen wordt; van Cloudfront naar jou server naar S3. Je zou dat met 'cache warming' wellicht nog kunnen aanpakken.

Acties:
  • +1 Henk 'm!

  • Kalentum
  • Registratie: Juni 2004
  • Laatst online: 21:38
egonolieux schreef op zondag 16 juni 2019 @ 19:09:
Een andere vraag die ik me stel is hoe ik best omga met het indelen en verwijderen van bestanden. Een mogelijk idee voor de indeling is elk bestand een unieke naam geven in hex notatie, en deze verdelen over 2 niveaus van directories om te vermijden dat deze directories te groot worden (filesystem performance). Bijvoorbeeld bestand `4a5e4f5610c24f5a41d53aa1e1213cb2.jpg` gaat in directory `4a/5e/4a5e4f5610c24f5a41d53aa1e1213cb2.jpg` waarbij de eerste 2 en de volgende 2 karakters gebruikt worden als directories. Dit zou de afbeeldingen maximaal spreiden over 16^4 directories.
S3 kent geen directories, alleen maar objecten. S3 presenteert zichzelf als een filesystem maar achter de schermen is het 1 grote bak met objecten. Zie deze pagina https://docs.aws.amazon.c...guide/using-folders.html:
In Amazon S3, buckets and objects are the primary resources, where objects are stored in buckets. Amazon S3 has a flat structure with no hierarchy like you would see in a file system. However, for the sake of organizational simplicity, the Amazon S3 console supports the folder concept as a means of grouping objects. Amazon S3 does this by using a shared name prefix for objects (that is, objects that have names that begin with a common string). Object names are also referred to as key names.
Het synchroniseren van de bestanden met de `image` tabel lijkt me een moeilijkere kwestie. Wat ik wil vermijden is dat bij het verwijderen van een record uit de `image` tabel het bestand achterblijft wegens een databasefout. Dit geldt ook voor een fout bij het inserten van een `image` record waar de bij afbeelding "referentieloos" achterblijft.
Dat kan vrij eenvoudig: je controleert of de database succesvol de query heeft uitgevoerd. Als dat zo is dan start je je 'verwijder afbeelding van S3' code. En als het niet gelukt is, laat je de afbeelding gewoon staan. Ik zou het niet een onderdeel van de database transactie maken. Want je database transactie wordt dan pas gecommit als de image delete is gelukt. Dus dan maak je een externe service bepalend voor de duur van je database transactie. En je wilt je transacties zo snel mogelijk maken.

Je kan ook nog voor 'soft deletes' gaan: ipv een image record te wissen uit de database markeer je de afbeelding als 'gewist' en run je een los script om de gemarkeerde afbeeldingen te wissen van S3 en uit je database.
Tot slot stel ik me de vraag hoe ik met lege directories van verwijderde bestanden moet omgaan. Aangezien de bestanden hoogswaarschijnlijk in de cloud (s3) opgeslagen zullen worden, lijkt het me niet zo verstandig na elke verwijdering van een bestand de directory tree en zijn de inhoud af te lopen om te checken of ze leeg zijn. Ik neem aan dat de lege directories achterlaten weinig problemen veroorzaakt?
Gezien het feit dat er geen directories zijn in S3 lijkt me dat geen probleem

Acties:
  • +1 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
egonolieux schreef op maandag 17 juni 2019 @ 06:41:
Het ziet er naar uit dat ik tussen flexibiliteit of latency moet kiezen?
Ik zou gewoon beginnen met zaken bovenop AWS te doen en de tools die daar aangeboden worden te gebruiken, en pas als er bepaalde beperkingen zijn te gaan kijken hoe je dat kunt optimaliseren. 9 van de 10 keer is, juist voor dit soort kleine projecten, het zelf moeten doen van beheer hier iets wat opweegt tegen 't beetje geld dat AWS kost. Je werpt vooraf al allemaal beperkingen op, vooral door 't gebrek aan ervaring. Vergeet niet dat Netflix ook ongeveer helemaal op AWS draait: media serveren zijn ze behoorlijk goed in.

Voor wat jij wil is DynamoDB voor de catalogus storage prima geschikt. Alles wat je op DynamoDB doet (dus bijvoorbeeld deletes op tables) geeft events af waarop je simpele handelingen (zoals het deleten van een S3 object) kunt laten afvuren. Het omgekeerde geldt ook trouwens: een POST naar een S3 bucket kan ook events af laten gaan, om bijvoorbeeld een insert in Dynamo te doen.

Door deze tools goed in te zetten is je applicatie simpeler en schaalbaarder dan waneer je met eigen servers en databases gaat hanessen. Ga het ook niet te lastig maken met abstractielagen bovenop S3. Je kunt een S3 heel simpel naar een andere cloud-dienst (google bijvoorbeeld) of een eigen systeem syncen. Geen problemen oplossen die waarschijnlijk nooit gaan bestaan.

[ Voor 14% gewijzigd door Hydra op 17-06-2019 15:35 ]

https://niels.nu


Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
TheNephilim schreef op maandag 17 juni 2019 @ 10:06:
[...]


Dat gebeurd alleen de eerste keer dat een afbeelding ingeladen wordt; van Cloudfront naar jou server naar S3. Je zou dat met 'cache warming' wellicht nog kunnen aanpakken.
Het is inderdaad enkel de eerste keer, maar het verkeer moet nog steeds in meerdere stappen gebeuren. En cache warming lijkt me moeilijk te doen als je tienduizenden afbeeldingen in meerdere formaten hebt?
rutgerw schreef op maandag 17 juni 2019 @ 11:03:
[...]


S3 kent geen directories, alleen maar objecten. S3 presenteert zichzelf als een filesystem maar achter de schermen is het 1 grote bak met objecten. Zie deze pagina https://docs.aws.amazon.c...guide/using-folders.html:

[...]


[...]


Dat kan vrij eenvoudig: je controleert of de database succesvol de query heeft uitgevoerd. Als dat zo is dan start je je 'verwijder afbeelding van S3' code. En als het niet gelukt is, laat je de afbeelding gewoon staan. Ik zou het niet een onderdeel van de database transactie maken. Want je database transactie wordt dan pas gecommit als de image delete is gelukt. Dus dan maak je een externe service bepalend voor de duur van je database transactie. En je wilt je transacties zo snel mogelijk maken.

Je kan ook nog voor 'soft deletes' gaan: ipv een image record te wissen uit de database markeer je de afbeelding als 'gewist' en run je een los script om de gemarkeerde afbeeldingen te wissen van S3 en uit je database.


[...]


Gezien het feit dat er geen directories zijn in S3 lijkt me dat geen probleem
S3 gebruikt dus een of andere hash map achter de schermen, handig.

Wat de database betreft, maakt het toch niet veel uit of de afbeeldingen binnen de transactie doe qua performance? Het enige moment waarop de boel trager zou zijn is als ik effectief een rollback moet doen.

Bij het opslaan maak ik eerst een image record aan, vervolgens de afbeelding op S3. Als het maken van de afbeelding in S3 niet lukt, doe ik gewoon een rollback. Bij het verwijderen verplaats ik eerst de afbeelding naar een tijdelijke map, verwijder dan de record, en bij een databasefout verplaats ik de afbeelding terug naar de oorspronkelijke plaats.
Hydra schreef op maandag 17 juni 2019 @ 15:32:
[...]


Ik zou gewoon beginnen met zaken bovenop AWS te doen en de tools die daar aangeboden worden te gebruiken, en pas als er bepaalde beperkingen zijn te gaan kijken hoe je dat kunt optimaliseren. 9 van de 10 keer is, juist voor dit soort kleine projecten, het zelf moeten doen van beheer hier iets wat opweegt tegen 't beetje geld dat AWS kost. Je werpt vooraf al allemaal beperkingen op, vooral door 't gebrek aan ervaring. Vergeet niet dat Netflix ook ongeveer helemaal op AWS draait: media serveren zijn ze behoorlijk goed in.

Voor wat jij wil is DynamoDB voor de catalogus storage prima geschikt. Alles wat je op DynamoDB doet (dus bijvoorbeeld deletes op tables) geeft events af waarop je simpele handelingen (zoals het deleten van een S3 object) kunt laten afvuren. Het omgekeerde geldt ook trouwens: een POST naar een S3 bucket kan ook events af laten gaan, om bijvoorbeeld een insert in Dynamo te doen.

Door deze tools goed in te zetten is je applicatie simpeler en schaalbaarder dan waneer je met eigen servers en databases gaat hanessen. Ga het ook niet te lastig maken met abstractielagen bovenop S3. Je kunt een S3 heel simpel naar een andere cloud-dienst (google bijvoorbeeld) of een eigen systeem syncen. Geen problemen oplossen die waarschijnlijk nooit gaan bestaan.
Vergeet niet dat diensten van AWS ook met een learning curve komen. Mijn opstelling is niet zo ingewikkeld en kan ik makkelijk binnen een korte tijd zelf opzetten met kant en klare oplossing zonder AWS. Maar je hebt wel een punt. Ik weet ik niet in welke mate al deze diensten een "vendor lock-in" zijn, ik zou er me eens in moeten verdiepen.

Acties:
  • +1 Henk 'm!

  • Kalentum
  • Registratie: Juni 2004
  • Laatst online: 21:38
egonolieux schreef op maandag 17 juni 2019 @ 20:02:
S3 gebruikt dus een of andere hash map achter de schermen, handig.

Wat de database betreft, maakt het toch niet veel uit of de afbeeldingen binnen de transactie doe qua performance? Het enige moment waarop de boel trager zou zijn is als ik effectief een rollback moet doen.

Bij het opslaan maak ik eerst een image record aan, vervolgens de afbeelding op S3. Als het maken van de afbeelding in S3 niet lukt, doe ik gewoon een rollback. Bij het verwijderen verplaats ik eerst de afbeelding naar een tijdelijke map, verwijder dan de record, en bij een databasefout verplaats ik de afbeelding terug naar de oorspronkelijke plaats.
Het hangt ervan af hoe druk die MySQL server heeft. Hoe drukker de server is en hoe langer de transacties duren, hoe groter de kans op deadlocks of zelfs connection errors. En die wil je niet. Als je tussen je BEGIN en je COMMIT een call doet naar een externe service (en dan ook nog eens een afbeelding upload) heb je kans dat die transactie erg lang open staat (bv een paar seconden), bv doordat je request lang duurt (grote afbeeldingen), omdat het netwerk eventjes langzaam is, de third party af en toe langzaam is. Transacties kunnen goed zijn voor dataconsistentie binnen je database (bv als SQL statement 1 moet teruggedraaid worden als SQL statement 2 faalt) maar ik zou vermijden om third party calls in je database transactie te wrappen.

Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
rutgerw schreef op maandag 17 juni 2019 @ 20:37:
[...]


Het hangt ervan af hoe druk die MySQL server heeft. Hoe drukker de server is en hoe langer de transacties duren, hoe groter de kans op deadlocks of zelfs connection errors. En die wil je niet. Als je tussen je BEGIN en je COMMIT een call doet naar een externe service (en dan ook nog eens een afbeelding upload) heb je kans dat die transactie erg lang open staat (bv een paar seconden), bv doordat je request lang duurt (grote afbeeldingen), omdat het netwerk eventjes langzaam is, de third party af en toe langzaam is. Transacties kunnen goed zijn voor dataconsistentie binnen je database (bv als SQL statement 1 moet teruggedraaid worden als SQL statement 2 faalt) maar ik zou vermijden om third party calls in je database transactie te wrappen.
Vanuit dat perspectief had ik het inderaad niet bekeken.

Om terug te komen op je vorige post:
Dat kan vrij eenvoudig: je controleert of de database succesvol de query heeft uitgevoerd. Als dat zo is dan start je je 'verwijder afbeelding van S3' code. En als het niet gelukt is, laat je de afbeelding gewoon staan. Ik zou het niet een onderdeel van de database transactie maken. Want je database transactie wordt dan pas gecommit als de image delete is gelukt. Dus dan maak je een externe service bepalend voor de duur van je database transactie. En je wilt je transacties zo snel mogelijk maken.

Je kan ook nog voor 'soft deletes' gaan: ipv een image record te wissen uit de database markeer je de afbeelding als 'gewist' en run je een los script om de gemarkeerde afbeeldingen te wissen van S3 en uit je database.
Soft deletes ben ik niet zo zeer geneigd te implementeren omdat dit vroeg of later overal in je queries kruipt door een extra conditie te moeten toevoegen. Misschien een beter plan i.p.v. soft deletes is de image record verplaatsen naar een "deleted" tabel? Een script kan dan achteraf de afbeeldingen verwijderen adhv de gegevens uit deze tabel.

Acties:
  • +1 Henk 'm!

  • Kalentum
  • Registratie: Juni 2004
  • Laatst online: 21:38
egonolieux schreef op dinsdag 18 juni 2019 @ 21:33:
Soft deletes ben ik niet zo zeer geneigd te implementeren omdat dit vroeg of later overal in je queries kruipt door een extra conditie te moeten toevoegen. Misschien een beter plan i.p.v. soft deletes is de image record verplaatsen naar een "deleted" tabel? Een script kan dan achteraf de afbeeldingen verwijderen adhv de gegevens uit deze tabel.
een aparte tabel kan ook werken. Misschien ook wel beter dan soft deletes en het zal ook wel redelijk snel zijn: je kan gewoon alle records in die tabel processen en dan wissen. Alleen opletten wat er gebeurt met images die verwijderd worden terwijl het clean up script draait.

Acties:
  • +1 Henk 'm!

  • gitaarwerk
  • Registratie: Augustus 2001
  • Niet online

gitaarwerk

Plays piano,…

Misschien iets te over-engineerd voor je, maar... bij mijn vorige werkgever hebben we ook deze technieken gebruikt. Dit was enorm positief.

1. Je beheert een lijstje met welke sizes je zou willen voor gangbare formaten.
2. Je upload de bestanden
3. Lambdas zorgen voor je resizing
4. Serveren van S3
5. <3 joepie

https://aws.amazon.com/bl...-lambdaedge-aws-cdn-blog/

Ik kan je zeggen dat we met > 1,5miljoen bezoekers per dag, > 500k producten, incl free tier we 50$ per maand betaalde hiervoor :D

initieel om alle afbeeldingen die we al hadden te resizen kostte het eenmalig 100-200$. Daar kan zelfs geen klein bedrijf met een VM/aparte DNS tegenop betreft kosten. Dus sowieso is AWS best heel kost-efficient. Als je zelf niet boven de free-tier uitkomt, dan is dat helemaal mooi. Mocht je dit wel komen, dan doe je ergens wat heel goed. Mocht het dan alsnog na de balans geld kosten, dan moet je ergens anders gaan optimaliseren :Y)

De enige dingen die je moet doen is server side nog de juiste formaten bepalen.

Oh ja, mocht dit onderdeel van je business zijn, zou ik je aanraden wel een virusscanner erop los te laten voordat je deze door de lambdas heen gooit. Als je een keer een virus serveert en Google heeft dat door, wordt je site gelijk geblokkeerd. De snelheid met waarmee die eraf gaat kan redelijk wat schade veroorzaken.

Verder zou ik alleen in je DB een hash van je image zetten. De image sizes kun je bepalen van die lijst.

Verder zou je als ik mij niet vergis zelf een relatie tussen de hash maken, maar hier kan ik fout in zijn, ik heb niet aan die kant meegewerkt.

Oh ja,
Als je dan toch met JPEG bezig bent... zorg vooral dat je ze lekker comprimeert en progressive-jpegs gebruikt ipv lazy loading. Ik wil je meer details wel vertellen, maar dan wel in DM :)


Overigens niet het hele topic gelezen, dus excuse my ignorance :+

[ Voor 9% gewijzigd door gitaarwerk op 19-06-2019 09:47 ]

Ontwikkelaar van NPM library Gleamy


Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
gitaarwerk schreef op woensdag 19 juni 2019 @ 09:45:
Misschien iets te over-engineerd voor je, maar... bij mijn vorige werkgever hebben we ook deze technieken gebruikt. Dit was enorm positief.

1. Je beheert een lijstje met welke sizes je zou willen voor gangbare formaten.
2. Je upload de bestanden
3. Lambdas zorgen voor je resizing
4. Serveren van S3
5. <3 joepie

https://aws.amazon.com/bl...-lambdaedge-aws-cdn-blog/

Ik kan je zeggen dat we met > 1,5miljoen bezoekers per dag, > 500k producten, incl free tier we 50$ per maand betaalde hiervoor :D

initieel om alle afbeeldingen die we al hadden te resizen kostte het eenmalig 100-200$. Daar kan zelfs geen klein bedrijf met een VM/aparte DNS tegenop betreft kosten. Dus sowieso is AWS best heel kost-efficient. Als je zelf niet boven de free-tier uitkomt, dan is dat helemaal mooi. Mocht je dit wel komen, dan doe je ergens wat heel goed. Mocht het dan alsnog na de balans geld kosten, dan moet je ergens anders gaan optimaliseren :Y)

De enige dingen die je moet doen is server side nog de juiste formaten bepalen.

Oh ja, mocht dit onderdeel van je business zijn, zou ik je aanraden wel een virusscanner erop los te laten voordat je deze door de lambdas heen gooit. Als je een keer een virus serveert en Google heeft dat door, wordt je site gelijk geblokkeerd. De snelheid met waarmee die eraf gaat kan redelijk wat schade veroorzaken.

Verder zou ik alleen in je DB een hash van je image zetten. De image sizes kun je bepalen van die lijst.

Verder zou je als ik mij niet vergis zelf een relatie tussen de hash maken, maar hier kan ik fout in zijn, ik heb niet aan die kant meegewerkt.

Oh ja,
Als je dan toch met JPEG bezig bent... zorg vooral dat je ze lekker comprimeert en progressive-jpegs gebruikt ipv lazy loading. Ik wil je meer details wel vertellen, maar dan wel in DM :)


Overigens niet het hele topic gelezen, dus excuse my ignorance :+
Bedankt voor de suggesties, juist enkele vraagjes: :)

Ik neem aan dat het ook mogelijk is te verhinderen dat de oorspronkelijke afbeelding rechtstreeks opgevraagd wordt? Bijvoorbeeld een 404 sturen als de "dimensions" query string parameter afwezig is in de lambda. Dit is om te voorkomen dat gebruikers direct de mogelijks gigantische onbewerkte afbeelding opvragen.

Mijn volgende vraag is in welke mate het aan te raden is de afbeelding bij het uploaden te bewerken vóór deze naar S3 te sturen. Stel nu dat een gebruiker een afbeelding upload met een hele boel whitespace/transparantie er rond (die getrimd moet worden), of de afbeelding is verkeerd georienteerd. Ik neem aan dat deze aanpassingen best eerst op eigen server gebeuren? Of is dit wat je oa bedoelt met server side formaten bepalen etc?

De virusscanner is inderdaad een goede tip. Welke tools lijken je het best door deze job? clamav?

Acties:
  • Beste antwoord
  • +2 Henk 'm!

  • Douweegbertje
  • Registratie: Mei 2008
  • Laatst online: 14:52

Douweegbertje

Wat kinderachtig.. godverdomme

egonolieux schreef op woensdag 19 juni 2019 @ 21:51:
[...]


Bedankt voor de suggesties, juist enkele vraagjes: :)

Ik neem aan dat het ook mogelijk is te verhinderen dat de oorspronkelijke afbeelding rechtstreeks opgevraagd wordt? Bijvoorbeeld een 404 sturen als de "dimensions" query string parameter afwezig is in de lambda. Dit is om te voorkomen dat gebruikers direct de mogelijks gigantische onbewerkte afbeelding opvragen.

Mijn volgende vraag is in welke mate het aan te raden is de afbeelding bij het uploaden te bewerken vóór deze naar S3 te sturen. Stel nu dat een gebruiker een afbeelding upload met een hele boel whitespace/transparantie er rond (die getrimd moet worden), of de afbeelding is verkeerd georienteerd. Ik neem aan dat deze aanpassingen best eerst op eigen server gebeuren? Of is dit wat je oa bedoelt met server side formaten bepalen etc?

De virusscanner is inderdaad een goede tip. Welke tools lijken je het best door deze job? clamav?
Volgens mij is het meer deze flow:

- Uploaden door de gebruiker
- Trimmen, orientatie whatever laten uitvoeren vanuit je 'applicatie'
- Je hebt nu je 'raw' image
- Upload naar een bucket (side note; iedereen heeft het hier over AWS, maar in feite zijn alle buckets compatible met elkaar. M.a.w. het is een API voor objects, je kan hier net zo goed elke andere bucket voor gebruiken. Zorg dat je misschien geen vendor lock krijgt ;)
- Zie code example:https://github.com/amazon-archives/serverless-image-resizing/blob/master/lambda/index.js
- User request whatever.nl/50x50/foo.png
- Lamda pakt hem over en checkt of hij er is, zo ja -> serve, zo niet -> resize.
* zie ook de code m.b.t. afmetingen ;)

Dit is 'on the fly', technisch gezien zou je ook gewoon een watcher op je bucket kunnen zetten en per definitie je sizes kunnen maken voordat een user een request doet.. Soort cache warmer :)

Voor lokaal werken zou je:
- Een clone van je bucket kunnen maken
- Je lib die je gebruikt zo inrichten dat je met 1 var kan kiezen wat er met een image gebeurt. Ik heb bijv. een dev env. waar ik 100% dezelfde code kan gebruiken lokaal maar dat hij alles lokaal uitvoert. Voor prod is het een bucket. Aan de programmeer kant merk ik hier niets van
- Voor puur reads zou je kunnen spelen met redirects, m.a.w. een htaccess bijv om alles van images vanuit acceptance op te halen...

Wat IMO helpt is om gewoon eens hier mee te spelen. Het is soms even wennen dat cloud native :+ Hele concepten over files / data werkt soms totaal anders dan je denkt / gewend bent. Soms 'fucked' het met je brein om het mooi te zeggen, maar de uitwerking is vaak zoveel makkelijker en mooier :)

Acties:
  • 0 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
Douweegbertje schreef op woensdag 19 juni 2019 @ 22:14:
[...]


Volgens mij is het meer deze flow:

- Uploaden door de gebruiker
- Trimmen, orientatie whatever laten uitvoeren vanuit je 'applicatie'
- Je hebt nu je 'raw' image
- Upload naar een bucket (side note; iedereen heeft het hier over AWS, maar in feite zijn alle buckets compatible met elkaar. M.a.w. het is een API voor objects, je kan hier net zo goed elke andere bucket voor gebruiken. Zorg dat je misschien geen vendor lock krijgt ;)
- Zie code example:https://github.com/amazon-archives/serverless-image-resizing/blob/master/lambda/index.js
- User request whatever.nl/50x50/foo.png
- Lamda pakt hem over en checkt of hij er is, zo ja -> serve, zo niet -> resize.
* zie ook de code m.b.t. afmetingen ;)

Dit is 'on the fly', technisch gezien zou je ook gewoon een watcher op je bucket kunnen zetten en per definitie je sizes kunnen maken voordat een user een request doet.. Soort cache warmer :)

Voor lokaal werken zou je:
- Een clone van je bucket kunnen maken
- Je lib die je gebruikt zo inrichten dat je met 1 var kan kiezen wat er met een image gebeurt. Ik heb bijv. een dev env. waar ik 100% dezelfde code kan gebruiken lokaal maar dat hij alles lokaal uitvoert. Voor prod is het een bucket. Aan de programmeer kant merk ik hier niets van
- Voor puur reads zou je kunnen spelen met redirects, m.a.w. een htaccess bijv om alles van images vanuit acceptance op te halen...

Wat IMO helpt is om gewoon eens hier mee te spelen. Het is soms even wennen dat cloud native :+ Hele concepten over files / data werkt soms totaal anders dan je denkt / gewend bent. Soms 'fucked' het met je brein om het mooi te zeggen, maar de uitwerking is vaak zoveel makkelijker en mooier :)
Dit is inderdaad ongeveer de workflow die ik in gedachten had :). Aangezien de meeste van mijn vragen beantwoord zijn, zal ik jouw reactie als antwoord opgeven.

Acties:
  • +1 Henk 'm!

  • gitaarwerk
  • Registratie: Augustus 2001
  • Niet online

gitaarwerk

Plays piano,…

mooi beantwoord door @Douweegbertje :) mijn verstand hield daar een beetje op. Beste is inderdaad spelen ernee. Vendorlock is altijd een interessant onderwerp. De free tiers kunnen erg aantrekkelijj zijn. Voordeel van infrastructure as code is dat het redelijk verplaatsbaat is. Zover ik gehoord/gedaan/gelezen heb zijn ook grote delen van infra te verplaatsen. Zeker als je ook nog eens op Docker instances laat draaien, of apis volgens swagger definities. (rare naam blijf ik het vinden).

afijn, back to the subject. CDN.

Als je de mogelijkheid hebt om je afbeedingen direct vanuit dezelfe locatie te sturen, zou ik het doen (iig, zelfde ips). Dat scheelt een extra dns lookup, en met http/2 technieken stream je direct de afbeeldingen zonder teveel wachttijd meer. Ook progressive als eerdere tip, boven lazy loading. Namelijk extra scripts en je browser kan praktisch gezien lastiger je laadvolgorde meer zien. Ook nemen progressive images al tijdens het laden snel de juiste ruimtes in.

Sorry voor het ongevraagd advies :Y)

Ontwikkelaar van NPM library Gleamy


Acties:
  • +1 Henk 'm!

  • egonolieux
  • Registratie: Mei 2009
  • Laatst online: 06-01-2024

egonolieux

Professionele prutser

Topicstarter
gitaarwerk schreef op donderdag 20 juni 2019 @ 08:24:
mooi beantwoord door @Douweegbertje :) mijn verstand hield daar een beetje op. Beste is inderdaad spelen ernee. Vendorlock is altijd een interessant onderwerp. De free tiers kunnen erg aantrekkelijj zijn. Voordeel van infrastructure as code is dat het redelijk verplaatsbaat is. Zover ik gehoord/gedaan/gelezen heb zijn ook grote delen van infra te verplaatsen. Zeker als je ook nog eens op Docker instances laat draaien, of apis volgens swagger definities. (rare naam blijf ik het vinden).

afijn, back to the subject. CDN.

Als je de mogelijkheid hebt om je afbeedingen direct vanuit dezelfe locatie te sturen, zou ik het doen (iig, zelfde ips). Dat scheelt een extra dns lookup, en met http/2 technieken stream je direct de afbeeldingen zonder teveel wachttijd meer. Ook progressive als eerdere tip, boven lazy loading. Namelijk extra scripts en je browser kan praktisch gezien lastiger je laadvolgorde meer zien. Ook nemen progressive images al tijdens het laden snel de juiste ruimtes in.

Sorry voor het ongevraagd advies :Y)
Als ik vanuit mijn backend de afbeeldingen op S3 opsla, kan ik deze makkelijk als origin instellen in cloudfront, praktisch dezelde locatie dus :). HTTP/2 en progressive JPEGs schelen inderdaad heel wat, ik gebruik hier oa jpegoptim voor.

Acties:
  • 0 Henk 'm!

  • BCC
  • Registratie: Juli 2000
  • Laatst online: 20:45

BCC

Cloudinary doet dit ook altijd erg goed imho.

Na betaling van een licentievergoeding van €1.000 verkrijgen bedrijven het recht om deze post te gebruiken voor het trainen van artificiële intelligentiesystemen.


Acties:
  • +1 Henk 'm!

  • rogierslag
  • Registratie: Maart 2005
  • Laatst online: 14-10-2024
Indien je eigen servercapaciteit hebt voor een Docker container, en het prima vindt om de eenmaal gecachte images via Cloudfront te laten lopen kun je een service als iaas (https://github.com/inventid/iaas) gebruiken. Deze zet je images goed georienteerd op, support cropping on upload, en ondersteunt een lading image formats direct.

Wij gebruiken deze voor het uitsturen van miljoenen images per dag. Lamba was met grote images (onze sources gaan soms tot 60 megapixel) alsnog wat traag, dus dat intern trekken scheelde veel
Pagina: 1