Kuidas kasutada Golang 1.8 HTTP / 2 Server Push API-d

Golang 1.8 vabastati koos HTTP / 2 serveri tõukefunktsiooniga. Golang värskendas net / http paketti HTTP / 2 funktsiooni toetamiseks versioonis 1.6 ja see kood juba toetas serveri tõukeks kasutatavat raami PUSH_PROMISE, kuid 1.6-l puudus API selle raami loomiseks. Ja siis sisaldab 1.8 lõpuks seda API-d.

Kuidas kasutada serveripussi?

http.ResponseWriteril on ainulaadne omadus. Liidese http.ResponseWriter taga on peidetud lukustatud meetodid ja need avati tüübivalimise kaudu. Paljud programmeerijad on tuttavad saidiga http.ResponseWriter, kuid ainult kümnendik neist teab seda (uurisin Tokyos Golangi 1.8 väljalaskepeol).

Golang 1.7 ja madalamatel versioonidel on juba kolm varjatud liidest:

func-käitleja (w http.ResponseWriter, r * http.Request) {
    // Avage HTTP / 1.1 tükeldatud reageerimise funktsioon
    f, ok: = w (http.Flusher)
    kui ok {
        f.Flush ()
    }

    // Vabastage abistaja funktsioon tükeldatud pika küsitluse toetamiseks (serverist saadetud sündmused)
    c, ok: = w (http.CloseNotifier)
    kui ok {
        mine func () {
            jaoks {
                vali {
                juhtum <-c.CloseNotify ():

                }
            }
        } ()
    }

    // WebSocketi toetamiseks avage madala taseme pistikupesade juurdepääs
    h, ok: = w. (http.kaaperdaja)
    kui ok {
        konn, rw, viga: = h.Hijack ()
    }
}

Golang 1.8 rakendab Push API-d sarnaselt neile:

func-käitleja (w http.ResponseWriter, r * http.Request) {
    // Avage HTTP / 2 serveri tõuge
    p, ok: = w (http.Pusher)
    kui ok {
        p.Push ("/ cool_style.css", null)
    }
}

HTTP / 2 serveri tõukefunktsiooni saate lisada, kui lisate ülaltoodud koodi http-töötleja funktsioonidesse. Spetsiaalseid konfiguratsioone väljaspool funktsiooni ei pea te lisama.

Kui kasutajaagendid, mis ei toeta HTTP / 2, ebaõnnestub ülekandmine aadressile http.Pusher (ok muutuvad valeks) ja Push () -meetodi kõned jäetakse ära. Võite lihtsalt testida GODEBUG = http2server = 0 abil (keelata HTTP2 serveri funktsioon).

Kuidas see töötab?

Järgmine kood on täielik näide serveri tõukefunktsiooni kasutamiseks:

paketi peamine
import (
    "fmt"
    "io / ioutil"
    "net / http"
)
var pildi [] bait
// pildi ettevalmistamine
func init () {
    var viga viga
    image, err = ioutil.ReadFile ("./ image.png")
    kui eksid! = null {
        paanika (eks)
    }
}
// Saada HTML ja lüka pilt
func handlerHtml (w http.ResponseWriter, r * http.Request) {
    tõukur, ok: = w. (http.Pusher)
    kui ok {
        fmt.Println ("Push / image")
        tõukur. Lükka ("/ pilt", null)
    }
    w.Header (). Lisage ("Sisu tüüp", "tekst / html")
    fmt.Fprintf (w, `    `)
}
// Saada pilt tavalise HTTP-päringuna
func handlerImage (w http.ResponseWriter, r * http.Request) {
    w.Header (). Komplekt ("Sisu tüüp", "pilt / png")
    w.Write (pilt)
}
func main () {
    http.HandleFunc ("/", käitlejaHtml)
    http.HandleFunc ("/ image", handlerImage)
    fmt.Println ("alustage http kuulamist: 18443")
    viga: = http.ListenAndServeTLS (": 18443", "server.crt", "server.key", null)
    fmt.Println (ekslik)
}

Pärast Push () meetodi kutsumist loob net / http pakett HTTP-serverites pseudo HTTP-päringuid. funktsiooni handlerImage () kutsutakse pseudopäringuga. Ressursside edastamiseks ei pea te lisakoodi rakendama. net / http kasutab serveri tõukamiseks olemasolevaid käitleja funktsioone.

Kas soovite tuvastada pseudopäringu? Saate seda teha, kontrollides r.Header.Get ('User-Agent'). Pseudopäringutes on ainult RFC-i nõutav hostpäis. Ma pole kunagi näinud ühtegi kasutajaagenti, kes ei saada kasutajaagendi päist. Tavalise HTTP-päringuga saate erinevat sisu edasi lükata, isegi kui see tähendab vähem.

Mure jõudluse pärast

Näete serveri tõuke parendamist brauserite arendajariistade kaudu. Chrome näitab võrgu üksikasjalikku aruannet.

Järgmine ekraanipilt on HTTP / 1.1 tulemus:

See on HTTP / 2 tulemus:

Mul on esinemise pärast üks potentsiaalne mure. Esimene on ajastus, mida tõukejõud tegelikult teeb. Proovisin kontrollida Golangi rakenduse käitumist ja teatasin, et:

  • Serveri surumine toimub pärast funktsiooni handlerHtml () lõpuleviimist.
  • Isegi kui kasutatakse tükeldatud vastust (http.Flusher), toimub surumine seansi sulgemisel.

Kui HTML-failid genereeritakse koos RDB sisuga ja see võtab nii kaua aega, oleks serveri tõuke kasutamise täiuslik ajastus. Kuid praeguse juurutamisega ei saa ma seda teha.

Vika?

Proovisin kasutada meetodi Push () teist parameetrit, kuid minu lisatud päiseid eirati (nagu Cache-Control). Ainult päised, mis on lisatud rakendusse handlerImage (), töötavad ühiselt. Ma kontrollin net / http-koodi pärast tex tagastamise esitamist.