/fastrest

Go语言RESTful服务通用组件库

Primary LanguageGoBSD 3-Clause "New" or "Revised" LicenseBSD-3-Clause

fastrest

Go Reference

Go语言RESTful服务通用组件
Restful服务公共组件库,目的为帮忙快速开发服务程序,尽可能省去与业务无关的重复代码。
可以只使用个别组件,也可以组合起来当框架用。

目录

结构体/方法作用说明
restserver/httpserverhttp服务组件一套创建Handler、解析请求、输出响应的辅助函数,需要组合httpmultiplexer一起使用
restserver/httpserver/stdmiddlewareshttp中间件一个http的缓存中间件,支持简单的常见的缓存控制策略
restcacheCaching单个数据的缓存中间件缓存流程的胶水逻辑。
基于SentinelGroup解决缓存实效风暴问题。
简单介绍见这里
MCaching批量数据的缓存中间件
restcache/lrucacheLRUCacheLRU缓存存储实现了restcache的缓存存储接口。
基于LRUMap实现。

示例

restserver/httpserver: 创建一个HTTP Handler

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))

fastrest/restserver/httpserver/stdmiddlewares:HTTP缓存中间件

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) {
    // 缓存未命中,才会执行这里
    // ... ...
})

restcache: 单个数据的缓存

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)

restcache: 一批数据的缓存

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]
}