go语言之rpc支持json

标准库的RPC默认采用Go语言特有的gob编码,因此从其它语言调用Go语言实现的RPC服务将比较困难。在互联网的微服务时代,每个RPC以及服务的使用者都可能采用不同的编程语言,因此跨语言是互联网时代RPC的一个首要条件。得益于RPC的框架设计,Go语言的RPC其实也是很容易实现跨语言支持的。

Go语言的RPC框架有两个比较有特色的设计:一个是RPC数据打包时可以通过插件实现自定义的编码和解码;另一个是RPC建立在抽象的io.ReadWriteCloser接口之上的,我们可以将RPC架设在不同的通讯协议之上。这里我们将尝试通过官方自带的net/rpc/jsonrpc扩展实现一个跨语言的PPC。

1、服务端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main
 
import (
    "net"
    "net/rpc"
    "net/rpc/jsonrpc"
)
 
type HelloService struct {}
 
func (s *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 {
        panic("启动错误")
    }
    for {
        conn, err := listener.Accept()
        if err != nil {
            panic("接收")
        }
        go rpc.ServeCodec(jsonrpc.NewServerCodec(conn))
    }
}

  代码中最大的变化是用rpc.ServeCodec函数替代了rpc.ServeConn函数,传入的参数是针对服务端的json编解码器。

2、客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
 
import (
    "fmt"
    "net"
    "net/rpc"
    "net/rpc/jsonrpc"
)
 
func main(){
    conn, err := net.Dial("tcp", "localhost:1234")
    if err != nil {
        panic("连接错误")
    }
    client := rpc.NewClientWithCodec(jsonrpc.NewClientCodec(conn))
    var reply string
    err = client.Call("HelloService.Hello", "imooc", &reply)
    if err != nil {
        panic("调用错误")
    }
    fmt.Println(reply)
}

3、python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import json
import socket
import itertools
import time
 
 
class JSONClient(object):
 
    def __init__(self, addr):
        self.socket = socket.create_connection(addr)
        self.id_counter = itertools.count()
 
    def __del__(self):
        self.socket.close()
 
    def call(self, name, *params):
        request = dict(id=next(self.id_counter),
                    params=list(params),
                    method=name)
        self.socket.sendall(json.dumps(request).encode())
 
        # This must loop if resp is bigger than 4K
        response = self.socket.recv(4096)
        response = json.loads(response.decode())
 
        if response.get('id') != request.get('id'):
            raise Exception("expected id=%s, received id=%s: %s"
                            %(request.get('id'), response.get('id'),
                              response.get('error')))
 
        if response.get('error') is not None:
            raise Exception(response.get('error'))
 
        return response.get('result')
 
def close(self):
    self._socket.close()
 
 
if __name__ == '__main__':
    rpc = JSONClient(("localhost", 1234))
    args = "hello"
    print(rpc.call("HelloService.Hello", args))

  

posted @   ☞@_@  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
点击右上角即可分享
微信分享提示