使用 sync.Pool 的方式是不是有点怪,主要是 defer 和 api.pool.Put(buffer);buffer = nil 这里解释一下,为了提高 buufer 的复用率会在不使用时尽快把 buffer 放回到缓冲池中,defer 之所以会判断 buffer != nil 主要是在业务逻辑出现错误时,但是 buffer 还没有放回缓冲池时把 buffer 放回到缓冲池,因为在每个错误处理之后都写 api.pool.Put(buffer) 不是一个好的方法,而且容易忘记,但是如果在确定不再使用时 api.pool.Put(buffer);buffer = nil 就可以尽早把 buffer 放回到缓冲池中,提高复用率,减少新建 buffer。
这样就好了吗,别急,之前说服务里面还会构建请求,看看构建请求如何优化吧。
- package adapter
-
- import (
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "sync"
-
- "github.com/json-iterator/go"
- "github.com/sirupsen/logrus"
- "github.com/thinkeridea/go-extend/exbytes"
- )
-
- type Adapter struct {
- pool sync.Pool
- }
-
- func New() *Adapter {
- return &Adapter{
- pool: sync.Pool{
- New: func() interface{} {
- return bytes.NewBuffer(make([]byte, 4096))
- },
- },
- }
- }
-
- func (api *Adapter) Request(r *Request) (*Response, error) {
- var err error
- buffer := api.pool.Get().(*bytes.Buffer)
- buffer.Reset()
- defer func() {
- if buffer != nil {
- api.pool.Put(buffer)
- buffer = nil
- }
- }()
-
- e := jsoniter.NewEncoder(buffer)
- err = e.Encode(r)
- if err != nil {
- logrus.WithFields(logrus.Fields{
- "request": r,
- }).Errorf("jsoniter.Marshal failure: %v", err)
- return nil, fmt.Errorf("jsoniter.Marshal failure: %v", err)
- }
-
- data := buffer.Bytes()
- req, err := http.NewRequest("POST", "http://xxx.com", buffer)
- if err != nil {
- logrus.WithFields(logrus.Fields{
- "data": exbytes.ToString(data),
- }).Errorf("http.NewRequest failed: %v", err)
- return nil, fmt.Errorf("http.NewRequest failed: %v", err)
- }
-
- req.Header.Set("User-Agent", "xxx")
-
- httpResponse, err := http.DefaultClient.Do(req)
- if httpResponse != nil {
- defer func() {
- io.Copy(ioutil.Discard, httpResponse.Body)
- httpResponse.Body.Close()
- }()
- }
-
- if err != nil {
- logrus.WithFields(logrus.Fields{
- "url": "http://xxx.com",
- }).Errorf("query service failed %v", err)
- return nil, fmt.Errorf("query service failed %v", err)
- }
-
- if httpResponse.StatusCode != 200 {
- logrus.WithFields(logrus.Fields{
- "url": "http://xxx.com",
- "status": httpResponse.Status,
- "status_code": httpResponse.StatusCode,
- }).Errorf("invalid http status code")
- return nil, fmt.Errorf("invalid http status code")
- }
-
- buffer.Reset()
- _, err = io.Copy(buffer, httpResponse.Body)
- if err != nil {
- return nil, fmt.Errorf("adapter io.copy failure error:%v", err)
- }
-
- respData := buffer.Bytes()
- logrus.WithFields(logrus.Fields{
- "response_json": exbytes.ToString(respData),
- }).Debug("response json")
-
- res := &Response{}
- err = jsoniter.Unmarshal(respData, res)
- if err != nil {
- logrus.WithFields(logrus.Fields{
- "data": exbytes.ToString(respData),
- "url": "http://xxx.com",
- }).Errorf("adapter jsoniter.Unmarshal failed, error:%v", err)
- return nil, fmt.Errorf("adapter jsoniter.Unmarshal failed, error:%v", err)
- }
-
- api.pool.Put(buffer)
- buffer = nil
-
- // ...
- return res, nil
- }
(编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|