实现 RPC 客户端 Node.js 并写入服务器

Implement RPC client Node.js with server written

我使用 Go 实现了 RPC 服务器。现在,我想使用 Node.js 编写客户端,如何从 Node.js 客户端向 Go 服务器进行 RPC 调用。

这是用 Go 编写的服务器代码。

server.go

package main

type HelloService struct{}

func (p *HelloService) Hello(request string, reply *string) error {
    *reply = "Hello " + request
    return nil
}

func main() {
    rpc.RegisterName("HelloService", new(HelloService))

    // run rpc on port 1234
    listener, err := net.Listen("tcp", ":1234")

    if err != nil {
        log.Fatal("ListenTCP error: ", err)
    }

    // use for-while for serve client
    for {
        conn, err := listener.Accept()
        log.Println("New connection: ", conn)

        if err != nil {
            log.Fatal("Accept error: ", err)
        }

        go rpc.ServeConn(conn)
    }
}
 

net/rpc package uses encoding/gob作为默认的连线格式。这是一种 Go 特定的二进制序列化格式,它很高效,但在实践中,仅在 Go 应用程序之间进行通信时才有用。

但是,net/rpc 支持使用不同的编解码器来(反)序列化数据,并且 net/rpc/jsonrpc 包提供了一个 JSON-RPC 1.0 兼容编解码器实现。

这是一个使用它的例子,还有一个使用 jayson 包的 Node.js 客户端(没什么特别的,只是我偶然发现的第一个支持 JSON -RPC 1.0):

server.go

package main

import (
        "log"
        "net"
        "net/rpc"
        "net/rpc/jsonrpc"
)

type HelloService struct{}

func (p *HelloService) Hello(request string, reply *string) error {
        *reply = "Hello " + request
        return nil
}

func main() {
        rpc.RegisterName("HelloService", new(HelloService))
        listener, err := net.Listen("tcp", ":1234")
        if err != nil {
                log.Fatal("ListenTCP error: ", err)
        }
        for {
                conn, err := listener.Accept()
                if err != nil {
                        log.Fatal("Accept error: ", err)
                }
                log.Printf("New connection: %+v\n", conn.RemoteAddr())
                go jsonrpc.ServeConn(conn)
        }
}

client.js

const jayson = require("jayson");

const client = jayson.client.tcp({
        host: "172.17.0.2",
        port: "1234",
        version: 1,
});

client.request("HelloService.Hello", ["chuckx"], (err, response) => {
        if (err) throw err;
        if (response.error) throw response.error;
        console.log("response:", response.result);
});

输出

服务器
$ go run server.go
2021/03/12 06:46:21 New connection: 172.17.0.3:51016
客户
$ node client.js
response: Hello chuckx

请注意,net/rpc 包不再接受新功能,因此您最好使用 gRPC 之类的东西以获得更多功能和更好的跨语言兼容性。