欢迎关注「全栈工程师修炼指南」公众号
设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习!
专注 企业运维实践、网络安全、系统运维、应用开发、物联网实战、全栈文章 等知识分享
“ 花开堪折直须折,莫待无花空折枝。 ”
作者主页:[ https://www.weiyigeek.top ]
博客:[ https://blog.weiyigeek.top ]
作者<安全开发运维>答疑交流群,回复【学习交流群】即可加入
文章目录:
-
Golang 优雅的计算接口耗时
-
Golang 优雅的接口限流思路
-
Golang 优雅的接口超时控制
Golang 优雅的计算接口耗时
描述: Goglang 接口耗时监控测试用例
核心:使用 defer + 匿名函数 再加上 time.Since() 函数实现再程序结束完毕时计算此代码片段(接口)执行耗时
示例:
package main
import (
"fmt"
"time"
)
/**
Goglang 接口耗时监控测试用例
核心:使用 defer + 匿名函数 再加上 time.Since() 函数实现再程序结束完毕时计算此代码片段(接口)执行耗时
**/
// 模拟接口耗时计算处理
func timeConsumingInterface(a, b int) string {
t0 := time.Now()
// 此处需要注意 defer 的特性
// 错误做法,它会在声明时便会将变量进行执行,所以在输出时使用时间为 0ms, 这显示我们想看到的。
// defer fmt.Printf("Use Time %d ms\n", time.Since(t0).Millisecond())
// 正确做法,将输出函数放在匿名函数中,函数里的相关变量计算将会在程序结束时执行,就可以达到我们想要的结果了。
defer func() {
fmt.Printf("Use Time %d ms\n", time.Since(t0).Milliseconds())
}()
if a > b {
// 模拟程序耗时
time.Sleep(100 * time.Millisecond)
return "ok, a > b"
} else {
// 模拟程序耗时
time.Sleep(200 * time.Millisecond)
return "ok, a < b"
}
}
func main() {
// 模拟一百并发调用
timeConsumingInterface(5, 6)
time.Sleep(3 * time.Second)
}
执行结果:
$ go run .\main.go
Use Time 207 ms
Golang 优雅的接口限流思路
描述: Goglang 接口限流测试用例,此处以模拟数据库访问函数 readDB()
为例。
核心:利用make申请一个带容量的管道来实现。
示例:
package main
import (
"encoding/json"
"fmt"
"sync/atomic"
"time"
)
/**
Goglang 接口限流测试用例,此处以模拟数据库访问函数 readDB() 为例。
核心:利用make申请一个带容量的管道来实现。
**/
type Res struct {
Username string `json:"username"`
Status string `josn:"status"`
}
var (
countnum int32
countnum_limit = make(chan struct{}, 10) // 开辟容量为10的管道
)
// 模拟,数据库SQL请求查询
func readDB() string {
atomic.AddInt32(&countnum, 1) // 原子操作+1
defer atomic.AddInt32(&countnum, -1) // 原子操作-1,defer 在退出时执行
fmt.Printf("ReadDB 函数调用并发 %d\n", atomic.LoadInt32(&countnum))
time.Sleep(200 * time.Millisecond) // 200 毫秒
var res = &Res{Username: "WeiyiGeek", Status: "ok"}
value, err := json.Marshal(res)
if err != nil {
fmt.Println(err)
}
return string(value) // {"username":"WeiyiGeek","status":"ok"}
}
// 模拟接口限流处理
func flowControlInterface() {
countnum_limit <- struct{}{}
readDB()
// 读取完毕后取出管道数据,防止达到10之后阻塞。
<-countnum_limit
}
func main() {
// 模拟一百并发调用
for i := 0; i < 100; i++ {
go flowControlInterface()
}
time.Sleep(3 * time.Second)
}
执行结果:
$ go run ./main.go
ReadDB 函数调用并发 1
ReadDB 函数调用并发 2
ReadDB 函数调用并发 3
ReadDB 函数调用并发 4
ReadDB 函数调用并发 5
ReadDB 函数调用并发 6
ReadDB 函数调用并发 7
ReadDB 函数调用并发 8
ReadDB 函数调用并发 9
ReadDB 函数调用并发 10
ReadDB 函数调用并发 10
.....
ReadDB 函数调用并发 10
ReadDB 函数调用并发 10
ReadDB 函数调用并发 10
ReadDB 函数调用并发 9
ReadDB 函数调用并发 10
ReadDB 函数调用并发 9
亲,文章就要看完了,不关注一下【全栈工程师修炼指南】吗?
Golang 优雅的接口超时控制
描述: Goglang 接口超时控制测试用例
核心:使用管道chan 加上 select 多路复用,实现数据库查询接口的超时处理。
示例:
package main
import (
"net/http"
"time"
)
/**
Goglang 接口超时控制测试用例
核心:使用管道chan 加上 select 多路复用,实现数据库查询接口的超时处理。
**/
// 模拟数据库访问函数
func readDB() string {
time.Sleep(200 * time.Millisecond)
return "{\"name\":\"weiyigeek\",\"公众号\":\"全栈工程师修炼指南\"}"
}
// 模拟接口超时示例
func timeoutInterface(w http.ResponseWriter, req *http.Request) {
var resp string
// 创建一个chan管道
ch := make(chan struct{}, 1)
// 创建一个协程来调用数据库访问函数
go func() {
resp = readDB()
// 向管道写入一个空结构体
ch <- struct{}{}
}()
// 使用 select 多路复用来实现一个超时控制
select {
// 当数据库调用完毕则执行取出
case <-ch:
// 假如此300毫秒先到了,而readDB()还没有执行完毕则返回超时信息。
// 300ms => 此实践中并不会触发超时,这是由于我们模拟的数据库读取还是比较简单的。
// 此处使用 100s 来验证超时
case <-time.After(100 * time.Millisecond):
resp = "{\"err\":\"数据库读取超时.\"}"
}
w.Write([]byte(resp))
}
func main() {
http.HandleFunc("/", timeoutInterface)
http.ListenAndServe("127.0.0.1:5678", nil)
}
执行结果:
本文至此完毕,更多技术文章,尽情等待下篇好文!
原文地址: https://blog.weiyigeek.top
如果此篇文章对你有帮助,请你将它分享给更多的人!
学习书籍推荐 往期发布文章
公众号回复【0008】获取【Ubuntu22.04安装与加固脚本】
公众号回复【10001】获取【WinServer安全加固脚本】
公众号回复【10002】获取【KylinOS银河麒麟安全加固脚本】
公众号回复【0011】获取【k8S二进制安装部署教程】
公众号回复【0014】获取【Nginx学习之路汇总】
公众号回复【0015】获取【Jenkins学习之路汇总】
热文推荐
欢迎长按(扫描)二维码 ,获取更多渠道哟!
欢迎关注 【全栈工程师修炼指南】(^U^)ノ~YO
添加作者微信【weiyigeeker】,拉你一起学习交流吧!
关注回复【学习交流群】即可加入【安全开发运维沟通交流群】
温馨提示: 由于作者水平有限,本章错漏缺点在所难免,希望读者批评指正,若有问题或建议请在文章末尾留下您宝贵的经验知识,或联系邮箱地址 master@weiyigeek.top 或 关注公众号 [全栈工程师修炼指南] 留言。
万水千山总是情,点个【赞 + 在看】吧!
点击【"阅读原文"】获取更多有趣的知识!