博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Golang-RPC(二):golang中的rpc实现之json-rpc
阅读量:3985 次
发布时间:2019-05-24

本文共 2834 字,大约阅读时间需要 9 分钟。

因为内置net/rpc包接口设计的缺陷,通过追踪 rpc.HandleHTTP() 方法,找到 ServeHTTP 方法:

func (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if req.Method != "CONNECT" {
w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.WriteHeader(http.StatusMethodNotAllowed) io.WriteString(w, "405 must CONNECT\n") return } conn, _, err := w.(http.Hijacker).Hijack() if err != nil {
log.Print("rpc hijacking ", req.RemoteAddr, ": ", err.Error()) return } io.WriteString(conn, "HTTP/1.0 "+connected+"\n\n") server.ServeConn(conn)}func (server *Server) ServeConn(conn io.ReadWriteCloser) {
buf := bufio.NewWriter(conn) srv := &gobServerCodec{
rwc: conn, dec: gob.NewDecoder(conn), enc: gob.NewEncoder(buf), encBuf: buf, } server.ServeCodec(srv)}

根本就没有设置codec的参数,直接写死了 gob ,所以依赖于 net/rpc 包的除了 gob 之外的编码方式都只能使用 tcp 协议。

我们无法使用jsonrpc等定制的编码作为rpc.DialHTTP的底层协议,如果需要让jsonrpc支持rpc.DialHTTP函数,需要调整rpc的接口。

除了传输协议,还有可以指定一个RPC编码协议,用于编码/解码RPC调用的函数参数和返回值,RPC调用不指定编码协议时,默认采用Go语言特有的gob编码协议。

因为,, 其他语言一般都不支持Go语言的gob协议,因此如果需要跨语言RPC调用就需要采用通用的编码协议。

Go的标准库还提供了一个"net/rpc/jsonrpc"包,用于提供基于JSON编码的RPC支持。

JSON RPC采用JSON进行数据编解码,因而支持跨语言调用。但目前的jsonrpc库是基于tcp协议实现的,暂时不支持使用http进行数据传输。

定义服务

package repoimport (	"errors")type Order struct {
}type OrderInfo struct {
Id string Price float64 Status int}func (o *Order) GetOne(orderId string, orderInfo *OrderInfo) error {
if orderId == "" {
return errors.New("orderId is invalid") } *orderInfo = OrderInfo{
Id: orderId, Price: 100.00, Status: 1, } return nil}

服务端

package mainimport (	"log"	"net"	"net/rpc"	"net/rpc/jsonrpc"	"demo1/go-rpc/repo")func main() {
err := rpc.Register(new(repo.Order)) if err != nil {
log.Fatal(err) } l, err := net.Listen("tcp", ":8100") if err != nil {
log.Fatal(err) } for {
conn, e := l.Accept() if e != nil {
continue } go jsonrpc.ServeConn(conn) }}

客户端

package mainimport (	"fmt"	"log"	"net/rpc/jsonrpc"	"demo1/go-rpc/repo")func main() {
client, err := jsonrpc.Dial("tcp", "127.0.0.1:8100") if err != nil {
log.Fatal("dialing:", err) } orderId := "asddddddd" var orderInfo repo.OrderInfo err = client.Call("Order.GetOne", orderId, &orderInfo) if err != nil {
log.Fatal("Order error:", err) } fmt.Println(orderInfo)}

jsonrpc 中的协议说明

使用tcp工具连接测试

1、请求参数列表

id		int 	编号,默认是0method	string	要调用的方法params			参数,数组或者是map,如果参数是单个的值应转换成数组。

例如

{
"method":"Order.GetOne","params":["asddddddd"],"id":0}{
"method":"Order.GetOne","params":{
"A":9,"B":2},"id":0}

2、响应参数

id		int		编号,默认是0result			结果error	string	错误信息

如果成功,返回结果:

{
"id":0,"result":{
"Id":"asddddddd","Price":100,"Status":1},"error":null}

如果失败,返回结果:

{
"id":0,"result":null,"error":"rpc: can't find service Arith.Multiply"}{
"id":0,"result":null,"error":"json: cannot unmarshal string into Go value of type [1]interface {}"}

转载地址:http://ojaui.baihongyu.com/

你可能感兴趣的文章
在C++中使用Lua
查看>>
在Dll中调用自身的位图资源
查看>>
IP校验和详解
查看>>
C++中使用Mongo执行count和distinct运算
查看>>
一些socket的编程经验
查看>>
socket编程中select的使用
查看>>
C++获取文件大小常用技巧分享
查看>>
未来5年大机遇:做贩卖多巴胺的超级玩家
查看>>
30 岁之前,应当学会哪些技能?
查看>>
关于AIS编码解码的两个小问题
查看>>
GitHub 万星推荐:黑客成长技术清单
查看>>
可以在线C++编译的工具站点
查看>>
关于无人驾驶的过去、现在以及未来,看这篇文章就够了!
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
Web开发之路
查看>>
昨夜今晨最大八卦终于坐实——人类首次直接探测到了引力波
查看>>
年纪轻轻记忆力就衰退得厉害,我还有救吗?
查看>>
如何优雅、机智地和新公司谈薪水?
查看>>
为什么读了很多书,却学不到什么东西?
查看>>
长文干货:如何轻松应对工作中最棘手的13种场景?
查看>>