近年来,“微服务”在软件架构出现频次越来越高,其思想主要是指将一个大型的单个应用服务拆分为多个微服务,每个微服务在其自己的进程中运行,并采用轻量级的协议进程通信,通常采用的方法是基于HTTP的RESTful API。本文主要介绍一个RESTful框架的使用方式及其主要实现原理,主要基于Golang和MongoDB实现,协议采用HTTP+JSON,另外搭配ElasticSearch可以实现数据资源的搜索功能。使用者只需要定义好数据资源的结构体,即可快速构建RESTful服务。
https://github.com/jimdn/restful
HTTP方法 | 路径 | URL参数 | HTTP Body | 说明 |
---|---|---|---|---|
POST | /{biz} | - | 新增的数据内容 | 新增一条数据 |
PUT | /{biz}/{id} | - | 新增/覆盖的数据内容 | 新增或覆盖更新一条数据 |
PATCH | /{biz}/{id} | seq | 修改的数据内容 | 部分更新一条数据(需要带上原数据的seq) |
DELETE | /{biz}/{id} | - | - | 删除一条数据 |
GET | /{biz}/{id} | - | - | 查询一条数据 |
GET | /{biz} | page size filter range in nin all search order select | - | 分页查询URL各参数示例: page=1 size=10 filter={"star":5, "city":"shenzhen"} range={"age":{"gt":20, "lt":40}} in={"color":["blue", "red"]} nin={"color":["blue", "red"]} all={"color":["blue", "red"]} search=hello order=["+age", "-time"] select=["id", "name", "age"] |
· 普通类型: bool int32 uint32 int64 uint64 float32 float64 string struct · 数组类型: []bool []int32 []uint32 []int64 []uint64 []float32 []float64 []string []struct · 字典类型: map[string]bool map[string]int32 map[string]uint32 map[string]int64 map[string]uint64 map[string]float32 map[string]float64 map[string]string map[string]struct
· CreateOnly: 只允许创建,不允许后续修改字段 · ReadOnly: 只允许读取字段,不允许创建和修改,适用于从别的系统导入数据到数据库,然后提供数据的读取服务
type Foo struct {
Id *string `json:"id,omitempty" bson:"_id,omitempty"`
...
}
· btime: birth time,记录该条数据创建的时间戳 · mtime: modify time, 记录该条数据最后一次修改的时间戳
· seq: 数据序列号,数据每次被修改都会更新序列号,更新(PATCH)请求需要带上数据原seq防止并发写引起数据错乱
· db: 数据库名称 · col: 表名称(集合名称) 示例:/{Biz}?db=dbName&col=colName 如未指定,则组件默认以rest_{biz}作为数据库名称,以cn作为表名称
框架使用方式非常简单,初始化好一个router路由句柄和mongodb句柄,定义好数据资源的结构,即可服务。
服务前需要先启动一个MongoDB服务,假设服务地址为:mongodb://127.0.0.1:27017
package main
import (
"fmt"
"net/http"
"time"
"github.com/globalsign/mgo"
"github.com/gorilla/mux"
"github.com/jimdn/restful"
)
// step 1: init data structure
type Student struct {
Id *string `json:"id,omitempty" bson:"_id,omitempty"`
Name *string `json:"name,omitempty" bson:"name,omitempty"`
Age *int64 `json:"age,omitempty" bson:"age,omitempty"`
Sex *string `json:"sex,omitempty" bson:"sex,omitempty"`
Hobbies []string `json:"hobbies,omitempty" bson:"hobbies,omitempty"`
Btime *int64 `json:"btime,omitempty" bson:"btime,omitempty"` // internal, doc birth time
Mtime *int64 `json:"mtime,omitempty" bson:"mtime,omitempty"` // internal, doc modify time
Seq *string `json:"seq,omitempty" bson:"seq,omitempty"` // internal, doc seq, prevent concurrent updating
}
func main () {
// step 2: init router and mongodb
router := mux.NewRouter()
mgoSess, err := mgo.DialWithTimeout("mongodb://127.0.0.1:27017", 5 * time.Second)
if err != nil {
fmt.Printf("mongo dial err: %v\n", err)
return
}
// step 3: init restful
processors := []restful.Processor {
{
Biz: "students",
URLPath: "/students",
DataStruct: new(Student),
},
}
restfulGlobalCfg := restful.GlobalConfig {
Mux: router,
MgoSess: mgoSess,
}
err = restful.Init(&restfulGlobalCfg, &processors)
if err != nil {
fmt.Printf("restful init err: %v\n", err)
return
}
// step4: start http server
srv := &http.Server{
Handler: router,
Addr: "127.0.0.1:8080",
WriteTimeout: 10 * time.Second,
ReadTimeout: 10 * time.Second,
}
err = srv.ListenAndServe()
if err != nil {
fmt.Printf("ListenAndServe err: %v", err)
}
}
更多示例可以参考代码库里的examples目录里的示例。
4. 主要实现思路
type Foo struct {
Id *string `json:"id,omitempty" bson:"_id,omitempty"`
...
}
如请求处理失败,失败代码会同时体现在HttpStatusCode和包体的code,失败信息会体现在包体的msg。
字段内容值的合法性判断
字段加密功能
字段脱敏功能
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。