Teleport 一个 Golang TCP Socket 的全新框架

网友投稿 1004 2022-10-23

Teleport 一个 Golang TCP Socket 的全新框架

Teleport 一个 Golang TCP Socket 的全新框架

eRPC is an efficient, extensible and easy-to-use RPC framework.

Suitable for RPC, Microservice, Peer-to-Peer, IM, Game and other fields.

简体中文

Install

go vesion ≥ 1.11 install

GO111MODULE=on go get -u -v -insecure github.com/henrylee2cn/erpc/v6

import

import "github.com/henrylee2cn/erpc/v6"

Feature

Use peer to provide the same API package for the server and clientProvide multi-layout abstractions such as: peersession/socketrouterhandle/contextmessageprotocolcodectransfer filterplugin Support reboot and shutdown gracefullyHTTP-compatible message format: Composed of two parts, the Header and the BodyHeader contains metadata in the same format as HTTP headerBody supports for custom codec of Content Type-Like, already implemented: ProtobufThriftjsONXMLFormPlain Support push, call-reply and more message types Support custom message protocol, and provide some common implementations: rawproto - Default high performance binary protocoljsonproto - JSON message protocolpbproto - Ptotobuf message protocolthriftproto - Thrift message protocolhttproto - HTTP message protocol Optimized high performance transport layer Use Non-block socket and I/O multiplexing technologySupport setting the size of socket I/O bufferSupport setting the size of the reading message (if exceed disconnect it)Support controling the connection file descriptor Support a variety of network types: tcptcp4tcp6unixunixpacketkcpquicother websocketevio Provide a rich plug-in point, and already implemented: authbinderheartbeatignorecase(service method)overloaderproxy(for unknown service method)secure Powerful and flexible logging system: Detailed log information, support print input and output detailsSupport setting slow operation alarm thresholdSupport for custom implementation log component Client session support automatically redials after disconnection

Benchmark

Self Test

A server and a client process, running on the same machine CPU: Intel Xeon E312xx (Sandy Bridge) 16 cores 2.53GHz Memory: 16G OS: Linux 2.6.32-696.16.1.el6.centos.plus.x86_64, CentOS 6.4 Go: 1.9.2 Message size: 581 bytes Message codec: protobuf Sent total 1000000 messages erpc

client concurrencymean(ms)median(ms)max(ms)min(ms)throughput(TPS)
1001016075505
50091197052192
10001924187050040
20003954409042551
5000961281148046367

erpc/socket

client concurrencymean(ms)median(ms)max(ms)min(ms)throughput(TPS)
10000140225682
50021240212630
100043510180733
200086640183351
500021186510133886

Comparison Test

More Detail

Profile torch of erpc/socket

svg file

Heap torch of erpc/socket

svg file

Example

server.go

package mainimport ( "fmt" "time" "github.com/henrylee2cn/erpc/v6")func main() { defer erpc.FlushLogger() // graceful go erpc.GraceSignal() // server peer srv := erpc.NewPeer(erpc.PeerConfig{ CountTime: true, ListenPort: 9090, PrintDetail: true, }) // srv.SetTLSConfig(erpc.GenerateTLSConfigForServer()) // router srv.RouteCall(new(Math)) // broadcast per 5s go func() { for { time.Sleep(time.Second * 5) srv.RangeSession(func(sess erpc.Session) bool { sess.Push( "/push/status", fmt.Sprintf("this is a broadcast, server time: %v", time.Now()), ) return true }) } }() // listen and serve srv.ListenAndServe()}// Math handlertype Math struct { erpc.CallCtx}// Add handles addition requestfunc (m *Math) Add(arg *[]int) (int, *erpc.Status) { // test meta erpc.Infof("author: %s", m.PeekMeta("author")) // add var r int for _, a := range *arg { r += a } // response return r, nil}

client.go

package mainimport ( "time" "github.com/henrylee2cn/erpc/v6")func main() { defer erpc.SetLoggerLevel("ERROR")() cli := erpc.NewPeer(erpc.PeerConfig{}) defer cli.Close() // cli.SetTLSConfig(&tls.Config{InsecureSkipVerify: true}) cli.RoutePush(new(Push)) sess, stat := cli.Dial(":9090") if !stat.OK() { erpc.Fatalf("%v", stat) } var result int stat = sess.Call("/math/add", []int{1, 2, 3, 4, 5}, &result, erpc.WithAddMeta("author", "henrylee2cn"), ).Status() if !stat.OK() { erpc.Fatalf("%v", stat) } erpc.Printf("result: %d", result) erpc.Printf("Wait 10 seconds to receive the push...") time.Sleep(time.Second * 10)}// Push push handlertype Push struct { erpc.PushCtx}// Push handles '/push/status' messagefunc (p *Push) Status(arg *string) *erpc.Status { erpc.Printf("%s", *arg) return nil}

More Examples

Usage

Peer(server or client) Demo

// Start a servervar peer1 = erpc.NewPeer(erpc.PeerConfig{ ListenPort: 9090, // for server role})peer1.Listen()...// Start a clientvar peer2 = erpc.NewPeer(erpc.PeerConfig{})var sess, err = peer2.Dial("127.0.0.1:8080")

Call-Struct API template

type Aaa struct { erpc.CallCtx}func (x *Aaa) XxZz(arg *) (, *erpc.Status) { ... return r, nil}

register it to root router:

// register the call route// HTTP mapping: /aaa/xx_zz// RPC mapping: Aaa.XxZzpeer.RouteCall(new(Aaa))// or register the call route// HTTP mapping: /xx_zz// RPC mapping: XxZzpeer.RouteCallFunc((*Aaa).XxZz)

Service method mapping

The default mapping(HTTPServiceMethodMapper) of struct(func) name to service methods:AaBb -> /aa_bbABcXYz -> /abc_xyzAa__Bb -> /aa_bbaa__bb -> /aa_bbABC__XYZ -> /abc_xyzAa_Bb -> /aa/bbaa_bb -> /aa/bbABC_XYZ -> /abc/xyzerpc.SetServiceMethodMapper(erpc.HTTPServiceMethodMapper) The mapping(RPCServiceMethodMapper) of struct(func) name to service methods:AaBb -> AaBbABcXYz -> ABcXYzAa__Bb -> Aa_Bbaa__bb -> aa_bbABC__XYZ -> ABC_XYZAa_Bb -> Aa.Bbaa_bb -> aa.bbABC_XYZ -> ABC.XYZerpc.SetServiceMethodMapper(erpc.RPCServiceMethodMapper)

Call-Function API template

func XxZz(ctx erpc.CallCtx, arg *) (, *erpc.Status) { ... return r, nil}

register it to root router:

// register the call route// HTTP mapping: /xx_zz// RPC mapping: XxZzpeer.RouteCallFunc(XxZz)

Push-Struct API template

type Bbb struct { erpc.PushCtx}func (b *Bbb) YyZz(arg *) *erpc.Status { ... return nil}

register it to root router:

// register the push handler// HTTP mapping: /bbb/yy_zz// RPC mapping: Bbb.YyZzpeer.RoutePush(new(Bbb))// or register the push handler// HTTP mapping: /yy_zz// RPC mapping: YyZzpeer.RoutePushFunc((*Bbb).YyZz)

Push-Function API template

// YyZz register the handlerfunc YyZz(ctx erpc.PushCtx, arg *) *erpc.Status { ... return nil}

register it to root router:

// register the push handler// HTTP mapping: /yy_zz// RPC mapping: YyZzpeer.RoutePushFunc(YyZz)

Unknown-Call-Function API template

func XxxUnknownCall (ctx erpc.UnknownCallCtx) (interface{}, *erpc.Status) { ... return r, nil}

register it to root router:

// register the unknown call route: /*peer.SetUnknownCall(XxxUnknownCall)

Unknown-Push-Function API template

func XxxUnknownPush(ctx erpc.UnknownPushCtx) *erpc.Status { ... return nil}

register it to root router:

// register the unknown push route: /*peer.SetUnknownPush(XxxUnknownPush)

Plugin Demo

// NewIgnoreCase Returns a ignoreCase plugin.func NewIgnoreCase() *ignoreCase { return &ignoreCase{}}type ignoreCase struct{}var ( _ erpc.PostReadCallHeaderPlugin = new(ignoreCase) _ erpc.PostReadPushHeaderPlugin = new(ignoreCase))func (i *ignoreCase) Name() string { return "ignoreCase"}func (i *ignoreCase) PostReadCallHeader(ctx erpc.ReadCtx) *erpc.Status { // Dynamic transformation path is lowercase ctx.UriObject().Path = strings.ToLower(ctx.UriObject().Path) return nil}func (i *ignoreCase) PostReadPushHeader(ctx erpc.ReadCtx) *erpc.Status { // Dynamic transformation path is lowercase ctx.UriObject().Path = strings.ToLower(ctx.UriObject().Path) return nil}

Register above handler and plugin

// add router groupgroup := peer.SubRoute("test")// register to test groupgroup.RouteCall(new(Aaa), NewIgnoreCase())peer.RouteCallFunc(XxZz, NewIgnoreCase())group.RoutePush(new(Bbb))peer.RoutePushFunc(YyZz)peer.SetUnknownCall(XxxUnknownCall)peer.SetUnknownPush(XxxUnknownPush)

Config

type PeerConfig struct { Network string `yaml:"network" ini:"network" comment:"Network; tcp, tcp4, tcp6, unix, unixpacket, kcp or quic"` LocalIP string `yaml:"local_ip" ini:"local_ip" comment:"Local IP"` ListenPort uint16 `yaml:"listen_port" ini:"listen_port" comment:"Listen port; for server role"` DialTimeout time.Duration `yaml:"dial_timeout" ini:"dial_timeout" comment:"Default maximum duration for dialing; for client role; ns,µs,ms,s,m,h"` RedialTimes int32 `yaml:"redial_times" ini:"redial_times" comment:"The maximum times of attempts to redial, after the connection has been unexpectedly broken; Unlimited when <0; for client role"` RedialInterval time.Duration `yaml:"redial_interval" ini:"redial_interval" comment:"Interval of redialing each time, default 100ms; for client role; ns,µs,ms,s,m,h"` DefaultBodyCodec string `yaml:"default_body_codec" ini:"default_body_codec" comment:"Default body codec type id"` DefaultSessionAge time.Duration `yaml:"default_session_age" ini:"default_session_age" comment:"Default session max age, if less than or equal to 0, no time limit; ns,µs,ms,s,m,h"` DefaultContextAge time.Duration `yaml:"default_context_age" ini:"default_context_age" comment:"Default CALL or PUSH context max age, if less than or equal to 0, no time limit; ns,µs,ms,s,m,h"` SlowCometDuration time.Duration `yaml:"slow_comet_duration" ini:"slow_comet_duration" comment:"Slow operation alarm threshold; ns,µs,ms,s ..."` PrintDetail bool `yaml:"print_detail" ini:"print_detail" comment:"Is print body and metadata or not"` CountTime bool `yaml:"count_time" ini:"count_time" comment:"Is count cost time or not"`}

Optimize

SetMessageSizeLimit sets max message size. If maxSize<=0, set it to max uint32.func SetMessageSizeLimit(maxMessageSize uint32) SetSocketKeepAlive sets whether the operating system should send keepalive messages on the connection.func SetSocketKeepAlive(keepalive bool) SetSocketKeepAlivePeriod sets period between keep alives.func SetSocketKeepAlivePeriod(d time.Duration) SetSocketNoDelay controls whether the operating system should delay message transmission in hopes of sending fewer messages (Nagle's algorithm). The default is true (no delay), meaning that data is sent as soon as possible after a Write.func SetSocketNoDelay(_noDelay bool) SetSocketReadBuffer sets the size of the operating system's receive buffer associated with the connection.func SetSocketReadBuffer(bytes int) SetSocketWriteBuffer sets the size of the operating system's transmit buffer associated with the connection.func SetSocketWriteBuffer(bytes int)

Extensions

Codec

packageimportdescription
json"github.com/henrylee2cn/erpc/v6/codec"JSON codec(erpc own)
protobuf"github.com/henrylee2cn/erpc/v6/codec"Protobuf codec(erpc own)
thrift"github.com/henrylee2cn/erpc/v6/codec"Form(url encode) codec(erpc own)
xml"github.com/henrylee2cn/erpc/v6/codec"Form(url encode) codec(erpc own)
plain"github.com/henrylee2cn/erpc/v6/codec"Plain text codec(erpc own)
form"github.com/henrylee2cn/erpc/v6/codec"Form(url encode) codec(erpc own)

Plugin

packageimportdescription
auth"github.com/henrylee2cn/erpc/v6/plugin/auth"An auth plugin for verifying peer at the first time
binder"github.com/henrylee2cn/erpc/v6/plugin/binder"Parameter Binding Verification for Struct Handler
heartbeat"github.com/henrylee2cn/erpc/v6/plugin/heartbeat"A generic timing heartbeat plugin
proxy"github.com/henrylee2cn/erpc/v6/plugin/proxy"A proxy plugin for handling unknown calling or pushing
secure"github.com/henrylee2cn/erpc/v6/plugin/secure"Encrypting/decrypting the message body
overloader"github.com/henrylee2cn/erpc/v6/plugin/overloader"A plugin to protect erpc from overload

Protocol

packageimportdescription
rawproto"github.com/henrylee2cn/erpc/v6/proto/rawprotoA fast socket communication protocol(erpc default protocol)
jsonproto"github.com/henrylee2cn/erpc/v6/proto/jsonproto"A JSON socket communication protocol
pbproto"github.com/henrylee2cn/erpc/v6/proto/pbproto"A Protobuf socket communication protocol
thriftproto"github.com/henrylee2cn/erpc/v6/proto/thriftproto"A Thrift communication protocol
httproto"github.com/henrylee2cn/erpc/v6/proto/httproto"A HTTP style socket communication protocol

Transfer-Filter

packageimportdescription
gzip"github.com/henrylee2cn/erpc/v6/xfer/gzip"Gzip(erpc own)
md5"github.com/henrylee2cn/erpc/v6/xfer/md5"Provides a integrity check transfer filter

Mixer

packageimportdescription
multiclient"github.com/henrylee2cn/erpc/v6/mixer/multiclient"Higher throughput client connection pool when transferring large messages (such as downloading files)
websocket"github.com/henrylee2cn/erpc/v6/mixer/websocket"Makes the eRPC framework compatible with websocket protocol as specified in RFC 6455
evio"github.com/henrylee2cn/erpc/v6/mixer/evio"A fast event-loop networking framework that uses the erpc API layer
htmlhtml "github.com/xiaoenai/tp-micro/helper/mod-html"HTML render for http client

Projects based on eRPC

projectdescription
TP-MicroTP-Micro is a simple, powerful micro service framework based on eRPC
PholcusPholcus is a distributed, high concurrency and powerful web crawler software

Business Users

License

eRPC is under Apache v2 License. See the LICENSE file for the full license text

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:ReentrantReadWriteLock读写锁和票据锁StempedLock
下一篇:SpringMVC源码解析-doDispatch方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~