Skip to content

Latest commit

 

History

History
173 lines (145 loc) · 6.2 KB

README.md

File metadata and controls

173 lines (145 loc) · 6.2 KB

fastrest

Go Reference

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

fastrest与常说的“框架”的区别

  • fastrest是一些辅助性质的函数/结构的集合。
  • fastrest不造重复的轮子。
  • fastrest力求足够的简单、开放。

目录

结构体/方法作用说明
restserver/httpserverhttp服务组件一套http服务的辅助组件,需要组合httpmultiplexer一起使用
restserver/httpserver/stdmiddlewareshttp中间件一个http的缓存中间件,支持简单的常见的缓存控制策略
restclient/httpclienthttp客户端组件一套http客户端的辅助组件
restcacheCaching单个数据的缓存中间件缓存流程的胶水逻辑。
基于SentinelGroup解决缓存实效风暴问题。
简单介绍见这里
MCaching批量数据的缓存中间件
restcache/lrucacheLRUCacheLRU缓存存储实现了restcache的缓存存储接口。
基于LRUMap实现。
resterror错误处理
restutils常用工具函数

示例

restserver/httpserver:启动一个HTTP Server

s := NewServer(ctx, &http.Server{
    Addr: "127.0.0.1:28080",
    Handler: ...,
})
addr, err := s.Start(ctx) //  启动监听,开始服务。直至收到SIGTERM、SIGINT信号,或Stop被调用。
fmt.Println("Listen running at:", addr)

s.Stop(ctx) // 结束监听。实际环境应该是内部接收退出信号

<-s.ShutdownNotify()
fmt.Println("Exiting...")
err = s.Wait(ctx) // 等待处理完
fmt.Println("Exited")

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 = NewGenericsHandler((func(ctx context.Context, req *Request) (*Response, error) {
    // do things

    // output json body
    return &Response{
        Echo: req.Greeting,
    }, nil
}))

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

restclient/httpclient: 客户端Get请求

type Request struct {
    Greeting string `schema:"greeting"`
}
type Response struct {
    Echo string `json:"echo"`
}

request := Request{Greeting: "Hi"}
response := Response{}
_ = Get(context.TODO(), &response, s.URL+"/path", request)

restclient/httpclient: 客户端PostJson请求

type Request struct {
    Greeting string `json:"greeting"`
}
type Response struct {
    Echo string `json:"echo"`
}

request := Request{Greeting: "Hi"}
response := Response{}
_ = PostJson(context.TODO(), &response, s.URL+"/path", 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]
}