W jaki sposób najlepiej serwować tysiące małych html/css

Cześć,

w jaki sposób najprościej i najlepiej serwować tysiące małych html/css? Chodzi o mały projekt, który umożliwi embedowanie małej wizytówki na stronie użytkownika (html/css). Jeżeli dana osoba wrzuci to na stronę, która ma 5 odwiedzin tygodniowo, to problemu nie będzie, ale przy setkach w górę serwer padnie.

Cachowanie dużo podejrzewam nie da, bo do serwowania ruchu większego od małego potrzeba by było podejrzewam x serwerów, co będzie i drogie i nie do końca szybkie.

Zastanawiam się, czy CDN nie byłoby lepszym rozwiązaniem, tylko nie do końca rozumiem, jak by to technicznie ogarnąć. Czy wgrywać gotowe html/css bezpośrednio na cdn (na cdn77 dają 50 GB przestrzeni za free, na maxcdn jest możliwość stworzenia push/pull zones), czy w jakiś sposób skonfigurować cdn, aby odpytywało serwer i w razie potrzeby dalej przekazywało na stronę użytkownika (serwer dostanie jedno zapytanie, a nie tysiąc). Dodatkowo nie do końca rozumiem, w jaki sposób można zapewnić, aby zawsze dana wizytówka była aktualna - przy każdej zmianie robić reset cache dnsa wydaje się bezsensem, a nie wiem, czy da się skasować i wgrać na cdn np. tylko jeden zmieniony plik.

Ktoś ma jakieś pomysły? Dzięki :smile:

Robilem cos podobnego przy uzyciu Amazonowego CDN-a czyli CloudFront-a. Przy kazdej zmianie danych ‘dynamicznych’ wystarczy utworzyc tzw. ‘invalidation request’, co robi sie latwo korzystajac z AWS-owego SDK.

Przy czym tych plikow sie nie ‘wgrywa’ - CDN odpytuje glowny serwer, po czym uznaje, ze od tej pory moze serwowac wersje ktora pobral; do momentu kolejnej ‘inwalidacji’; dana inwalidacja moze zawierac wiele sciezek (wiec mozna uniewaznic dowolna liczbe URL-i)

Pamietam, ze dokumentacja do tego CloudFront-a nie byla zbyt dobra, to jest kawalek skryptu ktory wtedy uzywalem:

def create_invalidation(files)                                                   
                                                                                   
    client = AWS::CloudFront.new(@config).client                                   
    
    # tutaj  definiujesz sciezki ktore zostana uniewaznione:
    items = invalidation_paths(files)                                              
                                                                                       
    unique_id = "INVALIDATION-#{Time.now.to_i}"                                    
                                                                                   
    response = client.create_invalidation(                                         
      :distribution_id => @config[:distribution_id],                               
      :invalidation_batch => {                                                     
        :paths => {                                                                
          :quantity => items.size,                                                 
          :items => items                                                          
        },                                                                         
        :caller_reference => unique_id                                             
      }                                                                            
    )                                                                              
                                                                                       
end

Wtedy w ten sposob cache’owalismy faktycznie statyczne pliki (css i js) ktore byly wgrywane na S3 (wiec ten skrypt przed utworzeniem inwalidacji pchal zmiany na S3); konfiguracja tego, zeby requesty do tych plikow ‘szly’ przez CloudFront robilo sie w DNS-ie (czyli AWS Route53), ale juz nie pamietam konkretnych ustawien.

W ten sposob cach’owac mozna wszystko, tj. rowniez wyniki stron dynamicznych (tylko nie pamietam teraz, czy dawalo sie to specyfikowac jakims wzorcem na poziomie ‘sciezek’, czy tez wszystko to, co bylo cachowane musialo byc serwowane z osobnej poddomeny)

Nginx + Memcached albo Redis są w stanie Serwować dziesiątki tysięcy zapytań na sekundę w ten sposób (to znaczy zapisany statyczny html/css w Memcached albo Redis serwowany bezpośrednio przez plugin w nginx).
Nginx nawet z dysku (SSD) byłby pewnie w stanie serwować tysiące tego typu zapytań na sekundę.

Problem którym się martwisz po prostu nie istnieje, dopóki nie osiągniesz tysięcy zapytań na sekundę nie musisz na to nawet czasu tracić, zapisujesz plik na dysku, podajesz ścierzkę klientowi, done.

Jak chcesz się bardzo bawić to mozesz wstępnie jeszcze spakować gzipem żeby nginx nie musiał kompresować w locie, ale to tylko jak bardzo potrzeujesz.

Ps. I nie mówię tu nawet o serwerze, albo X serwerach. Zwykły VPS z SSD za 300zł rocznie powinien być w stanie serwować tysiące tego typu requestów na SEKUNDĘ.

mark: dzięki za skrypt. Bardzo ciekawe z tą inwalidacją - będę musiał poszukać, jak to wygląda u innych providerów, bo cloudfront z tego co pamiętam, do tanich nie należał :smile:

swistak84: vps za 5 usd miesięcznie (digital ocean - 1 core, 512 ram, 20 GB ssd) wg Ciebie uciągnie taką ilość? mam wrażenie, że cdn nie tylko że odciąży serwer, to jeszcze będzie szybszy (pod względem geograficznym). Czy się mylę?

@cenebris Bez problemu taki VPS to uciągnie. Poczytaj o serwowaniu statycznych plików przez nginx w szczególności cache expiry i gzip module.

Zapisuj html/css jako statyczne pliki w public (możesz zrobić coś w stylu: /publlic/cards/unique_client_hash/card.{html,css} po czym klientowi podajesz link /cards/unique_client_hash/card.html).

Po czym zrób sobie test przez ab (apache benchmark), nginx serwujący około tysiąc zapytań na sekunde
o statycnze plikipowinien nawet nie rozgrzać maszyny (jeżeli przekroczy 10% CPU stawiam piwo).

Jak się w przyszłości CDN będziesz chciał dodać nie będzie problemu, a teraz nie musisz kombinować (no chyba że robisz projekt za unijną kasę i koszta musisz nabić).

Z ciekawosci sprawdzilem - ceny dla Europy

First 10 TB / month $0.085 / GB
Next 40 TB / month $0.080 / GB

1,000 GB x $0.085 = $85

Ale jesli to sa male pliki, to moze i tak warto? Sa tez ceny per-request, ale to chyba grosze wychodzi