50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

快速搭建 Go JSON-RPC Server

  • 2019-09-24
  • 本文字数:1828 字

    阅读完需:约 6 分钟

快速搭建Go JSON-RPC Server

jsonrpc 是无状态、轻量级的远程过程调用协议,传递数据格式为 JSON。GO 官方提供 rpc 包和 jsonrpc 包,与 rpc 包不同的是,jsonrpc 可以实现跨平台通信。本文将介绍如何用 Go 快速搭建一个 jsonrpc Server,用 PHP 实现 jsonrpc client 进行验证,同时也记录下验证过程中出现的坑。

实现 jsonrpc_server

引入包

1import (2    "net/rpc"3    "net"4    "log"5    "net/rpc/jsonrpc"6    "fmt"7)
复制代码

定义 server 端要伺服的 rpc method

 1// rpc handler 2type Edwin int  3// 定义rpc method 第一个参数是请求对象,第二参数是返回对象,返回值是返回rpc 内部调用过程中出现的错误信息 4func (this *Edwin) Add(args map[string]float64,res *float64) error  { 5    *res = args["num1"] + args["num2"] 6    return  nil 7} 8func (this *Edwin) Multi(args map[string]interface{},res *float64) error { 9    *res = args["num1"].(float64) * args["num2"].(float64)10    return nil11}
复制代码

注册 rpc handler,开启 server connection

 1    rpc.Register(new(Edwin)) 2 3    l,err := net.Listen("tcp",":11223") 4 5    if err!=nil{ 6        log.Fatalln("listen error:",err) 7    } 8 9    for{10        conn,err := l.Accept()1112        if err!= nil{13            log.Fatalln("accept failed:",err)14        }1516        fmt.Println("jsonrpc server  start lisen on 11223...")171819        go func(conn net.Conn) {20            fmt.Println("a new connection is coming...")21            jsonrpc.ServeConn(conn)22        }(conn)23    }
复制代码

php 实现 jsonrpc_client

 1class JsonRpc { 2    private $conn; 3 4    function __construct($host, $port) { 5        $this->conn = fsockopen($host, $port, $errno, $errStr, 2); 6 7    } 8 9    public function call($method, $params) {1011        $err = fwrite($this->conn, json_encode([12            'method' => $method,13            'params' => array($params),14            'id' => 1,15        ]));1617        if (empty($err)) {18            return false;19        }2021        stream_set_timeout($this->conn, 0, 300);2223        $line = fgets($this->conn);24        if ($line === false) {25            return NULL;26        }2728        fclose($this->conn);2930        return json_decode($line, true);31    }32}3334$client = new JsonRPC("127.0.0.1", 11223);35$client2 = new JsonRPC("127.0.0.1", 11223);36$ret = $client->Call("Edwin2.Multi", array("num1" => 14, "num2" => 20));37$ret2 = $client2->Call("Edwin2.Add", array("num1" => 14, "num2" => 20));38var_export($ret);39var_export($ret2);
复制代码

验证

 1# 开启 jsonrpc server 2go run jsonrpc_server.go 3# 正常会输出监听信息 4> jsonrpc server  start lisen on 11223... 5> a new connection is coming... 6# 执行 jsonrpc client 7php jsonrpc_clinent.php 8# 正常输出以下信息 9> array (10  'id' => 1,11  'result' => 280,12  'error' => NULL,13)array (14  'id' => 1,15  'result' => 34,16  'error' => NULL,17)
复制代码

验证中的问题

问题代码:


1$err = fwrite($this->conn, json_encode([2            'method' => $method,3            'params' => array($params),4            // 'params' => $params // 不能这么用5            'id' => 1,6        ]));
复制代码


params 参数必须用 array 包含,如果直接传递过去,将报出以下错误信息:


1array (2  'id' => 1,3  'result' => NULL,4  'error' => 'json: cannot unmarshal object into Go value of type [1]interface {}',5)
复制代码


根据 JSON-RPC 规范,参数 params 可以是 Json Array,也可以是 Json Object,可是为什么还报错呢?于是查看源码,发现:


1在 src/net/rpc/jsonrpc/server.go 第95行,go官方实现指定params必须是数组:2    var params [1]interface{}3    params[0] = x4    return json.Unmarshal(*c.req.Params, &params)5    ...
复制代码


通过这个坑发现,Go jsonrpc 并未严格按照 JSON-RPC 规范实现。

内部处理流程


作者介绍:


作者张大辉(企业代号名),目前负责贝壳找房 PHP、GO 方向研发工作。


本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。


原文链接:


https://mp.weixin.qq.com/s/k0cQ_kIs4FhfAz_ncctRBg


2019-09-24 18:152404

评论 1 条评论

发布
用户头像
Go 的 net/rpc/jsonrpc 只实现了 JSON-RPC 1.0 规范,在 JSON-RPC 1.0 规范中请求的 params 只能是 JSON Array。
https://stackoverflow.com/questions/24404108/json-rpc-parameters-version-1-0-vs-2-0
2021-02-23 10:04
回复
没有更多了
发现更多内容

开源新老兵携手打开社区大门,带大学生走近开源

DT极客

如何在 Spring/Spring Boot 中优雅地做参数校验?

JavaGuide

Java spring springboot

答对这八个Redis的问题,说明你精通了

AI乔治

Java redis 架构 分布式 高并发

京东首席架构师深邃洞察:服务化+云原生+微服务

Java架构师迁哥

一枚比特币变换一台车,特斯拉与比特币还要绑定多久?

CECBC

特斯拉

网络协议学习笔记 Day6

穿过生命散发芬芳

网络协议 4月日更

什么是低代码开发?低代码11大核心功能介绍!

优秀

低代码

聪明人的训练(二十七)

Changing Lin

4月日更

爆肝1W+字,通俗易懂的讲解下Java注解

AI乔治

Java 架构 面试 注解

MySQL主从不一致情形与解决方法

AI乔治

Java MySQL 架构 主从同步

MySQL高可用架构:mysql+keepalived实现

AI乔治

Java MySQL 架构 高可用架构 keepalive

收藏!阿里P9耗时28天,总结历年亿级活动高并发系统设计手册

Java架构师迁哥

工行首次全面展示数十项数字人民币研发试点成果

CECBC

数字人民币

电脑护眼不权威指南,年纪轻轻眼睛就不行了?

彭宏豪95

效率 windows 4月日更 护眼

你公司有没有企业文化?

石云升

团队建设 28天写作 职场经验 管理经验 4月日更

周转箱在仓配业务中的应用

Geek_vidmje

面试别慌!阿里专家带你从【入门+基础+进阶+项目】攻破SpringBoot

Java架构师迁哥

Github瞬间爆火!被各大厂要求直接下架的面试题库也太全了

Java 编程 程序员 架构 面试

别让心里的墙,挡住了你未来的路

小天同学

思考 认知提升 认知 4月日更

重装变态的微信

箭上有毒

生活记录 4月日更

ElasticSearch

云淡风轻

elasticsearch

深入浅出解读SpringMVC 进阶版

AI乔治

Java spring 架构 微服务 springmvc

强化区块链技术在数字政府、智慧城市、智能制造等领域应用

CECBC

人工智能

前端工程化-webpack

chun1123

大前端 webpack

Dubbo学习笔记

风翱

dubbo 4月日更

对于医疗健康行业,区块链最大的价值在哪里?

CECBC

医疗

架构师必经之路!Github榜首Java代码优化:77案例+28技巧开源分享

Java架构师迁哥

为打造更好移动生态:日活超1.2亿的百度知道,摊牌了

ToB行业头条

百度 百度知道

小技巧 | 帮助运营小姐姐批量修改文件名的几种方式

梁龙先森

Node 脚本 PowerShell

全面复盘B站面试时坑我最深的Java并发:JDK源码剖析

Java架构师迁哥

为什么区块链技术仍然被人们认为当成一个投机的工具?

CECBC

快速搭建Go JSON-RPC Server_文化 & 方法_张大辉_InfoQ精选文章