golang基于NATS构建实时REST服务同步插件库go-res的使用
Golang基于NATS构建实时REST服务同步插件库go-res的使用
概述
go-res是一个Go语言包,用于创建REST、实时和RPC API,通过Resgate无缝同步所有响应式Web客户端。
安装
go get github.com/jirenius/go-res
快速入门示例
package main
import res "github.com/jirenius/go-res"
func main() {
s := res.NewService("example")
s.Handle("model",
res.Access(res.AccessGranted),
res.GetModel(func(r res.ModelRequest) {
r.Model(struct {
Message string `json:"message"`
}{"Hello, World!"})
}),
)
s.ListenAndServe("nats://localhost:4222")
}
前提条件
需要安装NATS Server和Resgate,可以通过以下Docker命令完成:
docker network create res
docker run -d --name nats -p 4222:4222 --net res nats
docker run --name resgate -p 8080:8080 --net res resgateio/resgate --nats nats://nats:4222
完整示例
创建新服务
s := res.NewService("myservice")
添加模型资源处理程序
mymodel := map[string]interface{}{"name": "foo", "value": 42}
s.Handle("mymodel",
res.Access(res.AccessGranted),
res.GetModel(func(r res.ModelRequest) {
r.Model(mymodel)
}),
)
添加集合资源处理程序
mycollection := []string{"first", "second", "third"}
s.Handle("mycollection",
res.Access(res.AccessGranted),
res.GetCollection(func(r res.CollectionRequest) {
r.Collection(mycollection)
}),
)
添加参数化资源处理程序
s.Handle("article.$id",
res.Access(res.AccessGranted),
res.GetModel(func(r res.ModelRequest) {
article := getArticle(r.PathParam("id"))
if article == nil {
r.NotFound()
} else {
r.Model(article)
}
}),
)
添加方法调用处理程序
s.Handle("math",
res.Access(res.AccessGranted),
res.Call("double", func(r res.CallRequest) {
var p struct {
Value int `json:"value"`
}
r.ParseParams(&p)
r.OK(p.Value * 2)
}),
)
发送模型更新变更事件
s.With("myservice.mymodel", func(r res.Resource) {
mymodel["name"] = "bar"
r.ChangeEvent(map[string]interface{}{"name": "bar"})
})
发送集合更新添加事件
s.With("myservice.mycollection", func(r res.Resource) {
mycollection = append(mycollection, "fourth")
r.AddEvent("fourth", len(mycollection)-1)
})
添加认证处理程序
s.Handle("myauth",
res.Auth("login", func(r res.AuthRequest) {
var p struct {
Password string `json:"password"`
}
r.ParseParams(&p)
if p.Password != "mysecret" {
r.InvalidParams("Wrong password")
} else {
r.TokenEvent(map[string]string{"user": "admin"})
r.OK(nil)
}
}),
)
添加访问控制处理程序
s.Handle("mymodel",
res.Access(func(r res.AccessRequest) {
var t struct {
User string `json:"user"`
}
r.ParseToken(&t)
if t.User == "admin" {
r.AccessGranted()
} else {
r.AccessDenied()
}
}),
res.GetModel(func(r res.ModelRequest) {
r.Model(mymodel)
}),
)
使用路由
s.Route("v2", func(m *res.Mux) {
m.Handle("mymodel",
/* ... */
)
})
启动服务
s.ListenAndServe("nats://localhost:4222")
测试
restest子包用于测试服务和验证响应。
服务间通信
resprot子包提供了通过NATS服务器与其他服务通信的低级结构和方法。
存储
store子包包含用于处理数据库存储的处理程序和接口。
贡献
go-res包仍在开发中,但API基本已确定。对包API或其实现的任何反馈都非常感谢!
更多关于golang基于NATS构建实时REST服务同步插件库go-res的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基于NATS构建实时REST服务同步插件库go-res的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用NATS构建实时REST服务:go-res库指南
介绍
go-res是一个基于NATS的实时REST服务同步插件库,它允许开发者轻松构建实时应用程序后端。通过结合NATS的消息传递能力和RESTful接口,go-res提供了高效的实时数据同步解决方案。
核心概念
- 资源(Resource): 应用程序中的基本数据单元
- 模型(Model): 资源的持久化表示
- 集合(Collection): 资源的聚合
安装
首先安装必要的依赖:
go get github.com/nats-io/nats.go
go get github.com/jirenius/go-res
基本使用示例
1. 初始化服务
package main
import (
"log"
"github.com/jirenius/go-res"
"github.com/nats-io/nats.go"
)
func main() {
// 连接到NATS服务器
nc, err := nats.Connect(nats.DefaultURL)
if err != nil {
log.Fatal(err)
}
defer nc.Close()
// 创建res服务
s := res.NewService("example")
s.SetConnection(nc)
// 添加处理程序
s.Handle("model",
res.Access(res.AccessGranted),
res.GetModel(func(r res.ModelRequest) {
r.Model(map[string]interface{}{
"id": "123",
"title": "Example Model",
})
}),
)
// 启动服务
if err := s.Start(); err != nil {
log.Fatal(err)
}
// 保持程序运行
select {}
}
2. 定义资源模型
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func (u *User) ToMap() map[string]interface{} {
return map[string]interface{}{
"id": u.ID,
"name": u.Name,
"email": u.Email,
}
}
func getUserModelHandler(userStore map[string]*User) res.ModelHandlerFunc {
return func(r res.ModelRequest) {
id := r.PathParam("id")
if user, ok := userStore[id]; ok {
r.Model(user.ToMap())
} else {
r.NotFound()
}
}
}
3. 实时集合示例
func setupUserService(s *res.Service, userStore map[string]*User) {
s.Handle("users",
res.Access(res.AccessGranted),
res.GetCollection(func(r res.CollectionRequest) {
users := make([]interface{}, 0, len(userStore))
for _, u := range userStore {
users = append(users, res.Ref("user."+u.ID))
}
r.Collection(users)
}),
)
s.Handle("user.$id",
res.Access(res.AccessGranted),
res.GetModel(getUserModelHandler(userStore)),
res.Call("update", func(r res.CallRequest) {
var params map[string]interface{}
r.ParseParams(¶ms)
id := r.PathParam("id")
if user, ok := userStore[id]; ok {
if name, ok := params["name"].(string); ok {
user.Name = name
}
if email, ok := params["email"].(string); ok {
user.Email = email
}
// 通知所有订阅者变更
s.With("user."+id).Event("change", user.ToMap())
r.OK(nil)
} else {
r.NotFound()
}
}),
)
}
4. 事件订阅
客户端可以通过NATS订阅资源变更事件:
func subscribeToUserChanges(nc *nats.Conn, userID string) {
sub, err := nc.Subscribe("event.user."+userID+".change", func(msg *nats.Msg) {
log.Printf("User changed: %s", string(msg.Data))
})
if err != nil {
log.Fatal(err)
}
defer sub.Unsubscribe()
}
高级特性
1. 访问控制
s.Handle("admin.users",
res.Access(func(r res.AccessRequest) {
if r.AuthToken() == "admin-secret" {
r.AccessGranted()
} else {
r.AccessDenied()
}
}),
// ...其他处理程序
)
2. 查询参数支持
s.Handle("articles",
res.GetCollection(func(r res.CollectionRequest) {
query := r.Query()
author := query.Get("author")
category := query.Get("category")
// 根据查询参数过滤文章
filtered := filterArticles(author, category)
r.Collection(filtered)
}),
)
3. 错误处理
s.Handle("secure.data",
res.GetModel(func(r res.ModelRequest) {
if !isAuthorized(r) {
r.Error(res.ErrUnauthorized)
return
}
// ...处理请求
}),
)
最佳实践
- 资源命名: 使用清晰的命名约定(如
module.entity
) - 事件粒度: 保持事件小而具体
- 批处理: 对频繁更新使用批处理事件
- 监控: 监控NATS和服务指标
总结
go-res结合NATS提供了强大的实时REST服务构建能力。通过资源模型和事件系统,开发者可以轻松实现数据同步和实时更新功能。这种架构特别适合需要低延迟和高并发的应用场景。
要了解更多细节,建议查阅go-res的官方文档和示例代码库。