Go语言RESTful服务通用组件
Restful服务公共组件库,目的为帮忙快速开发服务程序,尽可能省去与业务无关的重复代码。
可以只使用个别组件,也可以组合起来当框架用。
包 | 结构体/方法 | 作用 | 说明 |
---|---|---|---|
restserver/httpserver | http服务组件 | 一套创建Handler、解析请求、输出响应的辅助函数,需要组合http、multiplexer一起使用 | |
restserver/httpserver/stdmiddlewares | http中间件 | 一个http的缓存中间件,支持简单的常见的缓存控制策略 | |
restcache | Caching | 单个数据的缓存中间件 | 缓存流程的胶水逻辑。 基于SentinelGroup解决缓存实效风暴问题。 简单介绍见这里。 |
MCaching | 批量数据的缓存中间件 | ||
restcache/lrucache | LRUCache | LRU缓存存储 | 实现了restcache的缓存存储接口。 基于LRUMap实现。 |
type Request struct {
Greeting string `schema:"greeting" json:"greeting" validate:"required"`
}
type Response struct {
Echo string `json:"echo"`
}
var handler http.HandlerFunc = NewHandler(func(r *http.Request) (response interface{}, err error) {
var req Request
// parse and validate query
err = ReadValidateRequest(r.Context(), &req, r)
if err != nil {
return nil, err
}
// do things
// output json body
return Response{
Echo: req.Greeting,
}, nil
})
或者:
type Request struct {
Greeting string `schema:"greeting" json:"greeting" validate:"required"`
}
type Response struct {
Echo string `json:"echo"`
}
// NewHandler + NewHandlerFunc 可以将一个gRPC服务方法,转为http.HandlerFunc。
var handler http.HandlerFunc = NewHandler(NewHandlerFunc(func(ctx context.Context, req *Request) (resp *Response, err error) {
// do things
return &Response{
Echo: req.Greeting,
}, nil
}, ReadValidateRequest))
storage := lrucache.NewLRUCache(10000, 10) // 一般也可能是redis客户端
ttlRange := [2]time.Duration{time.Minute * 4, time.Minute * 6}
cacheMiddleware := NewCacheMiddleware(storage, ttlRange, nil)
var handler http.HandlerFunc = cacheMiddleware(func(w http.ResponseWriter, r *http.Request) {
// 缓存未命中,才会执行这里
// ... ...
})
query := func(ctx context.Context, destPtr interface{}, args interface{}) (found bool, err error) {
// 如果Storage没找到,这里提供
// 一般是从持久化数据库、服务接口查询
return true, nil
}
caching := Caching{
Storage: lrucache.NewLRUCache(10000, 10), // 一般是redis实现。透明处理业务数据。
Query: query,
TTLRange: [2]time.Duration{time.Minute * 4, time.Minute * 6},
SentinelTTL: time.Second,
}
var resp Response
var key = "key"
var args = ? // 给query函数的参数
found, err := caching.Get(context.TODO(), &resp, key, args)
query := func(ctx context.Context, destSlicePtr interface{}, argsSlice interface{}) (missIndexes []int, err error) {
// 如果Storage没找到,这里提供
// 一般是从持久化数据库、服务接口查询
// destSlicePtr为接收结果的切片的指针,argsSlice为入参切片
// missIndexes是没查到的下标
return missIndexes, nil
}
mcaching := MCaching{
MStorage: lrucache.NewLRUCache(10000, 10), // 一般是redis实现
MQuery: query,
TTLRange: [2]time.Duration{time.Minute * 4, time.Minute * 6},
SentinelTTL: time.Second,
}
var keys = []string{......}
var args = ...... // 给query函数的参数切片
var resp []*response
missIndexes, err := mcaching.MGet(context.TODO(), &resp, keys, args)
for _, missIndex := range missIndexes {
// not found: keys[missIndex]
}