mirror of https://github.com/zhufuyi/sponge
docs: update readme
This commit is contained in:
parent
af791196cf
commit
236b72bebb
|
@ -18,7 +18,7 @@ Common gin middleware libraries, including:
|
|||
|
||||
### Logging middleware
|
||||
|
||||
You can set the maximum length for printing, add a request id field, ignore print path, customize [zap](go.uber.org/zap) log.
|
||||
You can set the maximum length for printing, add a request id field, ignore print path, customize [zap](https://github.com/uber-go/zap) log.
|
||||
|
||||
```go
|
||||
import (
|
||||
|
@ -126,6 +126,12 @@ func NewRouter() *gin.Engine {
|
|||
r.Use(middleware.CircuitBreaker(
|
||||
//middleware.WithValidCode(http.StatusRequestTimeout), // add error code 408 for circuit breaker
|
||||
//middleware.WithDegradeHandler(handler), // add custom degrade handler
|
||||
//middleware.WithBreakerOption(
|
||||
//circuitbreaker.WithSuccess(75), // default 60
|
||||
//circuitbreaker.WithRequest(200), // default 100
|
||||
//circuitbreaker.WithBucket(20), // default 10
|
||||
//circuitbreaker.WithWindow(time.Second*5), // default 3s
|
||||
//),
|
||||
))
|
||||
|
||||
// ......
|
||||
|
|
|
@ -43,7 +43,7 @@ func (o *circuitBreakerOptions) apply(opts ...CircuitBreakerOption) {
|
|||
}
|
||||
|
||||
// WithGroup with circuit breaker group.
|
||||
// NOTE: implements generics circuitbreaker.CircuitBreaker
|
||||
// Deprecated: use WithBreakerOption instead
|
||||
func WithGroup(g *group.Group) CircuitBreakerOption {
|
||||
return func(o *circuitBreakerOptions) {
|
||||
if g != nil {
|
||||
|
@ -52,6 +52,17 @@ func WithGroup(g *group.Group) CircuitBreakerOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithBreakerOption set the circuit breaker options.
|
||||
func WithBreakerOption(opts ...circuitbreaker.Option) CircuitBreakerOption {
|
||||
return func(o *circuitBreakerOptions) {
|
||||
if len(opts) > 0 {
|
||||
o.group = group.NewGroup(func() interface{} {
|
||||
return circuitbreaker.NewBreaker(opts...)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithValidCode http code to mark failed
|
||||
func WithValidCode(code ...int) CircuitBreakerOption {
|
||||
return func(o *circuitBreakerOptions) {
|
||||
|
|
|
@ -26,9 +26,16 @@ func runCircuitBreakerHTTPServer() string {
|
|||
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.New()
|
||||
r.Use(CircuitBreaker(WithGroup(group.NewGroup(func() interface{} {
|
||||
return circuitbreaker.NewBreaker()
|
||||
})),
|
||||
r.Use(CircuitBreaker(
|
||||
WithGroup(group.NewGroup(func() interface{} {
|
||||
return circuitbreaker.NewBreaker()
|
||||
})),
|
||||
WithBreakerOption(
|
||||
circuitbreaker.WithSuccess(75), // default 60
|
||||
circuitbreaker.WithRequest(200), // default 100
|
||||
circuitbreaker.WithBucket(20), // default 10
|
||||
circuitbreaker.WithWindow(time.Second*5), // default 3s
|
||||
),
|
||||
WithValidCode(http.StatusForbidden),
|
||||
WithDegradeHandler(degradeHandler),
|
||||
))
|
||||
|
|
|
@ -5,15 +5,34 @@
|
|||
### Example of use
|
||||
|
||||
```go
|
||||
import "github.com/go-dev-frame/sponge/pkg/grpc/client"
|
||||
package main
|
||||
|
||||
conn, err := client.NewClient(context.Background(), "127.0.0.1:8282",
|
||||
//client.WithServiceDiscover(builder),
|
||||
//client.WithLoadBalance(),
|
||||
//client.WithSecure(credentials),
|
||||
//client.WithUnaryInterceptor(unaryInterceptors...),
|
||||
//client.WithStreamInterceptor(streamInterceptors...),
|
||||
)
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/go-dev-frame/sponge/pkg/grpc/client"
|
||||
pb "google.golang.org/grpc/examples/helloworld/helloworld"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn, err := client.NewClient("127.0.0.1:8282",
|
||||
//client.WithServiceDiscover(getDiscovery(), false),
|
||||
//client.WithLoadBalance(),
|
||||
//client.WithSecure(credentials),
|
||||
//client.WithUnaryInterceptor(unaryInterceptors...),
|
||||
//client.WithStreamInterceptor(streamInterceptors...),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
greeterClient := pb.NewGreeterClient(conn)
|
||||
reply, err := greeterClient.SayHello(context.Background(), &pb.HelloRequest{Name: "Alice"})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("Greeting: %s\n", reply.GetMessage())
|
||||
|
||||
conn.Close()
|
||||
}
|
||||
```
|
||||
|
||||
Examples of practical use https://github.com/zhufuyi/grpc_examples/blob/main/usage/client/main.go
|
||||
|
|
|
@ -8,13 +8,19 @@ import (
|
|||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/resolver"
|
||||
|
||||
"github.com/go-dev-frame/sponge/pkg/servicerd/discovery"
|
||||
"github.com/go-dev-frame/sponge/pkg/servicerd/registry"
|
||||
)
|
||||
|
||||
// Option client option func
|
||||
type Option func(*options)
|
||||
|
||||
type options struct {
|
||||
builders []resolver.Builder
|
||||
builders []resolver.Builder
|
||||
iDiscovery registry.Discovery
|
||||
isInsecure bool
|
||||
|
||||
isLoadBalance bool
|
||||
credentials credentials.TransportCredentials
|
||||
unaryInterceptors []grpc.UnaryClientInterceptor
|
||||
|
@ -33,9 +39,17 @@ func (o *options) apply(opts ...Option) {
|
|||
}
|
||||
|
||||
// WithServiceDiscover set service discover
|
||||
func WithServiceDiscover(builders ...resolver.Builder) Option {
|
||||
func WithServiceDiscover(d registry.Discovery, isInsecure bool) Option {
|
||||
return func(o *options) {
|
||||
o.builders = builders
|
||||
o.iDiscovery = d
|
||||
o.isInsecure = isInsecure
|
||||
}
|
||||
}
|
||||
|
||||
// WithServiceDiscoverBuilder set service discover builder
|
||||
func WithServiceDiscoverBuilder(builder ...resolver.Builder) Option {
|
||||
return func(o *options) {
|
||||
o.builders = builder
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +97,15 @@ func NewClient(endpoint string, opts ...Option) (*grpc.ClientConn, error) {
|
|||
|
||||
// service discovery
|
||||
if len(o.builders) > 0 {
|
||||
dialOptions = append(dialOptions, grpc.WithResolvers(o.builders...))
|
||||
dialOptions = append(dialOptions, grpc.WithResolvers(o.builders...)) // higher priority
|
||||
} else {
|
||||
if o.iDiscovery != nil {
|
||||
dialOptions = append(dialOptions, grpc.WithResolvers(
|
||||
discovery.NewBuilder(
|
||||
o.iDiscovery,
|
||||
discovery.WithInsecure(o.isInsecure),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
// load balance option
|
||||
|
|
|
@ -8,8 +8,20 @@ import (
|
|||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/resolver"
|
||||
|
||||
"github.com/go-dev-frame/sponge/pkg/servicerd/registry"
|
||||
)
|
||||
|
||||
func getDiscovery() registry.Discovery {
|
||||
//endpoint = "discovery:///" + grpcClientCfg.Name // format: discovery:///serverName
|
||||
//cli, err := consulcli.Init(cfg.Consul.Addr, consulcli.WithWaitTime(time.Second*5))
|
||||
//if err != nil {
|
||||
// panic(fmt.Sprintf("consulcli.Init error: %v, addr: %s", err, cfg.Consul.Addr))
|
||||
//}
|
||||
//return consul.New(cli)
|
||||
return nil
|
||||
}
|
||||
|
||||
type builder struct{}
|
||||
|
||||
func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
|
||||
|
@ -34,7 +46,8 @@ var streamInterceptors = []grpc.StreamClientInterceptor{
|
|||
|
||||
func TestNewClient(t *testing.T) {
|
||||
conn, err := NewClient("127.0.0.1:50082",
|
||||
WithServiceDiscover(new(builder)),
|
||||
WithServiceDiscover(getDiscovery(), false),
|
||||
WithServiceDiscoverBuilder(new(builder)),
|
||||
WithLoadBalance(),
|
||||
WithSecure(insecure.NewCredentials()),
|
||||
WithUnaryInterceptor(unaryInterceptors...),
|
||||
|
|
|
@ -211,6 +211,12 @@ func setDialOptions() []grpc.DialOption {
|
|||
interceptor.UnaryServerCircuitBreaker(
|
||||
//interceptor.WithValidCode(codes.DeadlineExceeded), // add error code for circuit breaker
|
||||
//interceptor.WithUnaryServerDegradeHandler(handler), // add custom degrade handler
|
||||
//interceptor.WithBreakerOption(
|
||||
//circuitbreaker.WithSuccess(75), // default 60
|
||||
//circuitbreaker.WithRequest(200), // default 100
|
||||
//circuitbreaker.WithBucket(20), // default 10
|
||||
//circuitbreaker.WithWindow(time.Second*5), // default 3s
|
||||
//),
|
||||
),
|
||||
)
|
||||
options = append(options, option)
|
||||
|
|
|
@ -47,7 +47,7 @@ func (o *circuitBreakerOptions) apply(opts ...CircuitBreakerOption) {
|
|||
}
|
||||
|
||||
// WithGroup with circuit breaker group.
|
||||
// NOTE: implements generics circuitbreaker.CircuitBreaker
|
||||
// Deprecated: use WithBreakerOption instead
|
||||
func WithGroup(g *group.Group) CircuitBreakerOption {
|
||||
return func(o *circuitBreakerOptions) {
|
||||
if g != nil {
|
||||
|
@ -56,6 +56,17 @@ func WithGroup(g *group.Group) CircuitBreakerOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithBreakerOption set the circuit breaker options.
|
||||
func WithBreakerOption(opts ...circuitbreaker.Option) CircuitBreakerOption {
|
||||
return func(o *circuitBreakerOptions) {
|
||||
if len(opts) > 0 {
|
||||
o.group = group.NewGroup(func() interface{} {
|
||||
return circuitbreaker.NewBreaker(opts...)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithValidCode rpc code to mark failed
|
||||
func WithValidCode(code ...codes.Code) CircuitBreakerOption {
|
||||
return func(o *circuitBreakerOptions) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package interceptor
|
|||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -18,6 +19,12 @@ func TestUnaryClientCircuitBreaker(t *testing.T) {
|
|||
WithGroup(group.NewGroup(func() interface{} {
|
||||
return circuitbreaker.NewBreaker()
|
||||
})),
|
||||
WithBreakerOption(
|
||||
circuitbreaker.WithSuccess(75), // default 60
|
||||
circuitbreaker.WithRequest(200), // default 100
|
||||
circuitbreaker.WithBucket(20), // default 10
|
||||
circuitbreaker.WithWindow(time.Second*5), // default 3s
|
||||
),
|
||||
WithValidCode(codes.PermissionDenied),
|
||||
)
|
||||
|
||||
|
|
|
@ -5,22 +5,45 @@
|
|||
### Example of use
|
||||
|
||||
```go
|
||||
import "github.com/go-dev-frame/sponge/pkg/grpc/server"
|
||||
package main
|
||||
|
||||
port := 8282
|
||||
registerFn := func(s *grpc.Server) {
|
||||
pb.RegisterGreeterServer(s, &greeterServer{})
|
||||
}
|
||||
|
||||
server.Run(port, registerFn,
|
||||
//server.WithSecure(credentials),
|
||||
//server.WithUnaryInterceptor(unaryInterceptors...),
|
||||
//server.WithStreamInterceptor(streamInterceptors...),
|
||||
//server.WithServiceRegister(func() {}),
|
||||
//server.WithStatConnections(metrics.WithConnectionsLogger(logger.Get()), metrics.WithConnectionsGauge()), // show connections or set prometheus metrics
|
||||
)
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/go-dev-frame/sponge/pkg/grpc/server"
|
||||
"google.golang.org/grpc"
|
||||
pb "google.golang.org/grpc/examples/helloworld/helloworld"
|
||||
)
|
||||
|
||||
select{}
|
||||
type greeterServer struct {
|
||||
pb.UnimplementedGreeterServer
|
||||
}
|
||||
|
||||
func (s *greeterServer) SayHello(_ context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
|
||||
fmt.Printf("Received: %v\n", in.GetName())
|
||||
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
port := 8282
|
||||
registerFn := func(s *grpc.Server) {
|
||||
pb.RegisterGreeterServer(s, &greeterServer{})
|
||||
// Register other services here
|
||||
}
|
||||
|
||||
fmt.Printf("Starting server on port %d\n", port)
|
||||
srv, err := server.Run(port, registerFn,
|
||||
//server.WithSecure(credentials),
|
||||
//server.WithUnaryInterceptor(unaryInterceptors...),
|
||||
//server.WithStreamInterceptor(streamInterceptors...),
|
||||
//server.WithServiceRegister(srFn), // register service address to Consul/Etcd/Zookeeper...
|
||||
//server.WithStatConnections(metrics.WithConnectionsLogger(logger.Get()), metrics.WithConnectionsGauge()),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer srv.Stop()
|
||||
|
||||
select {}
|
||||
}
|
||||
```
|
||||
|
||||
Examples of practical use https://github.com/zhufuyi/grpc_examples/blob/main/usage/server/main.go
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
// RegisterFn register object
|
||||
type RegisterFn func(srv *grpc.Server)
|
||||
|
||||
// ServiceRegisterFn service register
|
||||
type ServiceRegisterFn func()
|
||||
// ServiceRegisterFn used to register service address to Consul/ETCD/Nacos/Zookeeper...
|
||||
type ServiceRegisterFn func() error
|
||||
|
||||
// Option set server option
|
||||
type Option func(*options)
|
||||
|
@ -95,15 +95,15 @@ func customInterceptorOptions(o *options) []grpc.ServerOption {
|
|||
return opts
|
||||
}
|
||||
|
||||
// Run grpc server
|
||||
func Run(port int, registerFn RegisterFn, options ...Option) {
|
||||
// Run grpc server with options, registerFn is the function to register object to the server
|
||||
func Run(port int, registerFn RegisterFn, options ...Option) (*grpc.Server, error) {
|
||||
o := defaultServerOptions()
|
||||
o.apply(options...)
|
||||
|
||||
// listening on TCP port
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if o.isShowConnections {
|
||||
|
@ -116,9 +116,11 @@ func Run(port int, registerFn RegisterFn, options ...Option) {
|
|||
// register object to the server
|
||||
registerFn(srv)
|
||||
|
||||
// register service to target
|
||||
// register service address to Consul/ETCD/Nacos/Zookeeper...
|
||||
if o.serviceRegisterFn != nil {
|
||||
o.serviceRegisterFn()
|
||||
if err = o.serviceRegisterFn(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
@ -128,4 +130,6 @@ func Run(port int, registerFn RegisterFn, options ...Option) {
|
|||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
return srv, nil
|
||||
}
|
||||
|
|
|
@ -18,6 +18,15 @@ var fn = func(s *grpc.Server) {
|
|||
// pb.RegisterGreeterServer(s, &greeterServer{})
|
||||
}
|
||||
|
||||
var srFn = func() error {
|
||||
//iRegistry, instance, err := consul.NewRegistry(cfg.Consul.Addr, id, cfg.App.Name, []string{instanceEndpoint})
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
// return iRegistry.Register(ctx, instance)
|
||||
return nil
|
||||
}
|
||||
|
||||
var unaryInterceptors = []grpc.UnaryServerInterceptor{
|
||||
func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
return nil, nil
|
||||
|
@ -32,13 +41,14 @@ var streamInterceptors = []grpc.StreamServerInterceptor{
|
|||
|
||||
func TestRun(t *testing.T) {
|
||||
port, _ := utils.GetAvailablePort()
|
||||
Run(port, fn,
|
||||
srv, _ := Run(port, fn,
|
||||
WithSecure(insecure.NewCredentials()),
|
||||
WithUnaryInterceptor(unaryInterceptors...),
|
||||
WithStreamInterceptor(streamInterceptors...),
|
||||
WithServiceRegister(func() {}),
|
||||
WithServiceRegister(srFn),
|
||||
WithStatConnections(metrics.WithConnectionsLogger(logger.Get()), metrics.WithConnectionsGauge()),
|
||||
)
|
||||
defer srv.Stop()
|
||||
t.Log("grpc server started", port)
|
||||
time.Sleep(time.Second * 2)
|
||||
|
||||
|
|
|
@ -8,9 +8,7 @@ Support `mysql`, `postgresql`, `sqlite`.
|
|||
|
||||
## Examples of use
|
||||
|
||||
### mysql
|
||||
|
||||
#### Initializing the connection
|
||||
### Mysql
|
||||
|
||||
```go
|
||||
import "github.com/go-dev-frame/sponge/pkg/sgorm/mysql"
|
||||
|
@ -18,7 +16,7 @@ Support `mysql`, `postgresql`, `sqlite`.
|
|||
var dsn = "root:123456@(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
|
||||
// case 1: connect to the database using the default settings
|
||||
gdb, err := mysql.Init(dsn)
|
||||
db, err := mysql.Init(dsn)
|
||||
|
||||
// case 2: customised settings to connect to the database
|
||||
db, err := mysql.Init(
|
||||
|
@ -81,18 +79,18 @@ Tidb is mysql compatible, just use **mysql.Init**.
|
|||
import "github.com/go-dev-frame/sponge/pkg/sgorm/sqlite"
|
||||
|
||||
func InitSqlite() {
|
||||
opts := []sgorm.Option{
|
||||
sgorm.WithMaxIdleConns(10),
|
||||
sgorm.WithMaxOpenConns(100),
|
||||
sgorm.WithConnMaxLifetime(time.Duration(10) * time.Minute),
|
||||
sgorm.WithLogging(logger.Get()),
|
||||
sgorm.WithLogRequestIDKey("request_id"),
|
||||
opts := []sqlite.Option{
|
||||
sqlite.WithMaxIdleConns(10),
|
||||
sqlite.WithMaxOpenConns(100),
|
||||
sqlite.WithConnMaxLifetime(time.Duration(10) * time.Minute),
|
||||
sqlite.WithLogging(logger.Get()),
|
||||
sqlite.WithLogRequestIDKey("request_id"),
|
||||
}
|
||||
|
||||
dbFile: = "test.db"
|
||||
db, err := sgorm.Init(dbFile, opts...)
|
||||
db, err := sqlite.Init(dbFile, opts...)
|
||||
if err != nil {
|
||||
panic("sgorm.Init error: " + err.Error())
|
||||
panic("sqlite.Init error: " + err.Error())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -159,6 +157,6 @@ func (table *User) TableName() string {
|
|||
|
||||
<br>
|
||||
|
||||
### gorm User Guide
|
||||
### Gorm Guide
|
||||
|
||||
- https://gorm.io/zh_CN/docs/index.html
|
||||
|
|
Loading…
Reference in New Issue