First, you should install rpcx:

go get -u -v github.com/smallnest/rpcx/...

It only install the basic features of rpcx. If you want to use etcd, you should add etcd tag:

go get -u -v -tags "etcd" github.com/smallnest/rpcx/...

And if you want to use quic, you also need to add quic tag:

go get -u -v -tags "quic etcd" github.com/smallnest/rpcx/...

I recommend you to install all tags even though you won't use them so far:

go get -u -v -tags "reuseport quic kcp zookeeper etcd consul ping" github.com/smallnest/rpcx/...

tags means:

  • quic: support quic transport
  • kcp: support kcp transport
  • zookeeper: support zookeeper register
  • etcd: support etcd register
  • consul: support consul register
  • ping: support network quality load balancing
  • reuseport: support reuseport

Implement Service

You can write your service just like writing a plain Go struct:

import "context"

type Args struct {
    A int
    B int

type Reply struct {
    C int

type Arith int

func (t *Arith) Mul(ctx context.Context, args *Args, reply *Reply) error {
    reply.C = args.A * args.B
    return nil

Arith is a Go type and it has a one method Mul. The first parameter of Mul method is context.Context。 The second parameter of Mul method is args。 It contains request data: A and B。 The third parameter of Mul method is reply。It is a pointer to Reply. The Mul method returns an error (can be nil). Mul sets Reply.C with result of A * B.

Now you has defined one service Arith and implemented its Mul method. we will introduce how to explore it to server and how clients to call it in next steps.

Implement Server

You can use three lines to explore the above service:

    s := server.NewServer()
    s.RegisterName("Arith", new(Arith), "")
    s.Serve("tcp", ":8972")

You register your service with Name Arith

You can register service by the below:

s.Register(new(example.Arith), "")

It uses the service type name as service name.

Implement Client

    // #1
    d := client.NewPeer2PeerDiscovery("tcp@"+*addr, "")
    // #2
    xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, client.DefaultOption)
    defer xclient.Close()

    // #3
    args := &example.Args{
        A: 10,
        B: 20,

    // #4
    reply := &example.Reply{}

    // #5
    err := xclient.Call(context.Background(), "Mul", args, reply)
    if err != nil {
        log.Fatalf("failed to call: %v", err)

    log.Printf("%d * %d = %d", args.A, args.B, reply.C)

#1 defines a service discovery implementation. In this example we use the simplest discovery: Peer2PeerDiscovery. Client get the server address by accessing this discovery and connect the server directly.

#2 creates a XClient, and passes FailMode, SelectMode and default option. FailMode indicates the client how to handle call failures: retry, return fast or retry another server? SelectMode indicates the client how to select a server if there are multiple servers for one service.

#3 defines the request: we want to get result of 10 * 20. Of course we know the result must be 200 but we will see whether reply from the server is 200.

#4 defines the result object, it is a zero value and actually rpcx can use it to know type of the result and then unmarshal the result to it.

#5 call the remote service and gets the result synchronously。

Call the service asynchronously

You can call the service synchronously:

    d := client.NewPeer2PeerDiscovery("tcp@"+*addr2, "")
    xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, client.DefaultOption)
    defer xclient.Close()

    args := &example.Args{
        A: 10,
        B: 20,

    reply := &example.Reply{}
    call, err := xclient.Go(context.Background(), "Mul", args, reply, nil)
    if err != nil {
        log.Fatalf("failed to call: %v", err)

    replyCall := <-call.Done
    if replyCall.Error != nil {
        log.Fatalf("failed to call: %v", replyCall.Error)
    } else {
        log.Printf("%d * %d = %d", args.A, args.B, reply.C)

You must use xclient.Go to replace xclient.Call and ti returns a channel. You can read the result from the channel.

By smallnest            updated 2019-10-10 03:01:36

results matching ""

    No results matching ""