目录
  • 基础api演示
  • 高性能api演示
  • 测试服务
  • golang单元测试
  • 测试报告

原计划学完golang语言http客户端实践之后,就可以继续了,没想到才疏学浅,在搜资料的时候发现除了golang sdk自带的net/http,还有一个更牛的httpclient实现github.com/valyala/fasthttp,据说性能是net/http的10倍,我想可能是有点夸张了,后期我会进行测试,以正视听。

在github.com/valyala/fasthttp用到了对象池,为了在高性能测试中减少内存的使用,fasthttp使用了两个对象池(我只看了这俩):requestpool sync.pool和responsepool sync.pool,当然fasthttp也提供了正常的对象创建api,后面我在案例中也会写到。

基础api演示

首先分享一下基础的用法封装:

ps:这个属于练习版本,所以没写多少注释。

package ft

import (
 "encoding/json"
 "fmt"
 "funtester/task"
 "github.com/valyala/fasthttp"
)


func fastget(url string, args map[string]interface{}) ([]byte, error) {
 uri := url + "?" + task.tovalues(args)
 _, resp, err := fasthttp.get(nil, uri)
 if err != nil {
  fmt.println("请求失败:", err.error())
  return nil, err
 }
 return resp, err
}

func fastpostform(url string, args map[string]interface{}) ([]byte, error) {

 // 填充表单,类似于net/url
 params := &fasthttp.args{}
 for s, i2 := range args {
  sprintf := fmt.sprintf("%v", i2)
  params.add(s, sprintf)
 }
 _, resp, err := fasthttp.post(nil, url, params)
 if err != nil {
  fmt.println("请求失败:", err.error())
  return nil, err
 }
 return resp, nil
}

func fastpostjson(url string, args map[string]interface{}) ([]byte, error) {

 req := &fasthttp.request{}
 req.setrequesturi(url)

 marshal, _ := json.marshal(args)
 req.setbody(marshal)

 // 默认是application/x-www-form-urlencoded,其实无所谓
 req.header.setcontenttype("application/json")
 req.header.setmethod("post")

 resp := &fasthttp.response{}
 if err := fasthttp.do(req, resp); err != nil {
  fmt.println("请求失败:", err.error())
  return nil, err
 }
 return resp.body(), nil
}

其中两点主要注意:

  • fastget、fastpostform使用的fasthttp提供的默认获取请求的方式,fastpostjson使用了自定义请求和获取响应的方式
  • 关于请求头中的req.header.setcontenttype方法,其实无所谓,服务端都可以解析

高性能api演示

下面分享使用更高的性能(基于对象池)的api创建请求和获取响应的方式:

package task

import (
 "crypto/tls"
 "encoding/json"
 "fmt"
 "github.com/valyala/fasthttp"
 "log"
 "time"
)

var fastclient fasthttp.client = fastclient()

// fastget 获取get请求对象,没有进行资源回收
// @description:
// @param url
// @param args
// @return *fasthttp.request
func fastget(url string, args map[string]interface{}) *fasthttp.request {
 req := fasthttp.acquirerequest()
 req.header.setmethod("get")
 values := tovalues(args)
 req.setrequesturi(url + "?" + values)
 return req
}

// fastpostjson post请求json参数,没有进行资源回收
// @description:
// @param url
// @param args
// @return *fasthttp.request
func fastpostjson(url string, args map[string]interface{}) *fasthttp.request {
 req := fasthttp.acquirerequest()
 // 默认是application/x-www-form-urlencoded
 req.header.setcontenttype("application/json")
 req.header.setmethod("post")
 req.setrequesturi(url)
 marshal, _ := json.marshal(args)
 req.setbody(marshal)
 return req
}

// fastpostform post请求表单传参,没有进行资源回收
// @description:
// @param url
// @param args
// @return *fasthttp.request
func fastpostform(url string, args map[string]interface{}) *fasthttp.request {
 req := fasthttp.acquirerequest()
 // 默认是application/x-www-form-urlencoded
 //req.header.setcontenttype("application/json")
 req.header.setmethod("post")
 req.setrequesturi(url)
 marshal, _ := json.marshal(args)
 req.bodywriter().write([]byte(tovalues(args)))
 req.bodywriter().write(marshal)
 return req
}

// fastresponse 获取响应,保证资源回收
// @description:
// @param request
// @return []byte
// @return error
func fastresponse(request *fasthttp.request) ([]byte, error) {
 response := fasthttp.acquireresponse()
 defer fasthttp.releaseresponse(response)
 defer fasthttp.releaserequest(request)
 if err := fastclient.do(request, response); err != nil {
  log.println("响应出错了")
  return nil, err
 }
 return response.body(), nil
}

// doget 发送get请求,获取响应
// @description:
// @param url
// @param args
// @return []byte
// @return error
func doget(url string, args map[string]interface{}) ([]byte, error) {
 req := fasthttp.acquirerequest()
 defer fasthttp.releaserequest(req) // 用完需要释放资源
 req.header.setmethod("get")
 values := tovalues(args)
 req.setrequesturi(url + "?" + values)
 resp := fasthttp.acquireresponse()
 defer fasthttp.releaseresponse(resp) // 用完需要释放资源
 if err := fastclient.do(req, resp); err != nil {
  fmt.println("请求失败:", err.error())
  return nil, err
 }
 return resp.body(), nil
}

// fastclient 获取fast客户端
// @description:
// @return fasthttp.client
func fastclient() fasthttp.client {
 return fasthttp.client{
  name:                     "funtester",
  nodefaultuseragentheader: true,
  tlsconfig:                &tls.config{insecureskipverify: true},
  maxconnsperhost:          2000,
  maxidleconnduration:      5 * time.second,
  maxconnduration:          5 * time.second,
  readtimeout:              5 * time.second,
  writetimeout:             5 * time.second,
  maxconnwaittimeout:       5 * time.second,
 }
}

测试服务

用的还是moco_funtester测试框架,脚本如下:

package com.mocofun.moco.main

import com.funtester.utils.argsutil
import com.mocofun.moco.mocoserver
import org.apache.tools.ant.taskdefs.condition.and

class share extends mocoserver {

    static void main(string[] args) {
        def util = new argsutil(args)
        //                def server = getservernolog(util.getintordefault(0,12345))
        def server = getserver(util.getintordefault(0, 12345))
        server.get(both(urlstartswith("/test"),existargs("code"))).response("get请求")
        server.post(both(urlstartswith("/test"), existform("fun"))).response("post请求form表单")
        server.post(both(urlstartswith("/test"), existparams("fun"))).response("post请求json表单")
        server.get(urlstartswith("/qps")).response(qps(textres("恭喜到达qps!"), 1))
//        server.response(delay(jsonres(getjson("have=fun ~ tester !")), 1000))
        server.response("have fun ~ tester !")
        def run = run(server)
        waitforkey("fan")
        run.stop()
    }
}

golang单元测试

第一次写golang单测,有点不适应,搞了很久才通。

package test

import (
 "funtester/ft"
 "funtester/task"
 "log"
 "testing"
)

const url = "http://localhost:12345/test"

func args() map[string]interface{} {
 return map[string]interface{}{
  "code": 32,
  "fun":  32,
  "msg":  "324",
 }
}

func testget(t *testing.t) {
 get := task.fastget(url, args())
 res, err := task.fastresponse(get)
 if err != nil {
  t.fail()
 }
 v := string(res)
 log.println(v)
 if v != "get请求" {
  t.fail()
 }
}

func testpostjson(t *testing.t) {
 post := task.fastpostjson(url, args())
 res, err := task.fastresponse(post)
 if err != nil {
  t.fail()
 }
 v := string(res)
 log.println(v)
 if v != "post请求json表单" {
  t.fail()
 }
}

func testpostform(t *testing.t) {
 post := task.fastpostform(url, args())
 res, err := task.fastresponse(post)
 if err != nil {
  t.fail()
 }
 v := string(res)
 log.println(v)
 if v != "post请求form表单" {
  t.fail()
 }
}

func testgetnor(t *testing.t) {
 res, err := ft.fastget(url, args())
 if err != nil {
  t.fail()
 }
 v := string(res)
 log.println(v)
 if v != "get请求" {
  t.fail()
 }
}

func testpostjsonnor(t *testing.t) {
 res, err := ft.fastpostjson(url, args())
 if err != nil {
  t.fail()
 }
 v := string(res)
 log.println(v)
 if v != "post请求json表单" {
  t.fail()
 }
}

func testpostformnor(t *testing.t) {
 res, err := ft.fastpostform(url, args())
 if err != nil {
  t.fail()
 }
 v := string(res)
 log.println(v)
 if v != "post请求form表单" {
  t.fail()
 }
}

测试报告

用的自带的控制台输出内容:

=== run   testget
2021/10/18 18:56:49 get请求
— pass: testget (0.01s)
=== run   testpostjson
2021/10/18 18:56:49 post请求json表单
— pass: testpostjson (0.00s)
=== run   testpostform
2021/10/18 18:56:49 post请求form表单
— pass: testpostform (0.00s)
=== run   testgetnor
2021/10/18 18:56:49 get请求
— pass: testgetnor (0.00s)
=== run   testpostjsonnor
2021/10/18 18:56:49 post请求json表单
— pass: testpostjsonnor (0.00s)
=== run   testpostformnor
2021/10/18 18:56:49 post请求form表单
— pass: testpostformnor (0.00s)
=== run   teststagejson

到此这篇关于golang请求fasthttp实践的文章就介绍到这了,更多相关golang请求fasthttp内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!