/go-rpc

golang client server rpc based on messaging (kafka) using code generation

Primary LanguageGoApache License 2.0Apache-2.0

Go RPC (using messaging system)

Go library for RPC client/server based on messaging system (currently support only Kafka)

Test

Features include:

Running example

Server Example

package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"

	"github.com/pongsatt/go-rpc"
	"github.com/pongsatt/go-rpc/example"
	"github.com/pongsatt/go-rpc/messaging"
)

func main() {
	kafkaClient := messaging.NewCpKafkaClient(&messaging.CpKafkaConfig{
		Brokers: "localhost:9092",
	})

	requestReplyClient := rpc.NewRequestReplyClient("RealServer", kafkaClient, &rpc.RequestReplyConfig{})

	err := example.NewRealServerProvider(
		requestReplyClient, &example.RealServer{})
	if err != nil {
		panic(err)
	}
	fmt.Println("server started")

	termChan := make(chan os.Signal)
	signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM)

	<-termChan
	kafkaClient.Shutdown()
}

Start kafka server (using Readpanda for simplicity)

./start_servers.sh

Start server

go run example/server/*

Server output

go-rpc go run example/server/*
server started

Client Example

package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/pongsatt/go-rpc"
	"github.com/pongsatt/go-rpc/example"
	"github.com/pongsatt/go-rpc/messaging"
)

func main() {
	kafkaClient := messaging.NewCpKafkaClient(&messaging.CpKafkaConfig{
		Brokers: "localhost:9092",
	})

	timeout := 30 * time.Second
	requestReplyClient := rpc.NewRequestReplyClient("RealServer", kafkaClient, &rpc.RequestReplyConfig{
		Timeout: &timeout,
	})

	// interface -> proxy
	proxy := example.NewServerProxy(requestReplyClient)

	// execute normal code
	client := example.NewCleint(proxy)

	for i := 0; i < 100; i++ {
		start := time.Now()
		id, err := client.Create("test")
		fmt.Printf("time use %s\n", time.Since(start))

		if err != nil {
			fmt.Printf("error creating %v\n", err)
		} else {
			fmt.Printf("got id %s\n", id)
		}
	}

	termChan := make(chan os.Signal)
	signal.Notify(termChan, syscall.SIGINT, syscall.SIGTERM)

	<-termChan
	kafkaClient.Shutdown()
}

Run client

go run example/client/*

Client output

go-rpc go run example/client/*
time use 275.060096ms
got id Hi test

Code Generation

Server

//go:generate go run github.com/pongsatt/go-rpc/cmd/gen provider -name=RealServer

package example

// RealServer struct
type RealServer struct {
}

// NewRealServer creates new instance
func NewRealServer() *RealServer {
	return &RealServer{}
}

// GetID func
func (proxy *RealServer) GetID(seed string) (string, error) {
	return "Hi " + seed, nil
}

// Create order
func (proxy *RealServer) Create(order *Order) (string, error) {
	return "ok", nil
}

Client

//go:generate go run github.com/pongsatt/go-rpc/cmd/gen proxy

package example

// Server interface
type Server interface {
	GetID(seed string) (string, error)
	Create(order *Order) (string, error)
}

// Client struct
type Client struct {
	server Server
}

// NewCleint new instance
func NewCleint(server Server) *Client {
	return &Client{server}
}

// Create func
func (client *Client) Create(seed string) (string, error) {
	return client.server.GetID(seed)
}

Run go generate

go generate ./...

Output

generating proxy
writing file client_gen.go # proxy for Server interface
generate done
generating provider
writing file realserver_gen.go # run rpc server for RealServer struct
generate done