在项目中一般会请求第三方的接口,也会对外提供接口,可能是RPC,也可能是HTTP等方式。在对外提供接口时,有必要提供相应的批量接口,好的批量实现能够提升性能。
在高并场景中,调用批量接口相比调用非批量接口有更大的性能优势。
比如获取商品详情接口,app的一次请求是个单接口调用,用户很少情况下是没问题。
如果有大量用户查询详情,这个接口频繁调用,在这一时刻高频获取数据库等资源或者多次存在查询重复详情将浪费服务器性能。
怎样能优化这个接口呢?
我们可以获取这一时刻的全部请求,请求资源进行去重和将请求不同的详情进行批量获取资源,来做分批分发响应
学习前需要了解:goroutine和channel这些基础。
package main
import (
"fmt"
"log"
"net/http"
"strconv"
"time"
)
type Msg struct {
key string
content string
}
type Context struct {
R *http.Request
W http.ResponseWriter
out chan<- Msg
}
var requests[] Context
func IndexHandler(w http.ResponseWriter,r *http.Request) {
var re Context
re.R=r
re.W=w
//申请管道,等待业务数据结果
cha :=make(chan Msg, 0)
re.out=cha
requests = append(requests,re)
//等待业务数据
msg:= <-cha
fmt.Fprint(w,msg.key +"_"+msg.content)
}
/**
批量处理请求
*/
func batchHandle( s[] Context ){
size :=len(s)
for i:=0;i<size;i++{
//fmt.Println(s[i].R.URL)
var msg Msg
msg.content="请求成功"
msg.key ="i:"+strconv.Itoa(i)
//将处理好的数据请求,写入对应管道
s[i].out<-msg
}
}
/**
收集两秒内接口请求,进行合并请求,批量处理数据,然后分发数据
*/
func task(){
tiker := time.NewTicker(time.Second*2)
for{
/**开启定时,将收集的请求,放置在新容器中**/
<-tiker.C
var r[] Context =requests
var rNew[] Context
//清空旧容器数据
requests= rNew
batchHandle(r)
}
}
func main() {
http.HandleFunc("/",IndexHandler)
go task()
log.Println(http.ListenAndServe(":8080",nil))
}