当前位置:首页 > 文章列表 > Golang > Go教程 > Golang请求fasthttp实践

Golang请求fasthttp实践

来源:脚本之家 2023-01-08 11:26:29 0浏览 收藏

本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《Golang请求fasthttp实践》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~

原计划学完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学习网公众号,带你了解更多关于golang的知识点!

版本声明
本文转载于:脚本之家 如有侵犯,请联系study_golang@163.com删除
Go语言HTTPServer开发的六种方式小结Go语言HTTPServer开发的六种方式小结
上一篇
Go语言HTTPServer开发的六种方式小结
详解Golang语言HTTP客户端实践
下一篇
详解Golang语言HTTP客户端实践
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 笔灵AI生成答辩PPT:高效制作学术与职场PPT的利器
    笔灵AI生成答辩PPT
    探索笔灵AI生成答辩PPT的强大功能,快速制作高质量答辩PPT。精准内容提取、多样模板匹配、数据可视化、配套自述稿生成,让您的学术和职场展示更加专业与高效。
    14次使用
  • 知网AIGC检测服务系统:精准识别学术文本中的AI生成内容
    知网AIGC检测服务系统
    知网AIGC检测服务系统,专注于检测学术文本中的疑似AI生成内容。依托知网海量高质量文献资源,结合先进的“知识增强AIGC检测技术”,系统能够从语言模式和语义逻辑两方面精准识别AI生成内容,适用于学术研究、教育和企业领域,确保文本的真实性和原创性。
    22次使用
  • AIGC检测服务:AIbiye助力确保论文原创性
    AIGC检测-Aibiye
    AIbiye官网推出的AIGC检测服务,专注于检测ChatGPT、Gemini、Claude等AIGC工具生成的文本,帮助用户确保论文的原创性和学术规范。支持txt和doc(x)格式,检测范围为论文正文,提供高准确性和便捷的用户体验。
    30次使用
  • 易笔AI论文平台:快速生成高质量学术论文的利器
    易笔AI论文
    易笔AI论文平台提供自动写作、格式校对、查重检测等功能,支持多种学术领域的论文生成。价格优惠,界面友好,操作简便,适用于学术研究者、学生及论文辅导机构。
    40次使用
  • 笔启AI论文写作平台:多类型论文生成与多语言支持
    笔启AI论文写作平台
    笔启AI论文写作平台提供多类型论文生成服务,支持多语言写作,满足学术研究者、学生和职场人士的需求。平台采用AI 4.0版本,确保论文质量和原创性,并提供查重保障和隐私保护。
    35次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码