module
0.0.0-20231129005948-e2a80a656c5c
Repository: https://github.com/wencan/fastrest.git
Documentation: pkg.go.dev
# README
fastrest
Go语言RESTful服务通用组件库
Restful服务公共组件库,目的为帮忙快速开发服务程序,尽可能省去与业务无关的重复代码。
可以只使用个别组件,也可以组合起来当“框架”用。
fastrest与常说的“框架”的区别
- fastrest是一些辅助性质的函数/结构的集合。
- fastrest不造重复的轮子。
- fastrest力求足够的简单、开放。
目录
包 | 结构体/方法 | 作用 | 说明 |
---|---|---|---|
restserver/httpserver | http服务组件 | 一套http服务的辅助组件,需要组合http、multiplexer一起使用 | |
restserver/httpserver/stdmiddlewares | http中间件 | 一个http的缓存中间件,支持简单的常见的缓存控制策略 | |
restclient/httpclient | http客户端组件 | 一套http客户端的辅助组件 | |
restcache | Caching | 单个数据的缓存中间件 | 缓存流程的胶水逻辑。 基于SentinelGroup解决缓存实效风暴问题。 简单介绍见这里。 |
MCaching | 批量数据的缓存中间件 | ||
restcache/lrucache | LRUCache | LRU缓存存储 | 实现了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]
}
# Packages
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author