Home

Awesome

eRPC

tag Go Version GoDoc Build Status Go report License

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

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

简体中文

eRPC-Framework

Install

GO111MODULE=on go get -u -v -insecure github.com/andeya/erpc/v7
import "github.com/andeya/erpc/v7"

Feature

Benchmark

Self Test

client concurrencymean(ms)median(ms)max(ms)min(ms)throughput(TPS)
1001016075505
50091197052192
10001924187050040
20003954409042551
5000961281148046367
client concurrencymean(ms)median(ms)max(ms)min(ms)throughput(TPS)
10000140225682
50021240212630
100043510180733
200086640183351
500021186510133886

Comparison Test

<table> <tr><th>Environment</th><th>Throughputs</th><th>Mean Latency</th><th>P99 Latency</th></tr> <tr> <td width="10%"><img src="https://github.com/andeya/rpc-benchmark/raw/master/result/env.png"></td> <td width="30%"><img src="https://github.com/andeya/rpc-benchmark/raw/master/result/throughput.png"></td> <td width="30%"><img src="https://github.com/andeya/rpc-benchmark/raw/master/result/mean_latency.png"></td> <td width="30%"><img src="https://github.com/andeya/rpc-benchmark/raw/master/result/p99_latency.png"></td> </tr> </table>

More Detail

erpc_socket_profile_torch

svg file

erpc_socket_heap_torch

svg file

Example

server.go

package main

import (
	"fmt"
	"time"

	"github.com/andeya/erpc/v7"
)

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 handler
type Math struct {
	erpc.CallCtx
}

// Add handles addition request
func (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 main

import (
  "time"

  "github.com/andeya/erpc/v7"
)

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", "andeya"),
  ).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 handler
type Push struct {
  erpc.PushCtx
}

// Push handles '/push/status' message
func (p *Push) Status(arg *string) *erpc.Status {
  erpc.Printf("%s", *arg)
  return nil
}

More Examples

Usage

NOTE:

Peer(server or client) Demo

// Start a server
var peer1 = erpc.NewPeer(erpc.PeerConfig{
ListenPort: 9090, // for server role
})
peer1.Listen()

...

// Start a client
var 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 *<T>) (<T>, *erpc.Status) {
    ...
    return r, nil
}
// register the call route
// HTTP mapping: /aaa/xx_zz
// RPC mapping: Aaa.XxZz
peer.RouteCall(new(Aaa))

// or register the call route
// HTTP mapping: /xx_zz
// RPC mapping: XxZz
peer.RouteCallFunc((*Aaa).XxZz)

Service method mapping

Call-Function API template

func XxZz(ctx erpc.CallCtx, arg *<T>) (<T>, *erpc.Status) {
    ...
    return r, nil
}
// register the call route
// HTTP mapping: /xx_zz
// RPC mapping: XxZz
peer.RouteCallFunc(XxZz)

Push-Struct API template

type Bbb struct {
    erpc.PushCtx
}
func (b *Bbb) YyZz(arg *<T>) *erpc.Status {
    ...
    return nil
}
// register the push handler
// HTTP mapping: /bbb/yy_zz
// RPC mapping: Bbb.YyZz
peer.RoutePush(new(Bbb))

// or register the push handler
// HTTP mapping: /yy_zz
// RPC mapping: YyZz
peer.RoutePushFunc((*Bbb).YyZz)

Push-Function API template

// YyZz register the handler
func YyZz(ctx erpc.PushCtx, arg *<T>) *erpc.Status {
    ...
    return nil
}
// register the push handler
// HTTP mapping: /yy_zz
// RPC mapping: YyZz
peer.RoutePushFunc(YyZz)

Unknown-Call-Function API template

func XxxUnknownCall (ctx erpc.UnknownCallCtx) (interface{}, *erpc.Status) {
    ...
    return r, nil
}
// register the unknown call route: /*
peer.SetUnknownCall(XxxUnknownCall)

Unknown-Push-Function API template

func XxxUnknownPush(ctx erpc.UnknownPushCtx) *erpc.Status {
    ...
    return nil
}
// 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 group
group := peer.SubRoute("test")
// register to test group
group.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

Extensions

Codec

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

Plugin

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

Protocol

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

Transfer-Filter

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

Mixer

packageimportdescription
multiclient"github.com/andeya/erpc/v7/mixer/multiclient"Higher throughput client connection pool when transferring large messages (such as downloading files)
websocket"github.com/andeya/erpc/v7/mixer/websocket"Makes the eRPC framework compatible with websocket protocol as specified in RFC 6455
evio"github.com/andeya/erpc/v7/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

<a href="http://www.xiaoenai.com"><img src="https://raw.githubusercontent.com/andeya/imgs-repo/master/xiaoenai.png" height="50" alt="深圳市梦之舵信息技术有限公司"/></a>    <a href="https://tech.pingan.com/index.html"><img src="http://pa-tech.hirede.com/templates/pa-tech/Images/logo.png" height="50" alt="平安科技"/></a> <br/> <a href="http://www.fun.tv"><img src="http://static.funshion.com/open/static/img/logo.gif" height="70" alt="北京风行在线技术有限公司"/></a>    <a href="http://www.kejishidai.cn"><img src="http://simg.ktvms.com/picture/logo.png" height="70" alt="北京可即时代网络公司"/></a> <a href="https://www.kuaishou.com/"><img src="https://inews.gtimg.com/newsapp_bt/0/4400789257/1000" height="70" alt="快手短视频平台"/></a>

License

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