Home

Awesome

rpc

PkgGoDev Build Status codecov Go Report Card LICENSE

Package rpc implements a remote procedure call over TCP, UNIX, HTTP and WS. The rpc improves throughput and reduces latency. Up to 4 times faster than net/rpc.

Feature

Comparison to other packages

Packagenetrpcjsonrpcrpcgrpcrpcx
Epoll/KqueueNoNoYesNoNo
MultiplexingYesYesYesYesYes
PipeliningNoNoYesNoNo
Auto BatchingNoNoYesNoNo
TransportNoNoYesNoNo

Benchmark

Low Concurrency

<img src="https://raw.githubusercontent.com/hslam/rpc-benchmark/master/rpc-bar-qps.png" width = "400" height = "300" alt="rpc" align=center><img src="https://raw.githubusercontent.com/hslam/rpc-benchmark/master/rpc-bar-p99.png" width = "400" height = "300" alt="rpc" align=center>

High Concurrency

<img src="https://raw.githubusercontent.com/hslam/rpc-benchmark/master/rpc-curve-qps.png" width = "400" height = "300" alt="rpc" align=center><img src="https://raw.githubusercontent.com/hslam/rpc-benchmark/master/rpc-curve-p99.png" width = "400" height = "300" alt="rpc" align=center>

Get started

Install

go get github.com/hslam/rpc

Import

import "github.com/hslam/rpc"

Usage

Examples

arith.proto

syntax = "proto3";
package service;

message ArithRequest {
    int32 a = 1;
    int32 b = 2;
}

message ArithResponse {
    int32 pro = 1;
}

GoGo Protobuf

protoc ./arith.proto --gogofaster_out=./

arith.go

package service

type Arith struct{}

func (a *Arith) Multiply(req *ArithRequest, res *ArithResponse) error {
	res.Pro = req.A * req.B
	return nil
}

server.go

package main

import (
	"github.com/hslam/rpc"
	"github.com/hslam/rpc/examples/codec/pb/service"
)

func main() {
	rpc.Register(new(service.Arith))
	rpc.Listen("tcp", ":9999", "pb")
}

conn.go

package main

import (
	"fmt"
	"github.com/hslam/rpc"
	"github.com/hslam/rpc/examples/codec/pb/service"
)

func main() {
	conn, err := rpc.Dial("tcp", ":9999", "pb")
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	req := &service.ArithRequest{A: 9, B: 2}
	var res service.ArithResponse
	if err = conn.Call("Arith.Multiply", req, &res); err != nil {
		panic(err)
	}
	fmt.Printf("%d * %d = %d\n", req.A, req.B, res.Pro)
}

transport.go

package main

import (
	"fmt"
	"github.com/hslam/rpc"
	"github.com/hslam/rpc/examples/codec/pb/service"
)

func main() {
	trans := &rpc.Transport{
		MaxConnsPerHost:     1,
		MaxIdleConnsPerHost: 1,
		Options:             &rpc.Options{Network: "tcp", Codec: "pb"},
	}
	defer trans.Close()
	req := &service.ArithRequest{A: 9, B: 2}
	var res service.ArithResponse
	if err := trans.Call(":9999", "Arith.Multiply", req, &res); err != nil {
		panic(err)
	}
	fmt.Printf("%d * %d = %d\n", req.A, req.B, res.Pro)
}

client.go

package main

import (
	"fmt"
	"github.com/hslam/rpc"
	"github.com/hslam/rpc/examples/codec/pb/service"
)

func main() {
	opts := &rpc.Options{Network: "tcp", Codec: "pb"}
	client := rpc.NewClient(opts, ":9997", ":9998", ":9999")
	client.Scheduling = rpc.LeastTimeScheduling
	defer client.Close()
	req := &service.ArithRequest{A: 9, B: 2}
	var res service.ArithResponse
	if err := client.Call("Arith.Multiply", req, &res); err != nil {
		panic(err)
	}
	fmt.Printf("%d * %d = %d\n", req.A, req.B, res.Pro)
}

context.go

package main

import (
	"context"
	"fmt"
	"github.com/hslam/rpc"
	"github.com/hslam/rpc/examples/codec/pb/service"
	"time"
)

func main() {
	conn, err := rpc.Dial("tcp", ":9999", "pb")
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	req := &service.ArithRequest{A: 9, B: 2}
	var res service.ArithResponse
	emptyCtx := context.Background()
	valueCtx := context.WithValue(emptyCtx, rpc.BufferContextKey, make([]byte, 64))
	ctx, cancel := context.WithTimeout(valueCtx, time.Minute)
	defer cancel()
	err = conn.CallWithContext(ctx, "Arith.Multiply", req, &res)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%d * %d = %d\n", req.A, req.B, res.Pro)
}

Output

9 * 2 = 18

License

This package is licensed under a MIT license (Copyright (c) 2019 Meng Huang)

Author

rpc was written by Meng Huang.