fastrest

package module
v0.0.0-...-f040d84 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 13, 2024 License: MIT Imports: 31 Imported by: 0

README

fastrest

fast restful framework for golang.

img.png

  1. Create your app directory, like mkdir myapp; cd myapp; go mod init myapp;

  2. Create initial config.toml in a folder initassets, example

    ---
    addr: ":14142"
    
  3. Create main code, example

    package main
    
    import (
        "embed"
        "github.com/bingoohuang/fastrest"
        _ "github.com/bingoohuang/fastrest/validators/v10" // 引入请求结构体自动校验
    )
    
    // InitAssets is the initial assets.
    //go:embed initassets
    var InitAssets embed.FS
    
    func main() {
        // 注册路由
        router := fastrest.New(map[string]fastrest.Service{
            "GET /status":  &fastrest.Status{},
            "POST /p1sign": &fastrest.P1Sign{},
        }, fastrest.WithPreProcessor(fastrest.PreProcessorFn(func(dtx *fastrest.Context) error {
            // 全局前置处理器
            return nil
        })), fastrest.WithPostProcessor(fastrest.PostProcessorFn(func(dtx *fastrest.Context) error {
            // 全局后置处理器
            return nil
        })))
    
        args := fastrest.ParseArgs(&InitAssets)
        args.Run(router)
    }
    
  4. Create Makefile, example

  5. Build make

  6. Create initial conf.toml and ctl: myapp -init

  7. Startup ./ctl start, you can set env export GOLOG_STDOUT=true before startup to view the log in stdout for debugging.

  8. Performance testing using berf: berf :14142/status -d15s -v

  9. Or single test berf :14142/p1sign -v source=bingoo bizType=abc -n1

➜  fastrest git:(main) ✗ berf :14142/p1sign source=bingoo bizType=abc -pRr -n1
### 127.0.0.1:63079->127.0.0.1:14142 time: 2022-01-05T14:19:36.312775+08:00 cost: 575.239µs
POST /p1sign HTTP/1.1
User-Agent: blow
Host: 127.0.0.1:14142
Content-Type: application/json; charset=utf-8
Content-Length: 36
Accept-Encoding: gzip, deflate

{"bizType":"abc","source":"bingoo"}

HTTP/1.1 200 OK
Server: fasthttp
Date: Wed, 05 Jan 2022 06:19:36 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 19

{"source":"bingoo"}

easyjson marshalling and unmarshalling

  1. Install easyjson tool
  2. Tag the model, see the following example.
  3. Generate easyjson codes: easyjson yourmodel.go
//easyjson:json
type P1SignReq struct {
Source  string `json:"source"`
BizType string `json:"bizType"`
}

//easyjson:json
type P1SignRsp struct {
Source string `json:"source"`
}

性能测试

  1. 空接口 /status TPS 30 万.
# Hostname Uptime Uptime Human Procs OS Platform Host ID Platform Version Kernel Version Kernel Arch Os Release Mem Available Num CPU Cpu Mhz Cpu Model
1 fs04-192-168-126-184 14173428 5 months 373 linux centos ea4bc56f-c6da-4914-afc6-4d9e54267d41 8 4.18.0-240.22.1.el8_3.x86_64 x86_64 NAME="CentOS Stream" VERSION="8" 57.25GiB/62.65GiB, 00.91% 16 2300 Intel(R) Xeon(R) Gold 5218 CPU @ 2.30GHz
[footstone@fs04-192-168-126-184 ~]$ berf :14142/status -c500
Berf benchmarking http://127.0.0.1:14142/status using 500 goroutine(s), 16 GoMaxProcs.

Summary:
  Elapsed                 43.346s
  Count/RPS   13280606 306379.932
    200       13280606 306379.932
  ReadWrite  426.481 401.970 Mbps

Statistics     Min       Mean     StdDev     Max
  Latency     27µs      1.612ms   1.773ms  56.755ms
  RPS       285977.74  306261.61  8250.69  326172.9

Latency Percentile:
  P50        P75      P90     P95      P99     P99.9     P99.99
  1.324ms  2.059ms  2.749ms  3.85ms  9.626ms  18.188ms  29.256ms
[footstone@fs04-192-168-126-184 ~]$ berf :14142/status -c500 -d1m
Berf benchmarking http://127.0.0.1:14142/status for 1m0s using 500 goroutine(s), 16 GoMaxProcs.

Summary:
  Elapsed                    1m0s
  Count/RPS   18266731 304441.873
    200       18266731 304441.873
  ReadWrite  423.783 399.428 Mbps

Statistics     Min       Mean     StdDev      Max
  Latency     27µs      1.621ms   1.766ms  69.199ms
  RPS       278032.17  304437.17  9856.28  323089.77

Latency Percentile:
  P50        P75      P90      P95      P99     P99.9     P99.99
  1.376ms  2.065ms  2.713ms  3.702ms  9.401ms  19.398ms  33.875ms

AccessLog

  1. 设置环境变量 ACCESS_LOG_DIR,启用 access log, e.g. ACCESS_LOG_DIR=accesslog fastrest

技术特点

fastrest 基于 Go 语言优秀的GPM并发模型之上,叠加多项优化技术:

  1. 替换默认的 net/http 为 fasthttp,基准测试性能提升约10倍
  2. 替换默认的 encoding/base64 为基于 Turbo-Base64 实现的 cristalhq/base64,是基准测试性能提升约3倍
  3. 替换默认的 encoding/json 为基于代码生成免除反射调用的 easyjson,,基准测试性能提升约5倍
  4. 调整默认的 最大并发数 GOMAXPROCS 8 为4倍值约30,能达到最高性能

Documentation

Index

Constants

View Source
const (
	ResultSendFile = "__ResultSendFile"
)

Variables

View Source
var (
	DefaultPreProcessors   []PreProcessor
	DefaultPostProcessors  []PostProcessor
	DefaultErrorProcessors []ErrorProcessor
)
View Source
var LogTypeEnv = func() LogType {
	switch v := os.Getenv("LOG_TYPE"); strings.ToLower(v) {
	case "0", "off", "no":
		return LogOff
	case "async":
		return LogAsync
	default:
		return LogOn
	}
}()

Functions

func Combined

Combined format: [<time>] <remote-addr> | <HTTP/http-version> | <method> <url> <request body size> - <status> <response body size> <response-time us> | <user-agent> [2017-05-31 13:27:28] 127.0.0.1:54082 | HTTP/1.1 | GET /hello 12345 - 200 12345 48.279µs | Paw/3.1.1 (Macintosh; OS X/10.12.5) GCDHTTPRequest

func GetClientIP

func GetClientIP(ctx *fasthttp.RequestCtx) string

GetClientIP returns the originating IP for a request.

func GetDailyLogWriter

func GetDailyLogWriter(filename string) (*rotatelogs.RotateLogs, error)

GetDailyLogWriter 日志文件切割,按天

func IsEnvOff

func IsEnvOff(name string) bool

func RegisterErrorProcessors

func RegisterErrorProcessors(processors ...ErrorProcessor)

func RegisterPostProcessor

func RegisterPostProcessor(processors ...PostProcessor)

func RegisterPreProcessor

func RegisterPreProcessor(processors ...PreProcessor)

func Short

Short format: <remote-addr> | <HTTP/:http-version> | <method> <url> - <status> - <response-time us> 127.0.0.1:53324 | HTTP/1.1 | GET /hello - 200 - 44.8µs

func Tiny

Tiny format: <method> <url> - <status> - <response-time us> GET / - 200 - 11.925 us

Types

type Arg

type Arg struct {
	Config string `flag:"c" usage:"yaml Config filepath"`

	Addr      string `val:":14142"`
	Init      bool   `usage:"init example conf.yml/ctl and then exit"`
	Version   bool   `usage:"print version then exit"`
	ReusePort bool   `usage:"Reuse port"`
	MaxProcs  int    `usage:"GOMAXPROCS"`
}

func ParseArgs

func ParseArgs(initFiles *embed.FS) Arg

func (*Arg) Run

func (c *Arg) Run(router *Router)

func (*Arg) VersionInfo

func (c *Arg) VersionInfo() string

type Context

type Context struct {
	Req interface{}
	Rsp interface{}

	Ctx         *fasthttp.RequestCtx
	ServiceName string

	Returners []bytebufferpool.PoolReturner
}

func (*Context) AppendPoolReturner

func (c *Context) AppendPoolReturner(r bytebufferpool.PoolReturner)

func (*Context) ApplyPoolBuf

func (c *Context) ApplyPoolBuf(size int) []byte

func (*Context) Release

func (c *Context) Release()

type DummyService

type DummyService struct{}

func (*DummyService) CreateReq

func (d *DummyService) CreateReq() (interface{}, error)

func (DummyService) Process

func (d DummyService) Process(*Context) (interface{}, error)

type Echo

type Echo struct{ DummyService }

func (*Echo) Process

func (p *Echo) Process(c *Context) (interface{}, error)

type Encrypt

type Encrypt struct{ DummyService }

func (*Encrypt) CreateReq

func (p *Encrypt) CreateReq() (interface{}, error)

func (*Encrypt) Process

func (p *Encrypt) Process(dtx *Context) (interface{}, error)

type EncryptReq

type EncryptReq struct {
	TransId   string `json:"transId"`
	AppId     string `json:"appId"`
	KeyId     string `json:"keyId"`
	Mode      string `json:"mode"`
	Padding   string `json:"padding"`
	PlainText string `json:"plainText"`
}

func (EncryptReq) MarshalEasyJSON

func (v EncryptReq) MarshalEasyJSON(w *jwriter.Writer)

MarshalEasyJSON supports easyjson.Marshaler interface

func (*EncryptReq) UnmarshalEasyJSON

func (v *EncryptReq) UnmarshalEasyJSON(l *jlexer.Lexer)

UnmarshalEasyJSON supports easyjson.Unmarshaler interface

type EncryptRsp

type EncryptRsp struct {
	Data string `json:"data"`
}

func (EncryptRsp) MarshalEasyJSON

func (v EncryptRsp) MarshalEasyJSON(w *jwriter.Writer)

MarshalEasyJSON supports easyjson.Marshaler interface

func (*EncryptRsp) UnmarshalEasyJSON

func (v *EncryptRsp) UnmarshalEasyJSON(l *jlexer.Lexer)

UnmarshalEasyJSON supports easyjson.Unmarshaler interface

type ErrorProcessor

type ErrorProcessor interface {
	ProcessError(dtx *Context, err error) error
}

type ErrorProcessorFn

type ErrorProcessorFn func(dtx *Context, err error) error

func (ErrorProcessorFn) ProcessError

func (f ErrorProcessorFn) ProcessError(dtx *Context, err error) error

type Jpg

type Jpg struct{ DummyService }

func (*Jpg) Process

func (p *Jpg) Process(ctx *Context) (interface{}, error)

type LogPrint

type LogPrint func(format string, a ...interface{})

LogPrint logs a message using the given format and optional arguments. The usage of format and arguments is similar to that for fmt.Printf(). LogPrint should be thread safe.

type LogType

type LogType int
const (
	LogOff LogType = iota
	LogOn
	LogAsync
)

type P1Sign

type P1Sign struct{ DummyService }

func (*P1Sign) CreateReq

func (p *P1Sign) CreateReq() (interface{}, error)

func (*P1Sign) Process

func (p *P1Sign) Process(dtx *Context) (interface{}, error)

type P1SignReq

type P1SignReq struct {
	Source  string `json:"source"`
	BizType string `json:"bizType"`
}

func (P1SignReq) MarshalEasyJSON

func (v P1SignReq) MarshalEasyJSON(w *jwriter.Writer)

MarshalEasyJSON supports easyjson.Marshaler interface

func (*P1SignReq) UnmarshalEasyJSON

func (v *P1SignReq) UnmarshalEasyJSON(l *jlexer.Lexer)

UnmarshalEasyJSON supports easyjson.Unmarshaler interface

type P1SignRsp

type P1SignRsp struct {
	Source string `json:"source"`
}

func (P1SignRsp) MarshalEasyJSON

func (v P1SignRsp) MarshalEasyJSON(w *jwriter.Writer)

MarshalEasyJSON supports easyjson.Marshaler interface

func (*P1SignRsp) UnmarshalEasyJSON

func (v *P1SignRsp) UnmarshalEasyJSON(l *jlexer.Lexer)

UnmarshalEasyJSON supports easyjson.Unmarshaler interface

type PanicProcessor

type PanicProcessor interface {
	PanicProcess(dtx *Context, recovered interface{})
}

type PanicProcessorFn

type PanicProcessorFn func(dtx *Context, recovered interface{})

func (PanicProcessorFn) PanicProcess

func (f PanicProcessorFn) PanicProcess(dtx *Context, recovered interface{})

type PanicService

type PanicService struct{ DummyService }

func (*PanicService) Process

func (p *PanicService) Process(dtx *Context) (interface{}, error)

type PostProcessor

type PostProcessor interface {
	PostProcess(dtx *Context) error
}

type PostProcessorFn

type PostProcessorFn func(dtx *Context) error

func (PostProcessorFn) PostProcess

func (f PostProcessorFn) PostProcess(dtx *Context) error

type PreProcessor

type PreProcessor interface {
	PreProcess(dtx *Context) error
}

type PreProcessorFn

type PreProcessorFn func(dtx *Context) error

func (PreProcessorFn) PreProcess

func (f PreProcessorFn) PreProcess(dtx *Context) error

type Router

type Router struct {
	Config *RouterConfig
	// contains filtered or unexported fields
}

func New

func New(m map[string]Service, fns ...RouterConfigFn) *Router

func (*Router) Serve

func (r *Router) Serve(port string, reusePort bool) error

func (*Router) ServeListener

func (r *Router) ServeListener(ln net.Listener) error

type RouterConfig

type RouterConfig struct {
	PanicProcessor  PanicProcessor
	AccessLogDir    string
	PreProcessors   []PreProcessor
	PostProcessors  []PostProcessor
	ErrorProcessors []ErrorProcessor

	NotFoundHandler func(dtx *Context)
}

type RouterConfigFn

type RouterConfigFn func(*RouterConfig)

func WithAccessLogDir

func WithAccessLogDir(v string) RouterConfigFn

func WithErrorProcessor

func WithErrorProcessor(v ErrorProcessor) RouterConfigFn

func WithNotFoundHandler

func WithNotFoundHandler(v func(ctx *Context)) RouterConfigFn

func WithPanicProcessor

func WithPanicProcessor(v PanicProcessor) RouterConfigFn

func WithPostProcessor

func WithPostProcessor(v PostProcessor) RouterConfigFn

func WithPreProcessor

func WithPreProcessor(v PreProcessor) RouterConfigFn

type Rsp

type Rsp struct {
	Data    interface{} `json:"data,omitempty"`
	Message string      `json:"message,omitempty"`
	Status  int         `json:"status,omitempty"`
}

func (Rsp) MarshalEasyJSON

func (v Rsp) MarshalEasyJSON(w *jwriter.Writer)

MarshalEasyJSON supports easyjson.Marshaler interface

func (*Rsp) UnmarshalEasyJSON

func (v *Rsp) UnmarshalEasyJSON(l *jlexer.Lexer)

UnmarshalEasyJSON supports easyjson.Unmarshaler interface

type Service

type Service interface {
	CreateReq() (interface{}, error)
	Process(dtx *Context) (interface{}, error)
}

type Status

type Status struct{ DummyService }

func (*Status) Process

func (p *Status) Process(*Context) (interface{}, error)

type Version

type Version struct{ DummyService }

func (*Version) Process

func (p *Version) Process(ctx *Context) (interface{}, error)

Directories

Path Synopsis
cmd
fgrpc
validators
v10

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL