Konfigurasjon av webservere og applikasjonsservere for lastbalansering

Innhold

Generelt

Vi anbefaler alltid at trafikk i f?rste rekke h?ndteres av en fullverdig webserver, slik som Apache eller nginx. Selv om det ofte i prinsippet er mulig ? la lastbalanserer snakke direkte med en applikasjonsserver, mister man da mye fleksibilitet og mange muligheter. Hvis man trenger ? h?ndtere sertifikater p? backend er som regel dette ogs? langt enklere ? gj?re i en webserver, og man kan simpelthen f?lge oppskriftene for hhv. Apache eller nginx, som er dokumentert i kokeboken for SSL.

Vi anbefaler videre at webserveren settes til ? lytte p? port 80 og/eller 443 (istedenfor ustandard porter), og begrenses til ? kun tillate trafikk mot disse portene fra UiOs nett. Dette kan man oppn? helst ved ? plassere (eller flytte om n?dvendig) serveren til et VLAN tilh?rende et mer lukket nett, f.eks. kategori 3, eller sekund?rt ved ? begrense innkommende trafikk i lokal firewall n?r dette ikke er mulig. Hovedform?let er alts? ? forhindre at webserver kan ta imot trafikk direkte fra verden, og dermed tvinge innkommende trafikk gjennom lastbalanserer.

Dersom webserver reversproxyer videre til en applikasjonsserver over HTTP, kan denne egentlig benytte hvilken som helst port over 1024. Ofte benyttes port 8080 til dette form?let for lokal ukryptert trafikk. Hvis applikasjonsserver kj?rer p? samme server som webserver - hvilket den som regel gj?r - b?r applikasjonsserveren kun lytte p?/binde mot localhost, og ikke public IP. Webserver b?r da f?lgelig ogs? reversproxye videre til localhost, over valgt port, f.eks. 8080. Hovedform?let med dette er igjen ? forhindre at applikasjonsserver kan ta imot trafikk utenfra - inkludert fra andre servere - og dermed tvinge innkommende trafikk til denne gjennom webserver. Hvis applikasjonsserver kj?rer p? en annen server enn webserver, b?r applikasjonsserver kun tillate trafikk fra IPen(e) til webserver, begrenset med lokal firewall.

Gj?r man alt dette, s?rger man alts? for ? stenge bakd?rer, og at all innkommende web-trafikk vil f?lge ?nsket vei: lastbalanserer -> webserver -> applikasjonsserver.

Applikasjonsservere skal kj?res som en dedikert upersonlig bruker, og aldri som root. Som regel vil en lokal bruker v?re tilstrekkelig. Webservere (og applikasjonsservere der dette er mulig) m? alltid installeres med systempakke fra standard-repo, som da vil benytte dedikert lokal bruker og s?rge for at egnede rettigheter ivaretas.

Gjenopprette korrekt IP

N?r HTTP-trafikk g?r gjennom en reversproxy, slik den gj?r ved den typen lastbalansering vi gj?r (lastbalansering i HTTP-laget), gj?res det i realiteten to separate foresp?rsler. En fra klient til lastbalanserer, og s? en ny fra lastbalanserer til webserver (backend). Det er dette som gj?r det mulig ? p?virke egenskaper ved foresp?rselen i lastbalanseringslaget, og "fikse" ting der, f?r den g?r videre til webserver. Ettersom disse foresp?rslene er separate, kan de ogs? ha forskjellige egenskaper. Foresp?rselen fra klient til lastbalanserer kan f.eks. g? over IPv6 og HTTP/2, mens foresp?rselen fra lastbalanserer til backend kan g? over IPv4 og HTTP/1.1 - eller andre kombinasjoner av faktorer. Lastbalanserer vil oversette mellom disse, s? s?ml?st som mulig.

En negativ konsekvens ved dette, er at foresp?rslene fra lastbalanserer til backend ser ut i webserver som de kommer fra IPen som tilh?rer lastbalansereren, istedenfor IPen som tilh?rer klienten. Dette stemmer jo for s? vidt, men man er som regel mer interessert i hvilken klient som faktisk sitter i andre enden. Denne informasjonen (og mer til) eksponerer lastbalanserer gjennom egne HTTP headere, s?rlig headerne X-Forwarded-For og Forwarded. Begge disse gj?r i prinsippet det samme, men X-Forwarded-For er mer utbredt, og ofte enklere ? ta i bruk. Vha. disse headerne kan man i webserver "gjenopprette" den opprinnelige IPen som faktisk tilh?rer klienten, og dermed ogs? eksponere denne videre inn i tjenesten til selve applikasjonen. St?tte for ? gj?re dette er h?yst varierende i ymse applikasjonsservere, og dette er én av grunnene til at vi alltid anbefaler ? ha en skikkelig webserver - med st?tte for dette og langt mer - i forkant. Da vil man ha tilgang til det fulle og rike verkt?yskrinet av muligheter som en webserver tilbyr, og f? logger med korrekt IP fra webserveren.

Det er mange grunner til at det er viktig ? sette opp webserver til ? korrekt rapportere klientens IP-adresse. Uten dette vil det v?re vanskelig (eller s?gar umulig) ? skille forskjellige klienter fra hverandre, b?de i logger og ellers. Logger som rapporteres inn i DataOPS vil v?re langt mindre nyttige eller verdifulle, ettersom de mangler en av de mest vesentlige detaljene. Det vil v?re utfordrende ? debugge problemer med tjenesten, og dersom det skulle oppst? en hendelse vil denne v?re vanskelig for IT-sikkerhet ? kunne analysere. I det store og hele vil man i de fleste sammenhenger v?re mer eller mindre blind mht. hvem som faktisk bruker tjenesten.

Videresending fra HTTP til HTTPS

Det er i dag et lovkrav i offentlig forvaltning ? videresende foresp?rsler mot HTTP direkte videre til HTTPS. Lastbalanserer vil alltid gj?re dette, automatisk og ubetinget, slik at alle tjenester satt opp med lastbalansering vil oppfylle dette kravet. Dersom man har logikk p? backend som er ment ? h?ndtere dette, kan (og b?r) denne med andre ord skrus av, ettersom dette ellers kan skape problemer.

Selv om man unng?r ? gj?re dette i webserver, hender det at enkelte applikasjoner har logikk for ? ta seg av slik videresending, eller vurdere hvilken protokoll innkommende foresp?rsler er gjort over. Hvis tjenesten er satt opp med HTTP-trafikk (ikke HTTPS) mellom lastbalanserer og backend, kan dette i noen tilfeller skape problemer, dersom applikasjonen tror foresp?rsler er gjort over HTTP (som de jo er for foresp?rslene den "ser"), n?r de i realiteten er gjort over HTTPS mellom klient og lastbalanserer, som er det vesentlige. Da kan man risikere ? f? en uendelig loop, ettersom alle foresp?rsler vil resultere i en videresending til HTTPS-adressen, som klienten allerede bruker.

L?sningen p? dette er ? ta i bruk en HTTP header som heter X-Forwarded-Proto, eller evt. proto-verdien i Forwarded-headeren dersom man istedet bruker denne. Denne forteller hvilken protokoll den opprinnelige foresp?rselen benyttet, og settes av lastbalanserer for alle innkommende foresp?rsler. Ved ? f? applikasjon (eller webserver, avhengig av behov og oppsett) til ? anse verdien av denne headeren som faktisk benyttet protokoll, istedenfor protokollen i foresp?rselen den selv ser, omg?r man alts? dette problemet.

OpenShift/OKD

Alle tjenester som kj?rer i OpenShift/OKD m? plasseres bak lastbalanserer - s?rlig om de skal v?re tilgjengelig fra Internet. Her anbefales det f?rst og fremst ? f?lge den generelle OpenShift-dokumentasjonen, med s?rlig fokus p? seksjonene for hhv. Edge og Passthrough.

Merk at de generelle anbefalingene for oppsett bak lastbalansering gjelder ogs? her, og da s?rlig det som gjelder ? ha en webserver foran der dette er mulig, anbefalt oppsett for webservere som nginx og Apache, og h?ndtering av tilgangskontroll.

Det kj?rer en HTTP Echo-tjeneste i OpenShift som vil vise hvilke headere som er tilgjengelig fra innsiden av et cluster, og som man kan benytte seg av. Legg s?rlig merke til headerne Forwarded samt X-Forwarded-* som alle stammer fra lastbalansererne.

Apache

Apache HTTP server er nok den web-serveren vi har mest erfaring med, s?rlig i www-drift. I utgangspunktet trenger man ikke ? gj?re noen endringer i Apache-oppsettet for ? f? dette til ? virke med v?re lastbalanserere, men endringer er n?dvendig for ? gjenopprette opprinnelig klient-IP. For ? gj?re dette i Apache, benytter man modulen mod_remoteip, hvor dette kan l?ses med kun noen f? linjer konfigurasjon.

mod_remoteip

F?rst m? man skru p? modulen mod_remoteip. P? Red Hat er denne allerede inkludert i httpd-pakken, s? man trenger ikke installere noe ekstra for dette. Hvis modulen ikke allerede er lastet inn, kan den enkelt legges inn som en linje der man laster inn andre moduler:

Loadmodule remoteip_module modules/mod_remoteip.so

Videre m? man fortelle Apache hvilken header den skal hente IP fra, samt hvilke lastbalanserere man har i forkant.

RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy w3prod-lb-uio01.uio.no
RemoteIPTrustedProxy w3prod-lb-uio02.uio.no

Noen vil kanskje foretrekke ? heller bruke IPv4- og IPv6-adressene. Da m? man i s? fall huske ? legge inn begge, alts? b?de IPv4 og IPv6 for begge lastbalansererne, siden trafikk kan komme fra begge lastbalanserere og begge IP-versjoner.

I eksempelet over sier man alts? at klientens IP-adresse skal hentes fra HTTP-headeren X-Forwarded-For, og at denne informasjonen kun skal stoles p? dersom den stammer fra lastbalansererne w3prod-lb-uio01.uio.no eller w3prod-lb-uio02.uio.no.

I noen tilfeller vil tjenesten settes opp p? andre lastbalanserere enn de i eksempelet, f.eks. dersom tjenesten er en test-instans, eller dersom den kj?rer i et annet milj? (OpenShift, Educloud eller annet). Det ligger en full liste over alle lastbalanserere i git, men er du usikker p? dette s? sp?r oss gjerne. Det er ogs? mulig ? si at man stoler p? hele UiOs nett, men man er da n?dt til ? ta h?yde for b?de IPv4 og IPv6. Dette er i utgangspunktet noe mindre sikkert, og gj?res i s? fall p? eget ansvar.

Loggformat

Loggformatet m? s? oppdateres til ? benytte verdien fra "X-Forwarded-For". Man kan benytte hvilket loggformat man m?tte ?nske, men vi vil foresl? flg., ettersom dette enkelt vil kunne parses av DataOPS uten behov for videre tilpasninger:

LogFormat "%a %v %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined

Det siste ordet i linjen er navnet p? loggformatet man har definert, som man s? m? s?rge for ? gjenbruke der man definerer logger. I dette eksempelet defineres alts? et loggformat kalt "combined". Dette er et navn som er ofte brukt i Apache, og gjerne vil v?re definert fra f?r av, men da med et annet format enn det vi her foresl?r.

Det enkleste vil da v?re ? finne linjene som starter p? CustomLog, og se p? slutten av linjen for ? finne ut navnet p? loggformatet man allerede bruker, f.eks. "combined" eller "common". Man kan s? finne den eksisterende LogFormat-linjen som slutter p? dette navnet, og bytte denne ut med linjen over, med samme navn p? slutten som det man alt bruker i CustomLog-linjer. Da holder det ? oppdatere denne ene linjen (som starter p? LogFormat), og man trenger ikke ? endre noen linjer som definerer logger (de som starter p? CustomLog).

Alternativt kan man legge til en ny loggformat-definisjon lik den over, og istedenfor "combined" kalle den f.eks. "uio" eller hva som helst. Da kan man spesifisere at logger istedet skal bruke dette nye formatet kalt "uio". Et eksempel p? sistnevnte kunne sett slik ut:

CustomLog /var/log/httpd/foo.uio.no/access_log uio

Om man ikke ?nsker ? bruke det foresl?tte loggformatet, kan man gj?re en mindre endring i det loggformatet man selv foretrekker, og simpelthen bytte fra "%h" til "%a". Dette er i seg selv tilstrekkelig for ? f? riktig kilde-IP i logger.

HTTP/2

Man b?r ogs? s?rge for ? skru p? st?tte for HTTP/2, ettersom denne har langt bedre ytelse enn den eldre (og n? ganske gamle) HTTP/1.1. I webservere - ogs? Apache - m? dette vanligvis aktivt skrus p? for ? brukes.

Dette gj?r man ved ? f?rst installere pakken mod_http2 med flg. systemkommando:

sudo yum install -y mod_http2

S? laste modulen i Apache-config, samme sted hvor man laster andre moduler:

LoadModule http2_module modules/mod_http2.so

Og til sist aktivere protokollen i Apache-config:

Protocols h2 h2c http/1.1

Denne siste linjen kan erstatte evt. tidligere Protocols-linje(r) man m?tte ha fra f?r. Hvis man ikke har en slik fra f?r av, kan denne puttes enten (helst) i generell server config, eller (evt.) inni en VirtualHost-blokk.

N?r trafikk fra lastbalanserer til backend (alts? Apache) g?r over HTTPS (port 443), vil da oppgradering til HTTP/2 skje automatisk, og man trenger ikke foreta seg noe mer.

Hvis den derimot g?r over HTTP (port 80), vil ikke oppgradering til HTTP/2 skje av seg selv, og lastbalanserer m? eksplisitt fortelles at den skal bruke dette. Dette gj?r man ved ? be www-drift om ? legge dette til. Konfigurasjonen man skal be om er dette:

backend_http_version: proto h2

Komprimering

Komprimering av innhold f?r det sendes til klient vil forbedre ytelsen p? lasting av sider, og dermed brukeropplevelsen. Her er det dog flere hensyn ? ta. Ikke alle filtyper er komprimerbare, f.eks. kan man normalt ikke komprimere bilder eller annet mediainnhold. Det finnes dessuten forskjellige komprimeringsalgoritmer ? velge mellom, og ikke alle er st?ttet av alle servere, eller alle klienter. Det riktige valget vil v?re den beste (og som regel mest moderne) komprimeringsalgoritmen som er st?ttet av backend, som klient oppgir at den st?tter (i request headeren Accept-Encoding).

N?r ikke backend komprimerer innhold, vil lastbalanserer automatisk komprimere svaret fra en backend dersom dette ikke alt er komprimert, s? fremt filtypen er av en type den vet kan komprimeres. Dette s?rger for at komprimering alltid tas i bruk n?r dette gir mening, for all trafikk som g?r gjennom lastbalanserer. Likevel er det ?nskelig at backend komprimerer innhold der dette er mulig, av flere ?rsaker:

  • N?r komprimeringen gj?res av backend istedenfor lastbalanserer, s?rger man for at lasten av ? komprimere fordeles utover alle tjenester, istedenfor at lastbalanserer m? p?ta seg hele byrden for alle
  • Lastbalanserer st?tter per i dag ikke de mest moderne komprimeringsalgoritmene, som gjerne er st?ttet i webservere, og vi har ikke enn? funnet noen m?te ? integrere dette p?
  • Lastbalanserer har en ?vre antallsbegrensning i listen over filtyper man kan angi at ?nskes komprimert

For Apache kan dette enklest l?ses ved ? ta i bruk samme konfigurasjon som www-drift benytter p? sine servere. Denne dekker alle relevante filtyper, og s?rger for at den mest effektive komprimeringsalgoritmen som st?ttes av begge parter til enhver tid blir brukt. Filen kan plasseres f.eks. i /etc/httpd/conf.d/, og dette vil som regel v?re alt du trenger ? gj?re.

Dersom du ikke har tilgang til filen, ta kontakt med www-drift, s? kan vi enten gi deg tilgang eller sende deg en kopi.

nginx

I utgangspunktet trenger man ikke ? gj?re noen endringer i nginx-oppsettet for ? f? dette til ? virke med v?re lastbalanserere, men endringer er n?dvendig for ? gjenopprette opprinnelig klient-IP. For ? gj?re dette i nginx, benytter man modulen real_ip, hvor dette kan l?ses med kun noen f? linjer konfigurasjon. P? Red Hat er denne allerede inkludert i nginx-pakken, s? man trenger ikke installere noe ekstra for dette.

real_ip

For ? ta i bruk real_ip, legger man til f?lgende i "http"-seksjonen av konfigurasjon, der "..." b?de f?r og etter er resten av den eksisterende konfigurasjonen. Den relevante koden m? legges til f?r "log_format" defineres:

http {
...
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
    set_real_ip_from w3prod-lb-uio01.uio.no;
    set_real_ip_from w3prod-lb-uio02.uio.no;
...

}

I eksempelet over sier man alts? at klientens IP-adresse ("Real IP") skal hentes fra HTTP-headeren X-Forwarded-For, og at denne informasjonen kun skal stoles p? dersom den stammer fra lastbalansererne w3prod-lb-uio01.uio.no eller w3prod-lb-uio02.uio.no. Siden versjon 1.31.1 av nginx skal det v?re mulig ? angi hostnavn p? denne m?ten, men hvis det ikke fungerer, kan du istedet legge inn IP-adressene til lastbalansererne. Det er da viktig at du legger inn b?de IPv4- og IPv6-adressene til begge lastbalansererne, alts? totalt fire oppf?ringer.

I noen tilfeller vil tjenesten settes opp p? andre lastbalanserere enn de i eksempelet, f.eks. dersom tjenesten er en test-instans, eller dersom den kj?rer i et annet milj? (OpenShift, Educloud eller annet). Det ligger en full liste over alle lastbalanserere i git, men er du usikker p? dette s? sp?r oss gjerne. Det er ogs? mulig ? si at man stoler p? hele UiOs nett, men man er da n?dt til ? ta h?yde for b?de IPv4 og IPv6. Dette er i utgangspunktet noe mindre sikkert, og gj?res i s? fall p? eget ansvar.

Loggformat

N?r man bruker real_ip-modulen i nginx, vil denne s?rge for ? benytte korrekt IP ogs? i logger. Det er dermed ikke n?dvendig ? gj?re noen ytterligere justeringer i nginx for ? f? riktige logger.

HTTP/2

I tillegg anbefaler vi at man tillater trafikk over HTTP/2, ettersom denne har langt bedre ytelse enn den eldre (og n? ganske gamle) HTTP/1.1. I webservere - ogs? nginx - m? dette vanligvis aktivt skrus p? for ? brukes. For ? f? til dette er det to ting man m? ta stilling til.

Den f?rste er hvilken versjon av nginx som brukes. Dette finner man ut med flg. kommando:

nginx -v

Det vesentlige her er hvorvidt denne er h?yere eller lavere enn 1.25.1, ettersom konfigurasjonssyntaks endret seg i denne versjonen. Hvis man bruker nginx p? Red Hat vil den v?re lavere, ettersom ingen Red Hat-versjoner forel?pig inneholder nyere versjoner enn dette. Men hvis man f.eks. kj?rer nginx i en container, eksempelvis p? OpenShift, kan det v?re man har en h?yere versjon.

Dersom man har en lavere versjon enn 1.25.1, finner man linjene som starter med listen, og legger til http2 p? slutten av disse.

Alts? hvis man har en linje som f.eks. ser slik ut:

listen 443 ssl;

Endrer man denne til ? se slik ut:

listen 443 ssl http2;

Hvis port 80 er i bruk b?r man gj?re tilsvarende endring for tilh?rende listen-linje der ogs?, men s?rg for ? lese neste punkt f?rst.

Hvis man derimot har en h?yere versjon enn 1.25.1, legger man istedet til denne linjen:

http2 on;

Denne plasseres da under listen-linjen beskrevet i forrige eksempel.

Det neste man m? ta stilling til er om trafikk fra lastbalanserer til backend (alts? nginx) g?r over HTTP (port 80) eller HTTPS (port 443). Dersom den g?r over HTTPS, vil HTTP/2 bli brukt automatisk (s? lenge man har gjort endringen beskrevet over), og man trenger ikke foreta seg noe mer. Hvis man bruker nginx i OpenShift i Passthrough-modus vil HTTPS alltid bli brukt, men man m? likevel s?rge for ? gj?re endringen beskrevet over for at det skal virke.

Hvis den derimot g?r over HTTP (port 80), vil ikke oppgradering til HTTP/2 skje av seg selv, og lastbalanserer m? eksplisitt fortelles at den skal bruke dette. Dette gj?r man ved ? be www-drift om ? legge dette til. Konfigurasjonen man skal be om er dette:

backend_http_version: proto h2

Merk at hvis man bruker nginx i OpenShift i Edge-modus trenger man per i dag ikke ? gj?re dette, ettersom det forel?pig ikke st?ttes i mellomliggende lag (OpenShifts interne router/ingress-punkt).

Komprimering

Komprimering av innhold f?r det sendes til klient vil forbedre ytelsen p? lasting av sider, og dermed brukeropplevelsen. Her er det dog flere hensyn ? ta. Ikke alle filtyper er komprimerbare, f.eks. kan man normalt ikke komprimere bilder eller annet mediainnhold. Det finnes dessuten forskjellige komprimeringsalgoritmer ? velge mellom, og ikke alle er st?ttet av alle servere, eller alle klienter. Det riktige valget vil v?re den beste (og som regel mest moderne) komprimeringsalgoritmen som er st?ttet av backend, som klient oppgir at den st?tter (i request headeren Accept-Encoding).

N?r ikke backend komprimerer innhold, vil lastbalanserer automatisk komprimere svaret fra en backend dersom dette ikke alt er komprimert, s? fremt filtypen er av en type den vet kan komprimeres. Dette s?rger for at komprimering alltid tas i bruk n?r dette gir mening, for all trafikk som g?r gjennom lastbalanserer. Likevel er det ?nskelig at backend komprimerer innhold der dette er mulig, av flere ?rsaker:

  • N?r komprimeringen gj?res av backend istedenfor lastbalanserer, s?rger man for at lasten av ? komprimere fordeles utover alle tjenester, istedenfor at lastbalanserer m? p?ta seg hele byrden for alle
  • Lastbalanserer st?tter per i dag ikke de mest moderne komprimeringsalgoritmene, som gjerne er st?ttet i webservere, og vi har ikke enn? funnet noen m?te ? integrere dette p?
  • Lastbalanserer har en ?vre antallsbegrensning i listen over filtyper man kan angi at ?nskes komprimert

For nginx har vi dessverre forel?pig ikke en ferdig konfigurasjon som kan benyttes, slik vi har for Apache. Dersom noen f?r til ? lage dette, tar vi veldig gjerne imot bidrag! Ta gjerne en titt p? konfigurasjonen www-drift benytter p? sine Apache-servere for inspirasjon - her vil man kunne se f.eks. hvilke MIME-typer vi dekker. S?rlig interessant ville det v?rt ? finne en god m?te man kan ta i bruk nginx-modulene for b?de brotli og zstd, b?de i RHEL og i containere.

Dersom du ikke har tilgang til filen, ta kontakt med www-drift, s? kan vi enten gi deg tilgang eller sende deg en kopi.

Reversproxy

Dersom du skal bruke nginx som reversproxy foran en applikasjonsserver, som beskrevet i generelt-seksjonen, er det noen linjer til som kan v?re greie ? f? med, for ? s?rge for at korrekt klient-IP blir videreformidlet til applikasjonsserveren p? riktig m?te. I tillegg er det gjerne lurt ? angi at man ?nsker ? benytte HTTP/1.1 (som i skrivende stund er den h?yeste HTTP-versjonen nginx st?tter som reversproxy). Hvis ikke vil den benytte HTTP/1.0, som ikke kan formidle riktig Host header, og heller ikke st?tte keepalive, som gir bedre utnyttelse av forbindelser.

En helhetlig config for reversproxy mot en applikasjonsserver kj?rende p? localhost p? port 8080 kan dermed f.eks. se omtrent slik ut (merk at her m? navnet foo.uio.no samt sti til sertifikat byttes ut):

server {
    listen 443 http2;
    server_name foo.uio.no;

    # Specify certificate
    ssl_certificate /path/to/foo.uio.no_fullchain.crt;
    ssl_certificate_key /path/to/foo.uio.no.key;
    
    # Trusted proxies
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
    set_real_ip_from w3prod-lb-uio01.uio.no;
    set_real_ip_from w3prod-lb-uio02.uio.no;

    # Proxy to port 8080 on localhost
    location / {
        proxy_pass http://localhost:8080/;
        proxy_http_version 1.1;
        proxy_set_header Host $proxy_host;
        proxy_set_header X-Real-IP $http_x_forwarded_for;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Enkelte guider p? nett vil kanskje foresl? at du legger til headere som X-Forwarded-Proto. Dette er ikke n?dvendig bak UiOs lastbalansering, som forklart i avsnittet om videresending til HTTPS.

IIS

Ogs? Microsoft Internet Information Services (IIS) har st?tte for X-Forwarded-For, selv om denne er noe mer begrenset enn i Apache og nginx. I Apache og nginx vil relevante interne variabler i webserver endre seg slik at klientens IP (hentet fra X-Forwarded-For) i prinsippet erstatter lastbalansererens IP, men i IIS er ikke dette tilfelle. Man vil likevel kunne f? riktig IP i logger, samt ha mulighet til ? benytte benytte ACLer der dette er relevant.

Vi har dessverre forel?pig ikke dokumentasjon for hvordan dette settes opp i IIS, men vi vet at seksjon for datainnsamling og automasjon (DIA) jobber med ? f? p? plass en felles l?sning som skal gj?re det enkelt og automatisk ? f? IIS til ? generere logger i ?nsket format for DataOps, med korrekt klient-IP. Inntil videre kan man ta kontakt med DIA for ? f? hjelp til ? sette dette opp riktig.

Applikasjonsservere

Les aller f?rst avsnittet Generelt, som inneholder viktig generell informasjon om hvordan applikasjonsservere b?r settes opp. Med applikasjonsserver mener vi i hovedsak egne dedikerte prosesser som server en webapplikasjon, som regel over HTTP. Det finnes mange gode artikler som nok definerer dette bedre enn vi klarer.

Ofte betjenes en tjeneste av en applikasjonsserver. Disse finnes det utallige varianter av, med varierende st?tte for slike ting som en webserver kan tilby, som beskrevet i Generelt-avsnittet. Vi anbefaler derfor alltid at en webserver plasseres foran en evt. applikasjonsserver. F?lger man instruksjonene p? denne siden, vil man f? riktig IP i webserver, b?de i logger og ?vrig milj?. I mange tilfeller vil dette v?re tilstrekkelig.

N?r en applikasjonsserver er i bruk, bak en webserver, kan det dog hende man ogs? her ?nsker ? f? tilgang til faktisk klient-IP. Dette kan f.eks. v?re tilfelle dersom man trenger ? generere logger som inneholder brukernavn (sammen med (korrekt) IP), eller andre detaljer som en webserver ikke vil vite om n?r den kun reversproxyer foresp?rsler videre. Det kan ogs? v?re at brukers IP skal benyttes i selve tjenesten p? noe vis. Hvordan dette kan l?ses vil avhenge av hvilken applikasjonsserver man bruker, og hvilke muligheter denne gir.

Applikasjonsservere kan i denne sammenhengen litt forenklet deles opp i to kategorier:

Direkte integrert og andre protokoller

Dette gjelder f.eks.:

I disse tilfellene vil som regel milj? fra webserver arves direkte, slik at variabler vil f?lge det som er satt i webserver, inkludert kilde-IP. Har man konfigurert ting riktig i webserver skal med andre ord vanligvis dette fungere "out of the box".

Merk at av disse alternativene, er det egentlig kun FastCGI/SCGI og (u)WSGI/ASGI vi normalt ville anbefalt i dag. De andre er n? i realiteten utdaterte, og b?r som regel byttes ut med mer moderne og fremtidsrettede l?sninger.

For moduler som kj?rer direkte i webserver (mod_php, mod_perl m.fl.), samt CGI, vil mye av det som st?r skrevet om applikasjonsservere dessuten ikke v?re relevant, ettersom disse ikke kj?rer som egne prosesser uavhengig av webserver, men istedet spawnes av (eller kj?rer som del av) webserverens egen prosess. Dermed vil de s?nn sett ikke egentlig regnes som applikasjonsservere - i hvert fall ikke med definisjonen vi bruker her.

Integrert over HTTP

Dette gjelder tilfeller der webserver snakker med applikasjonsserver kun over HTTP, og dermed fungerer som en ren reversproxy. Dersom tjenesten i prinsippet kan fungere uten behov for en webserver foran, er det trolig dette dere bruker. Merk at vi anbefaler likevel at man setter en webserver mellom lastbalanserer og applikasjonsserver. Se avsnittene Generelt, samt Gjenopprette korrekt IP, for en forklaring av hvorfor dette er anbefalt.

For at en applikasjonsserver skal se korrekt IP i slike tilfeller, m? (ogs?) applikasjonsserver kunne konfigureres til ? benytte HTTP-headeren X-Forwarded-For (eller Forwarded) og beslektede headere. I hvilken grad dette er st?ttet, og hvordan st?tten er implementert, vil variere stort mellom forskjellige applikasjonsservere, og det finnes altfor mange av disse til at vi kan dekke alle her. Dersom du setter deg fast, kan du gjerne ta kontakt, s? skal vi gj?re v?rt beste for ? hjelpe.

Av headere som kan v?re nyttige finner man bl.a. X-Forwarded-By som angir hvilken lastbalanserer X-Forwarded-For ble satt av (kan benyttes til ? spesifisere hvilke lastbalanserere man vil stole p?), X-Forwarded-Proto som angir hvilken protokoll innkommende foresp?rsel benyttet (kan f.eks. benyttes til ? forhindre redirect loop til HTTPS n?r applikasjonen tror den mottar foresp?rsler over HTTP) m.fl.

PROXY protocol

Det finnes ogs? en annen m?te for lastbalanserer ? videreformidle klientens IP p?, kalt PROXY protocol, men til forskjell fra X-Forwarded-For opererer denne i TCP-laget. Dette forutsetter at backend st?tter denne protokollen (hvilket b?de Apache og nginx gj?r), samt at st?tte for den aktiveres for tjenesten i lastbalanserer. Vi bruker ikke PROXY protocol noe s?rlig per i dag, men den kan v?re grei ? vite om. Den er ogs? beste l?sning der andre protokoller enn HTTP skal lastbalanseres, men dette gj?res kun unntaksvis.

Tilgangskontroll

Noen ganger har man behov for ? begrense tilgang basert p? IP, enten til spesifikke nett (subnett/CIDR) eller til enkelt(e) IP-adresse(r). Et vanlig bruksomr?de er ? begrense tilgang til klienter p? UiO-nett. Vi anbefaler at dette gj?res i webserver, som beskrevet i Generelt-avsnittet. Ved ? f?lge eksemplene over, "gjenopprettes" kilde-IP av webserver, slik ting fungerer p? samme m?te som n?r det ikke er et revers-proxy-lag med lastbalansering imellom. Dermed vil man kunne benytte vanlig ACL-funksjonalitet i webserver, akkurat som vanlig.

N?r man setter opp IP-basert tilgangskontroll, anbefaler vi at det benyttes en egen feilmeldingsside til dette. Denne kan gjerne forklare at tilgang nektes fordi man ikke kommer fra riktig nett eller IP, slik at bruker f?r en indikasjon p? hva som kan eller m? gj?res for ? f? tilgang til tjenesten (selvsagt uten ? avsl?re potensielt sensitive detaljer). P? denne siden kan det gjerne ogs? linkes til andre sider med mer informasjon om dette, der dette finnes. Se et godt eksempel p? hvordan dette kan se ut p? siden Brukerinfo har opprettet til dette form?let.

Det er ogs? mulig ? legge inn IP-basert tilgangskontroll for en tjeneste direkte i lastbalanserer, men dette frar?der vi. Dette er mer komplisert ? vedlikeholde, da alle endringer n?dvendigvis m? involvere www-drift som drifter lastbalanseringsl?sningen, til forskjell fra i webserver hvor man styrer dette helt selv. Det vil dessuten resultere i en mindre brukervennlig og hjelpsom feilmeldingsside, da denne vil v?re en generisk type som ikke gir noen indikasjon p? hvorfor tilgang nektes, og kan forveksles med feilmeldinger man mottar n?r manglende tilgang skyldes helt andre ?rsaker. Dette kan igjen medf?re un?dvendig ?kt trykk p? IT-hjelp, som da kan motta saker fra brukere som ikke skj?nner hvorfor de ikke f?r tilgang.

Caching

For ? s?rge for at en tjeneste oppn?r best mulig ytelse, er det essensielt ? utnytte de mulighetene man f?r vha. caching. Caching s?rger for at n?r en klient laster en tidligere bes?kt side, s? henter den p? nytt kun de ressursene som er n?dvendig, dvs. de ressursene som man kan forvente at har endret seg siden sist siden ble lastet. Dette s?rger b?de for at tjenesten oppleves raskere og mer responsiv for brukeren, samtidig som det det sparer betydelig ressursbruk i tjenestelaget.

M?ten man kommuniserer om og n?r en cache (f.eks. klientens innebygde cache) trenger ? laste ressurser p? nytt er i dag i all hovedsak vha. headeren Cache-Control. Andre headere enn denne har v?rt i bruk tidligere, men disse vil som regel ignoreres s? lenge Cache-Control forekommer, og lastbalanserer s?rger for at denne s? ? si alltid gj?r det. Dermed er det ikke n?dvendig ? sette eller bry seg om andre headere enn denne.

N?r en tjeneste sender denne headeren i en respons, vil lastbalanserer i de fleste tilfeller respektere verdiene som kommer fra tjenesten, men den vil i visse tilfeller pr?ve ? hjelpe, og i enkelte tilfeller velge ? overstyre. Dersom den ser at en respons ikke burde caches, f.eks. dersom responsen setter en sesjons-cookie eller p? andre m?ter vurderes som sensitiv, vil den s?rge for at headeren inneholder verdier som tilsier at responsen ikke skal caches i noe lag. Dersom den derimot ser at alt tyder p? at responsen aldri vil endre seg p? denne adressen - at ressursen er immutable - vil den s?rge for at dette videreformidles slik at ressursen kan oppn? optimal caching. Som oftest gjelder dette statiske ressurser hvor adressen er gjort unik, enten ved et versjonsnummer i dir/filnavn, eller n?r det inkluderes en hex-basert hash enten i filnavn eller i et gjenkjent query-parameter.

Dersom en tjeneste ikke sender Cache-Control i sin respons, vil lastbalanserer i mange tilfeller legge denne p?, med relativt konservative verdier basert p? innholdets type. Alts? vil dokumenter caches ganske kort (bare noen minutter), mens statiske ressurser vil caches lengre, basert p? type innhold.

Samlet sett s?rger dette for at de fleste foresp?rsler som regel vil f? en egnet caching policy, men i tilfeller der det hersker noen grad av tvil, og tjenesten selv har oppgitt en Cache-Control header, vil alts? som regel denne benyttes. Det er derfor viktig at man har et bevisst forhold til denne headeren, og er sikker p? at man benytter hensiktsmessige og godt egnede verdier.

Dette er et komplekst tema, og vi kan ikke dekke alt som inng?r i dette her. Utviklere og tjenesteeiere anbefales ? sette seg inn i dette, og skaffe seg i hvert fall et grovt overblikk over de grunnleggende prinsippene som ligger til grunn. Artikler som Cache-Control for Civilians anbefales for dette.

Vi vil likevel fors?ke ? gi noen pekepinner under for enkelte best practices knyttet til caching, og s?ledes pr?ve ? ta h?yde for noen av de vanligste problemene vi ser oppst? knyttet til caching.

Send Cache-Control header hvis du kan

TL;DR: Tjenesten vet som regel best hva som kan og ikke kan caches, samt hvor lenge og hvordan

N?r lastbalanserer mottar responser som mangler Cache-Control header, vil den (som oppsummert over) fors?ke ? gj?re noen delvis kvalifiserte antakelser basert p? innholdets type. Disse vil dog sjeldent v?re like gode som konkret kunnskap om hver spesifikke respons, og denne kunnskapen er det bare tjenesten selv - og de som lager den - som har. Det anbefales derfor ? alltid sende en Cache-Control header med alle responser, som er egnet for hver enkelte respons (se punktene under), n?r man har muligheten til dette. Eksempelvis kan det v?re at man ?nsker dokument-delen av en side alltid skal v?re fersk - det vil den ikke n?dvendigvis v?re dersom man ikke angir en Cache-Control header som sier dette.

Skill mellom dynamiske og statiske ressurser

TL;DR: Bare sett no-store, no-cache eller lav max-age for de responsene hvor det faktisk trengs!

Dette er trolig punktet det syndes aller mest mot. Man angir en policy per tjeneste heller enn per ressurs, og s? lar denne gjelde for alle responser for tjenesten. Dette er som regel en riktig d?rlig idé, ettersom det er all grunn til ? forskjellsbehandle disse. La oss se p? et par eksempler.

Dokumentdelen av en webside - dvs. de responsene som returnerer HTML - kan regnes som statisk hvis den er lik for alle som bes?ker den. Dette kan v?re en ferdig generert webside som serves som fil fra filsystemet, men det kan ogs? v?re statiske sider p? en ellers dynamisk webtjeneste. F.eks. kan en egen loginside gjerne regnes som statisk ettersom den er lik for alle, ikke i seg selv inneholder sensitiv informasjon, og sjeldent endres. En statisk webside kan med fordel caches, men kanskje ikke n?dvendigvis s? veldig lenge.

En webside (igjen dokumentdelen) vil derimot regnes som dynamisk dersom det motsatte er sant. F.eks. at innholdet p? en og samme adresse ser forskjellig ut for hvert bes?k, basert p? slikt som innholdet i en sesjons-cookie, innholdet p? selve siden (som kanskje blir generert p? nytt ved hver lasting), eller kanskje basert p? hvor man bes?ker den fra (kanskje den kun er tillatt fra enkelte IP-adresser el.l.). Slike sider ?nsker man gjerne at ikke caches overhodet, eller kanskje at de caches for sluttbrukeren men ikke i evt. mellomliggende lag, eller f.eks. at den kan serves direkte fra cache men revalideres i bakgrunnen. Her finnes det mange muligheter - se artikkelen Cache-Control for Civilians nevnt tidligere.

Den siste kategorien er dog den vel s? viktige her, nemlig st?tteressurser. En webside best?r av en rekke ressurser utover dokumentet, slik som stylesheets, JavaScript, bilder, og kanskje ogs? annet som fonter, video eller audio, og masse annet spennende. Disse ressursene er ofte de tyngste (st?rste) ? overf?re, og disse ressursene kan som regel caches med stor fordel - men bare hvis man gir lov til det!

Selv p? en sensitiv webside er det ofte hensiktsmessig ? tillate caching av st?tteressursene, nettopp fordi det er ikke disse som er sensitive. Et JavaScript eller en CSS-fil vil gjerne v?re lik for alle brukere, uavhengig av om brukeren er innlogget eller ikke. Ved ? tillate caching av disse, unng?r man at disse stadig (og helt un?dvendig) m? lastes p? nytt etter hvert som brukeren navigerer rundt i tjenesten. I de fleste tilfeller gjelder dette ogs? f.eks. bilder og andre ressurser, og da burde ogs? disse f? samme liberale policy. I de tilfeller hvor det derimot er n?dvendig at f.eks. enkelte bilder kun vises til innloggede brukere, kan disse likevel caches i klientlaget (men ikke i evt. mellomlag), eller man kan f.eks. benytte "Vary: cookie" header (se avsnitt under) for ? skille mellom disse.

Oppsummert kan man alts? si at man b?r definere en caching policy per ressurs og ikke per tjeneste. Gjort riktig vil dette kunne gi optimalt resultat.

Ikke sett for kort max-age

TL;DR: Ikke sett en lav max-age p? ressurser som sjeldent endres!

Hvor lenge en respons kan brukes fra cache bestemmes av Cache-Control-direktivet max-age (samt s-maxage for mellomliggende caching-lag dersom denne ogs? er oppgitt). Ofte ser man at denne verdien er satt uforholdsmessig lav, og ?rsaken til dette er som regel - som forklart i forrige punkt - at det er satt én caching policy basert p? dokumenter, som s? ogs? blir brukt for st?tteressurser, heller enn ? skille mellom disse.

For dokumenter gir det gjerne mening ? sette en relativt konservativ verdi - i hvert fall for sider som ikke endrer seg s? veldig ofte. Men for andre ressurser mister man mye verdi av caching dersom verdien settes for lavt, ettersom ressursen m? hentes (eller i det minste sjekkes) p? nytt n?r utl?psalderen er n?dd. Hvis man sjeldent oppdaterer en fil, og det ikke er s? farlig om enkelte klienter fortsetter ? se den gamle filen en stund etter at den er oppdatert, vurder om verdien kanskje kan settes h?yere.

Bruk cache busting og immutable

TL;DR: Ta i bruk cache busting der du kan, og sett da immutable i Cache-Control!

Den aller mest effektive m?ten ? tiln?rme seg caching p? er ved ? benytte cache busting. Dette vil si at man s?rger for ? gi hver unike kopi av en statisk fil en unik URL, ettersom ressurser caches basert p? URL. N?r en ny versjon av siden s? genereres p? nytt, f.eks. n?r man gj?r en release, vil alle filer som har endret seg siden forrige gang f? nytt unikt navn, og dermed ny URL. Den nye versjonen av siden vil s? referere til ressursene sine med det til enhver tid gjeldende navnet, slik at disse lastes enten fra cache, eller fra tjenesten, ut fra hvorvidt den refererte URLen eksisterer i cache. Dermed "buster" man de utdaterte filene fra cache, ved at disse simpelthen ikke lenger refereres.

Det finnes flere m?ter ? gj?re dette p?, men den mest anbefalte er ? generere en hex hash av filens innhold, og s? bruke denne som fingerprint som utgj?r del av filnavnet, heller enn i f.eks. en query string eller andre varianter. Se detaljer i Cache-Control for Civilians for en oppsummering av dette.

N?r dette er p? plass, kan og b?r man sette direktivet immutable i Cache-Control-header, samt en veldig lang max-age for ? ta h?yde for evt. klienter som ikke enn? st?tter immutable-direktivet. Da s?rger man for at den unike URLen som refererer til den unike kopien av filen aldri vil trenge ? lastes p? nytt, og har s?ledes oppn?dd optimal caching.

Mange moderne frontend-rammeverk (f.eks. NextJS) tar seg av alt dette automatisk, og gj?r hele jobben for deg. Har du mulighet til ? gj?re dette i rammeverket du bruker, er det varmt anbefalt ? gj?re dette, samt verifisere at det fungerer som beskrevet.

V?r n?ysom ved bruk av Vary: cookie

TL;DR: Ikke sett Vary: cookie p? responser hvor dette ikke faktisk trengs!

En header som ikke er Cache-Control men som likevel kan ha stor effekt p? caching er Vary. Denne sier hvilke headere i en foresp?rsel som kan resultere i et annet svar fra tjenesten. Verdier man ofte ser i Vary-headeren er typisk Accept-Encoding, som sier at forskjellige svar vil gis basert p? hvilken type komprimering (eller evt. ingen komprimering) klienten oppgir at den st?tter. Et svar som er komprimert med f.eks. gzip vil naturlig nok v?re ulikt fra et ukomprimert svar - selv om innholdet kanskje ser likt ut etter at klienten har dekomprimert det. Derfor er det n?dvendig ? skille mellom svar p? denne m?ten, og en mellomliggende cache som skal kunne cache responser som ellers er cachebare m? da cache en kopi for hver utgave av en side som blir levert - i dette eksempelet en kopi som er gzipet og en kopi som er ukomprimert. Ettersom det er f? komprimeringsvarianter i bruk, skalerer dette greit. Cachen holder da alts? styr p? én kopi per forskjellig verdi av headerne som forekommer i Vary-headeren.

Man kan dog angi et hvilket som helst header-navn som verdi i Vary-headeren, og da blir ting fort vrient, fordi det er vanskelig for mellomliggende cache ? vite hvor mange variasjoner det kan finnes som svar p? hver av header-verdiene. Dette gjelder s?rlig n?r man putter verdien cookie i Vary-headeren, ettersom det i prinsippet vil finnes (minst) like mange forskjellige verdier av cookie som det finnes klienter, og dette kan dermed umulig skalere. I praksis gj?r dette det umulig ? benytte mellomliggende cache for slike responser, og den vil heller ikke pr?ve. Dermed mister man et slikt caching-lag.

S? hvorfor skulle man da ?nske ? gj?re dette? Svaret er ofte for ? beskytte ressurser. Dersom f.eks. et bilde kun skal v?re tilgjengelig for innloggede brukere, eller kun for en viss kategori av innloggede brukere el.l., kan Vary: cookie v?re en l?sning p? dette - ettersom det da er den enkelte brukers tilgangskontroll (som bestemmes ut fra brukers sesjon, som igjen bestemmes ut fra brukers sesjons-cookie) som vil avgj?re dette. Med andre ord vil tilgang m?tte avgj?res p? individniv?, og dette oppn?r man ved ? gj?re ting p? denne m?ten.

G?r man for denne l?sningen, er det viktig ? s?rge for at Vary: cookie bare sendes p? de ressursene som er ment ? v?re tilgangskontrollert. Alts? vil det v?re lite hensiktsmessig ? sende denne for alle bilder "bare for sikkerhets skyld", ettersom det vil medf?re at ingen bilder vil kunne caches i mellomliggende lag - uavhengig av om de egentlig trenger slik beskyttelse. Istedet burde bruken av Vary: cookie i slike tilfeller trigges av at det settes tilgangskontroll p? bildet, og med andre ord h?ndteres per enkeltressurs. Da vil man oppn? b?de optimal kontroll og optimal caching.

Et annet alternativ kan v?re ? skille mellom max-age og s-maxage i Cache-Control-headeren. Sistnevnte p?virker kun caching i mellomlag, slik at hvis denne der settes til 0, vil man s?rge for at ressursene kan caches i klientlaget, men ikke i mellomlag. Man kan ogs? sette direktivet private, som er en direkte beskjed om at ressursen helt enkelt ikke skal lagres i mellomlag. Det er fullt mulig (og veldig vanlig) ? kombinere flere direktiv i Cache-Control-headeren, og selv om dette kan virke litt som sm?r p? flesk, er hensikten ofte ? s?rge for bredest mulig nedslagsfelt, slik at man effektivt kommuniserer samme hensikt til implementasjoner med varierende grad av st?tte for enkelte caching-direktiver.

V?r bevisst ved bruk av must-revalidate

TL;DR: Bruk gjerne must-revalidate, men ikke la det p?virke valg av verdi i max-age!

must-revalidate er i utgangspunktet et veldig fint direktiv ? bruke, ettersom det gir et fint kompromiss; ressursen serves fra cache, men samtidig revalideres den i bakgrunnen (etter at max-age er n?dd), ved ? sp?rre tjenesten om den har endret seg siden siste cachede kopi. Dersom den har det vil den lastes p? nytt, men inntil da (eller hvis den ikke har endret seg) vil den cachede versjonen benyttes. Dette direktivet kan med andre ord med fordel brukes, men det m? brukes sammen med en max-age, og det er da viktig ? sette max-age hensiktsmessig. Det kan v?re lett ? tenke at siden man har satt must-revalidate, kan man sette max-age lavt, ettersom cachen da vil validere responsen p? nytt mot server uansett. Noen setter s?gar max-age til 0, og tenker da at man slik garanterer en fersk respons fra server hver gang.

Dette stemmer for s? vidt i utgangspunktet, men med noen viktige nyanser. For det f?rste vil man da ende med ? generere en foresp?rsel til tjenesten hver gang selv om ressursen er cachet (eller i hvert fall s? lenge ikke max-age har utl?pt, som jo er umiddelbart dersom den er satt til 0). Om ressursen ikke har endret seg sparer man seg riktig nok fra ? m?tte sende dataene p? nytt, men tjenesten er likevel n?dt til ? sjekke hver gang.
Videre kan dette p?virke caching i mellomlaget, som kanskje ikke st?tter dette direktivet slik klient-cachen gjerne gj?r. Ettersom den da kun vil se p? max-age, vil den dersom denne er satt til 0 ende med ? ikke cache ressursen overhodet, og man mister dermed et helt lag med caching.

must-revalidate er derfor et fint supplement, men som ikke burde ha noen innvirkning p? hvilken verdi man setter i max-age. Sett max-age slik du uansett ville satt den, helt uavhengig av must-revalidate.

Bare bruk no-transform n?r det faktisk er n?dvendig

TL;DR: Ikke bruk no-transform med mindre du har et konkret behov som tilsier dette!

no-transform er et direktiv som sier at mellomliggende lag - caching s? vel som andre - ikke skal p? noe vis endre p? payload i responsen som kommer fra tjenesten. Dette kan i utgangspunktet h?res tilforlatelig nok ut, men det kan fort ha utilsiktede konsekvenser.

Det mest vesentlige av dette er gjerne komprimering. ? komprimere svaret regnes som ? endre p? det (? "transformere" det), og lb vil dermed ikke komprimere et tidligere ukomprimert svar, selv n?r dette ellers ville blitt gjort og hadde gitt gevinst. Dette p?virker dermed ikke n?dvendigvis caching i seg selv, men vil likevel ha en negativ effekt p? ytelse dersom ikke tjenesten selv s?rger for ? komprimere svaret (og gj?r minst en like god jobb som lastbalanserer ville gjort n?r den m? p?ta seg dette ansvaret).

Publisert 12. nov. 2024 14:12 - Sist endret 1. aug. 2025 17:21