golang http连接复用

server端

golang httpserver 默认开启keepalive连接复用选项

handler函数需要完整读body数据,构造返回消息,否则当数据不能一次发送完成时,连接复用就会失效。

示例如下

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

func connHandler(w http.ResponseWriter, r *http.Request) {
	// parse
	r.ParseForm()
	response_time := r.Header.Get("sleep-time")
	// <= NOTE
	if _, err := ioutil.ReadAll(r.Body); err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	defer r.Body.Close()
	// sleep for some time
	resp_time := 1
	if response_time != "" {
		ms, _ := strconv.ParseFloat(response_time, 64)
		resp_time = (int)(ms * 1000)
	}
	time.Sleep(time.Duration(resp_time) * time.Millisecond)
	// parepare response
	status := 200
	body := ""
	w.Header().Set("Content-Type", "text/plain")
	w.Header().Set("Content-Length", strconv.Itoa(len(body)))
	w.WriteHeader(status)
	w.Write([]byte(body))
}

func main() {
	http.HandleFunc("/", connHandler)
	if err := http.ListenAndServe(":server_port", nil); err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

client 端

客户端需要构建全局client,完整读 response body,并关闭body

package main

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

var (
    httpClient *http.Client
)

const (
    MaxIdleConnections int = 20
    RequestTimeout     int = 30
)

// init HTTPClient
func init() {
    httpClient = createHTTPClient()
}

// createHTTPClient for connection re-use
func createHTTPClient() *http.Client {
    client := &http.Client{
    	Transport: &http.Transport{
            MaxIdle    ConnsPerHost: MaxIdleConnections,
	},
	Timeout: time.Duration(RequestTimeout) * time.Second,
    }
    return client
}

func conn_reuse_post(conn_reuse_times int) {
    var endPoint string = "http://server_ip:server_port/"
    data := []byte{}
    // fill data 
    for i := 0; i < conn_reuse_times; i++ {
	// use global httpClient to send request
	resp, err := httpClient.Post(endPoint, "application/x-www-form-urlencoded", bytes.NewBuffer([]byte(data)))
	fmt.Println(resp)
	if err != nil {
	    log.Println("err", err)
	    return
	}
	io.Copy(ioutil.Discard, resp.Body) // <= NOTE
	resp.Body.Close()    // <= NOTE
    }
}

func main() {
    conn_reuse_post(5)
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值