gd

package module
v1.7.8 Latest Latest
Warning

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

Go to latest
Published: Apr 18, 2021 License: MIT Imports: 20 Imported by: 2

README

godog

"go" is the meaning of a dog in Chinese pronunciation, and dog's original intention is also a dog. So godog means "狗狗" in Chinese, which is very cute.


Author

author: Chuck1024
email : chuck.ch1024@outlook.com

Installation

Start with cloning gd:

> go get github.com/chuck1024/gd

Introduction

Godog is a basic framework implemented by golang, which is aiming at helping developers setup feature-rich server quickly.

The framework contains config module,databases module,error module,dlog module,net module,runtime module and server module. You can select any modules according to your practice. More features will be added later. I hope anyone who is interested in this work can join it and let's enhance the system function of this framework together.


Quick start

package main

import (
	"github.com/chuck1024/gd"
	"github.com/chuck1024/gd/net/dhttp"
	"github.com/chuck1024/gd/runtime/inject"
	"github.com/gin-gonic/gin"
	"net/http"
)

func HandlerHttp(c *gin.Context, req interface{}) (code int, message string, err error, ret string) {
	gd.Debug("httpServerTest req:%v", req)
	ret = "ok!!!"
	return http.StatusOK, "ok", nil, ret
}

func main() {
	d := gd.Default()
	inject.RegisterOrFail("httpServerInit", func(g *gin.Engine) error {
		r := g.Group("")
		r.Use(
			dhttp.GlFilter(),
			dhttp.GroupFilter(),
			dhttp.Logger("quick-start"),
		)

		d.HttpServer.GET(r, "test", HandlerHttp)

		if err := d.HttpServer.CheckHandle(); err != nil {
			return err
		}
		return nil
	})

	gd.SetConfig("Server", "httpPort", "10240")

	if err := d.Run(); err != nil {
		gd.Error("Error occurs, error = %s", err.Error())
		return
	}
}

[config]
So far, it only supports configuration with ini in gd. Of course, it supports more and more format configuration in future. What's more, your configuration file must have the necessary parameters, like this:

[Log]
enable = true
level = "DEBUG"

[Process]
maxCPU = 2
maxMemory = "2g"
healthPort = 9527

[Server]
serverName = "gd"
httpPort = 10240
rpcPort = 10241
grpcPort = 10242

Log.enable: log config, turn on log output. Log.level: log level. Process.maxCPU: a limit of CPU usage. 0 is default, means to use half cores.
Process.maxMemory: a limit of memory usage. Process.healthPort: the port for monitor. If it is 0, monitor server will not run. Server.serverName: server name.
Server.httpPort: http port. If it is 0, http server will not run.
Server.rpcPort: rpc port. If it is 0, rpc server will not run. Server.grpcPort: grpc port. If it is 0, grpc server will not run.

Those items mentioned above are the base need of a server application. And they are defined in config file: sample/conf/conf.json.


[net]
provides golang network server, it is contain http server and rpc server. It is a simple demo that you can develop it on the basis of it. I will import introduce rpc server. Focus on the rpc server.

type Packet interface {
	ID() uint32
	SetErrCode(code uint32)
}

default rpc packet:
type RpcPacket struct {
	Seq       uint32
	ErrCode   uint32
	Cmd       uint32 // also be a string, for dispatch.
	PacketLen uint32
	Body      []byte
}

gd rpc packet:
type DogPacket struct {
	Header
	Body []byte
}

type Header struct {
	PacketLen uint32
	Seq       uint32
	Cmd       uint32
	CheckSum  uint32
	ErrCode   uint32
	Version   uint8
	Padding   uint8
	SOH       uint8
	EOH       uint8
}

The Packet is a interface in rpc server and client. So, you can make your protocol that suits yourself by implementing packet's methods, if you need. You add new RpcPacket according to yourself rule. DogPacket is a protocol that is used by author. Of course, the author encourages the use of DogPacket.


[server]
provides server register and discovery. Load balancing will be provided in the future. Service discovery registration based on etcd and zookeeper implementation.

register :
type DogRegister interface {
	NewRegister(hosts []string, root, environ, group, service string)
	SetRootNode(node string) error
	GetRootNode() (root string)
	SetHeartBeat(heartBeat time.Duration)
	SetOffline(offline bool)
	Run(ip string, port int, weight uint64) error
	Close()
}

discovery:
type DogDiscovery interface {
	NewDiscovery(dns []string)
	Watch(node string) error
	WatchMulti(nodes []string) error
	AddNode(node string, info *server.NodeInfo)
	DelNode(node string, key string)
	GetNodeInfo(node string) (nodesInfo []server.NodeInfo)
	Run() error
	Close() error
}

nodeInfo:
type NodeInfo interface {
	GetIp() string
	GetPort() int
	GetOffline() bool
	GetWeight() uint64
}

type DefaultNodeInfo struct {
	Ip      string `json:"ip"`
	Port    int    `json:"port"`
	Offline bool   `json:"offline"`
	Weight  uint64 `json:"weight"`
}

The DogRegister and DogDiscovery are interface, gd supports zookeeper and etcd, so you can use others. The NodeInfo is info of node.


Usage

This example simply demonstrates the use of the gd. of course, you need to make conf.json in conf Folder. The example use service discovery with etcd. So, you can install etcd in your computer. Of course, you can choose to comment out these lines of code.

server:

package main

import (
 "context"
 "github.com/chuck1024/gd"
 de "github.com/chuck1024/gd/derror"
 "github.com/chuck1024/gd/net/dhttp"
 "github.com/chuck1024/gd/net/dogrpc"
 "github.com/chuck1024/gd/runtime/inject"
 pb "github.com/chuck1024/gd/sample/helloworld"
 "github.com/gin-gonic/gin"
 "google.golang.org/grpc"
 "net/http"
)

type TestReq struct {
	Data string
}

type TestResp struct {
	Ret string
}

func HandlerHttpTest(c *gin.Context, req *TestReq) (code int, message string, err error, ret *TestResp) {
	gd.Debug("httpServerTest req:%v", req)
	
	ret = &TestResp{
		Ret: "ok!!!",
	}

	return http.StatusOK, "ok", nil, ret
}

func HandlerRpcTest(req *TestReq) (code uint32, message string, err error, ret *TestResp) {
	gd.Debug("rpc sever req:%v", req)
	
	ret = &TestResp{
		Ret: "ok!!!",
	}

	return uint32(de.RpcSuccess), "ok", nil, ret
}

type reg struct {
	handler pb.GreeterServer
}

func (r *reg) RegisterHandler(s *grpc.Server) error {
	pb.RegisterGreeterServer(s, r.handler)
	return nil
}

// server is used to implement hello world.GreeterServer.
type server struct{}

// SayHello implements hello world.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func Register(e *gd.Engine) {
 // http 
	inject.RegisterOrFail("httpServerInit", func(g *gin.Engine) error {
		r := g.Group("")
		r.Use(
			dhttp.GlFilter(), 
			dhttp.StatFilter(), 
			dhttp.GroupFilter(), 
			dhttp.Logger("sample"), 
		)
		
		e.HttpServer.POST(r, "test", HandlerHttpTest)
		
		if err := e.HttpServer.CheckHandle(); err != nil {
			return err
		}
		return nil
 })
	
	// Rpc 
	e.RpcServer.AddDogHandler(1024, HandlerRpcTest)
	if err := e.RpcServer.DogRpcRegister(); err != nil {
		gd.Error("DogRpcRegister occur error:%s", err)
		return
	}
	dogrpc.InitFilters([]dogrpc.Filter{&dogrpc.GlFilter{}, &dogrpc.LogFilter{}})
	
	// grpc 
	inject.RegisterOrFail("registerHandler", &reg{handler: &server{}})
}

func main() {
	d := gd.Default()
	
	Register(d)
	
	err := d.Run()
	if err != nil {
		gd.Error("Error occurs, error = %s", err.Error())
		return
	}
}

// you can use command to test http service.
// curl -X POST http://127.0.0.1:10240/test -H "Content-Type: application/json" --data '{"Data":"test"}'
  • You can find it in "sample/service.go"
  • use control+c to stop process

rpc client:

package main

import (
	"fmt"
	"github.com/chuck1024/gd"
	"github.com/chuck1024/gd/dlog"
	"github.com/chuck1024/gd/server/discovery"
	"time"
)

func main() {
	d := gd.Default()
	c := d.NewRpcClient(time.Duration(500*time.Millisecond), 0)
	// discovery 
	var r discovery.DogDiscovery
	r = &discovery.ZkDiscovery{}
	r.NewDiscovery([]string{"localhost:2379"})
	r.Watch("/root/github/gd/stagging/pool")
	r.Run()
	time.Sleep(100 * time.Millisecond)

	hosts := r.GetNodeInfo("/root/github/gd/stagging/pool")
	for _, v := range hosts {
		dlog.Debug("%s:%d", v.GetIp(), v.GetPort())
	}

	// you can choose one or use load balance algorithm to choose best one.
	// or put all to c.Addr
	for _, v := range hosts {
		if !v.GetOffline() {
			c.AddAddr(fmt.Sprintf("%s:%d", v.GetIp(), v.GetPort()))
		}
	}

	body := []byte("How are you?")

	code, rsp, err := c.DogInvoke(1024, body)
	if err != nil {
		dlog.Error("Error when sending request to server: %s", err)
	}

	// or use rpc protocol
	//rsp, err = c.Invoke(1024, body)
	//if err != nil {
	//t.Logf("Error when sending request to server: %s", err)
	//}

	dlog.Debug("code=%d,resp=%s", code, string(rsp))
}
  • It contained "sample/rpc_client.go"

net module you also use it to do something if you want to use net module only. Here's how it's used.

rpc_server show how to start rpc server

package dogrpc_test

import (
	"github.com/chuck1024/gd/net/dogrpc"
	"testing"
)

func TestRpcServer(t *testing.T) {
	d := dogrpc.NewRpcServer()
	// Rpc
	d.AddHandler(1024, func(req []byte) (uint32, []byte) {
		t.Logf("rpc server request: %s", string(req))
		code := uint32(0)
		resp := []byte("Are you ok?")
		return code, resp
	})

	err := d.Run(10241)
	if err != nil {
		t.Logf("Error occurs, error = %s", err.Error())
		return
	}
}

  • You can find it in "net/dogrpc/rpc_server_test.go"

rpc_clientshow how to call rpc server

package dogrpc_test

import (
	"github.com/chuck1024/gd"
	"github.com/chuck1024/gd/utls"
	"testing"
	"time"
)

func TestRpcClient(t *testing.T) {
	d := gd.Default()
	c := d.NewRpcClient(time.Duration(500*time.Millisecond), 0)
	c.AddAddr(utils.GetLocalIP() + ":10241")

	body := []byte("How are you?")

	code, rsp, err := c.Invoke(1024, body)
	if err != nil {
		t.Logf("Error when sending request to server: %s", err)
	}

	t.Logf("code=%d,resp=%s", code, string(rsp))
}
  • You can find it in "net/dogrpc/rpc_client_test.go"

derror module provides the relation usages of error. It supports the structs of CodeError which contains code, error type, and error msg.

package derror

type CodeError struct {
	errCode int
	errType string
	errMsg  string
}

var (
	RpcSuccess             = 0
	Success                = 200
	BadRequest             = 400
	Unauthorized           = 401
	Forbidden              = 403
	NotFound               = 404
	SystemError            = 500
	ParameterError         = 600
	DBError                = 701
	CacheError             = 702
	RpcTimeout             = 10001
	RpcOverflow            = 10002
	RpcInternalServerError = 10003
	RpcInvalidParam        = 10004
	UnknownError           = "unknown error"

	ErrMap = map[int]string{
		RpcSuccess:             "ok",
		Success:                "ok",
		BadRequest:             "bad request",
		Unauthorized:           "Unauthorized",
		Forbidden:              "Forbidden",
		NotFound:               "not found",
		SystemError:            "system error",
		ParameterError:         "Parameter error",
		DBError:                "db error",
		CacheError:             "cache error",
		RpcTimeout:             "timeout error",
		RpcOverflow:            "overflow error",
		RpcInternalServerError: "interval server error",
		RpcInvalidParam:        "invalid param",
	}
)

// get derror type. you can also add type to ErrMap.
func GetErrorType(code int) string {
	t, ok := ErrMap[code]
	if !ok {
		t = UnknownError
	}
	return t
}

server module

  • if you use etcd, you must download etcd module
  • go get github.com/coreos/etcd/clientv3
  • you can find it usage on "server/register/register_test.go" and "server/discovery/discovery.go"
package register_test

import (
	"github.com/chuck1024/gd/server/register"
	"testing"
	"time"
)

func TestEtcd(t *testing.T) {
	var r register.DogRegister
	r = &register.EtcdRegister{}
	r.NewRegister([]string{"localhost:2379"}, "/root/", "stagging", "gd", "test", )

	r.Run("127.0.0.1", 10240, 10)
	time.Sleep(3 * time.Second)
	r.Close()
}

func TestZk(t *testing.T) {
	var r register.DogRegister
	r = &register.ZkRegister{}
	r.NewRegister([]string{"localhost:2181"}, "/root/", "stagging", "gd", "test", )
	r.Run("127.0.0.1", 10240, 10)
	time.Sleep(10 * time.Second)
	r.Close()
}
package discovery_test

import (
	"github.com/chuck1024/gd/server/discovery"
	"testing"
	"time"
)

func TestDiscEtcd(t *testing.T) {
	var r discovery.DogDiscovery
	r = &discovery.EtcdDiscovery{}
	r.NewDiscovery([]string{"localhost:2379"})
	r.Watch("/root/gd/test/stagging/pool")
	r.Run()
	time.Sleep(100 * time.Millisecond)

	n1 := r.GetNodeInfo("/root/gd/test/stagging/pool")
	for _, v := range n1 {
		t.Logf("%s:%d", v.GetIp(), v.GetPort())
	}

	time.Sleep(10 * time.Second)
}

func TestDiscZk(t *testing.T) {
	var r discovery.DogDiscovery
	r = &discovery.ZkDiscovery{}
	r.NewDiscovery([]string{"localhost:2181"})
	r.Watch("/root/gd/test/stagging/pool")
	r.Run()
	time.Sleep(100 * time.Millisecond)
	n1 := r.GetNodeInfo("/root/gd/test/stagging/pool")
	for _, v := range n1 {
		t.Logf("%s:%d", v.GetIp(), v.GetPort())
	}
	time.Sleep(10 * time.Second)
}

PS: More information can be obtained in the source code


License

gd is released under the MIT LICENSE.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	Shutdown = make(chan os.Signal)
	Running  = make(chan bool)
	Hup      = make(chan os.Signal)
)

Functions

func Config added in v1.6.7

func Config(name, key string) *ini.Key

get config

func Crash added in v1.6.7

func Crash(args ...interface{})

func Crashf added in v1.6.7

func Crashf(format string, args ...interface{})

Logs the given message and crashes the program

func Critical added in v1.6.7

func Critical(arg0 interface{}, args ...interface{})

Utility for critical log messages (returns an error for easy function returns) (see Debug() for parameter explanation) These functions will execute a closure exactly once, to build the error message for the return Wrapper for (*Logger).Critical

func CriticalT added in v1.6.7

func CriticalT(tag string, arg0 interface{}, args ...interface{})

func Debug added in v1.6.7

func Debug(arg0 interface{}, args ...interface{})

wrap log debug

func DebugT added in v1.6.7

func DebugT(tag string, arg0 interface{}, args ...interface{})

func Error added in v1.6.7

func Error(arg0 interface{}, args ...interface{})

Utility for error log messages (returns an error for easy function returns) (see Debug() for parameter explanation) These functions will execute a closure exactly once, to build the error message for the return Wrapper for (*Logger).Error

func ErrorT added in v1.6.7

func ErrorT(tag string, arg0 interface{}, args ...interface{})

func Exit added in v1.6.7

func Exit(args ...interface{})

Compatibility with `log`

func Exitf added in v1.6.7

func Exitf(format string, args ...interface{})

Compatibility with `log`

func Fine added in v1.6.7

func Fine(arg0 interface{}, args ...interface{})

Utility for fine log messages (see Debug() for parameter explanation) Wrapper for (*Logger).Fine

func Finest added in v1.6.7

func Finest(arg0 interface{}, args ...interface{})

Utility for finest log messages (see Debug() for parameter explanation) Wrapper for (*Logger).Finest

func GetConfFile added in v1.7.5

func GetConfFile() *ini.File

func GetLevel added in v1.6.7

func GetLevel() string

func Info added in v1.6.7

func Info(arg0 interface{}, args ...interface{})

Utility for info log messages (see Debug() for parameter explanation) Wrapper for (*Logger).Info

func InfoT added in v1.6.7

func InfoT(tag string, arg0 interface{}, args ...interface{})

func Log added in v1.6.7

func Log(lvl dlog.Level, source, message string)

Send a log message manually Wrapper for (*Logger).Log

func Logc added in v1.6.7

func Logc(lvl dlog.Level, closure func() string)

Send a closure log message Wrapper for (*Logger).Logc

func Logf added in v1.6.7

func Logf(lvl dlog.Level, format string, args ...interface{})

Send a formatted log message easily Wrapper for (*Logger).Logf

func NewGrpcClient added in v1.7.0

func NewGrpcClient(target string, makeRawClient func(conn *grpc.ClientConn) (interface{}, error), serviceName string) *dgrpc.GrpcClient

func NewHttpClient added in v1.6.5

func NewHttpClient() *dhttp.HttpClient

func NewRpcClient added in v1.6.5

func NewRpcClient(timeout time.Duration, retryNum uint32) *dogrpc.RpcClient

timeout Millisecond

func SetConfPath added in v1.6.8

func SetConfPath(path string)

set conf path

func SetConfig added in v1.6.7

func SetConfig(name, key, value string)

set config

func SetLevel added in v1.6.7

func SetLevel(lvl int)

func Stderr added in v1.6.7

func Stderr(args ...interface{})

Compatibility with `log`

func Stderrf added in v1.6.7

func Stderrf(format string, args ...interface{})

Compatibility with `log`

func Stdout added in v1.6.7

func Stdout(args ...interface{})

Compatibility with `log`

func Stdoutf added in v1.6.7

func Stdoutf(format string, args ...interface{})

Compatibility with `log`

func Trace added in v1.6.7

func Trace(arg0 interface{}, args ...interface{})

Utility for trace log messages (see Debug() for parameter explanation) Wrapper for (*Logger).Trace

func TraceT added in v1.6.7

func TraceT(tag string, arg0 interface{}, args ...interface{})

func Warn added in v1.6.7

func Warn(arg0 interface{}, args ...interface{})

Utility for warn log messages (returns an error for easy function returns) (see Debug() for parameter explanation) These functions will execute a closure exactly once, to build the error message for the return Wrapper for (*Logger).Warn

func WarnT added in v1.6.7

func WarnT(tag string, arg0 interface{}, args ...interface{})

Types

type Engine

type Engine struct {
	HttpServer *dhttp.HttpServer
	RpcServer  *dogrpc.RpcServer
	GrpcServer *dgrpc.GrpcServer
}

func Default

func Default() *Engine

func (*Engine) Run

func (e *Engine) Run() error

Engine Run

func (*Engine) Signal

func (e *Engine) Signal()

Directories

Path Synopsis
databases
Package log4go provides level-based and highly configurable logging.
Package log4go provides level-based and highly configurable logging.
net
dgrpc/sample/helloworld
Package helloworld is a generated protocol buffer package.
Package helloworld is a generated protocol buffer package.
dhttp
Package HttpClient is a simplified http client.
Package HttpClient is a simplified http client.
runtime
gl
gr
* * Copyright 2020 gd Author.
* * Copyright 2020 gd Author.
pc
helloworld
Package helloworld is a generated protocol buffer package.
Package helloworld is a generated protocol buffer package.

Jump to

Keyboard shortcuts

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