+3

[Go] Tìm hiểu về keep-alive trong http

  • keep-alive cơ bản là giữ kết nối giữa client và server.

Lợi ích

  • Giảm kết nối TCP giữa client và server, mỗi client chỉ có duy nhất một kết nối.
  • Giảm độ trễ – Việc giảm số lần bắt tay ba bước có thể giúp cải thiện độ trễ của trang web. Điều này đặc biệt đúng với các kết nối SSL/TLS, vốn yêu cầu các chuyến đi khứ hồi bổ sung để mã hóa và xác minh các kết nối.

Code mẫu client và server

Ví dụ 1

Server

package main
import (
	"fmt"
	"net/http"
)
func Index(w http.ResponseWriter, r *http.Request) {
	fmt.Println("receive a request from:", r.RemoteAddr, r.Header)
	w.Write([]byte("ok"))
}
func main() {
	fmt.Println("server keep alive")
	var s = http.Server{
		Addr:    ":8080",
		Handler: http.HandlerFunc(Index),
	}
	s.ListenAndServe()
}

Client

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
)

func main() {
	fmt.Println("client keep alive")

	c := &http.Client{}
	req, err := http.NewRequest("Get", "http://localhost:8080", nil)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%#v\n", *req)

	for i := 0; i < 3; i++ {
		resp, err := c.Do(req)
		if err != nil {
			fmt.Println("http get error:", err)
			return
		}
		defer resp.Body.Close()

		b, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("read body error:", err)
			return
		}
		fmt.Println("response body:", string(b))
		time.Sleep(time.Second)
	}
}

Kết Quả

  • Server:
server keep alive
receive a request from: [::1]:51328 map[Accept-Encoding:[gzip] User-Agent:[Go-http-client/1.1]]
receive a request from: [::1]:51328 map[Accept-Encoding:[gzip] User-Agent:[Go-http-client/1.1]]
receive a request from: [::1]:51328 map[Accept-Encoding:[gzip] User-Agent:[Go-http-client/1.1]]
  • Client:
client keep alive
http.Request{Method:"Get", URL:(*url.URL)(0x1400017a000), Proto:"HTTP/1.1", ProtoMajor:1, ProtoMinor:1, Header:http.Header{}, Body:io.ReadCloser(nil), GetBody:(func() (io.ReadCloser, error))(nil), ContentLength:0, TransferEncoding:[]string(nil), Close:false, Host:"localhost:8080", Form:url.Values(nil), PostForm:url.Values(nil), MultipartForm:(*multipart.Form)(nil), Trailer:http.Header(nil), RemoteAddr:"", RequestURI:"", TLS:(*tls.ConnectionState)(nil), Cancel:(<-chan struct {})(nil), Response:(*http.Response)(nil), ctx:(*context.emptyCtx)(0x1400012e008)}
response body: ok
response body: ok
response body: ok
  • Có thể thấy, Client đã gọi 3 request và điều chung 1 id 51328, đồng nghĩa là đã được reuse connection

Ví dụ 2:

Client

  • Trong phần tạo ra client, cấu hình disable keep alive:
c := &http.Client{
		Transport: &http.Transport{
			DisableKeepAlives: true,
		},
	}

Kết Quả

  • Server:
server keep alive
receive a request from: [::1]:51869 map[Accept-Encoding:[gzip] Connection:[close] User-Agent:[Go-http-client/1.1]]
receive a request from: [::1]:51872 map[Accept-Encoding:[gzip] Connection:[close] User-Agent:[Go-http-client/1.1]]
receive a request from: [::1]:51881 map[Accept-Encoding:[gzip] Connection:[close] User-Agent:[Go-http-client/1.1]]
  • Client: kêt quả không có gì thay đổi.
  • Bây giờ có thể thấy log ở server, mỗi request sẽ có 1 id (51869,51872,51881) khác nhau, đồng nghĩa là connect không được dùng lại.

Ví dụ 3

  • Bây giờ việc config keep-alive sẽ do server quyết định Server
func main() {
	fmt.Println("server keep alive")
	var s = http.Server{
		Addr:    ":8080",
		Handler: http.HandlerFunc(Index),
	}
	s.SetKeepAlivesEnabled(false)
	s.ListenAndServe()
}

Client : không có gì thay đổi.

Kết quả

  • Server:
server keep alive
receive a request from: [::1]:52987 map[Accept-Encoding:[gzip] User-Agent:[Go-http-client/1.1]]
receive a request from: [::1]:52991 map[Accept-Encoding:[gzip] User-Agent:[Go-http-client/1.1]]
receive a request from: [::1]:52994 map[Accept-Encoding:[gzip] User-Agent:[Go-http-client/1.1]]
  • Client: không có gì thay đổi
  • Kết luận là cũng không reuse connection.

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí