写点什么

快速搭建 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:152363

评论 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
回复
没有更多了
发现更多内容

华为云开源 | 线下meetup • 中国人民大学站

华为云开源

云原生 时序数据库 AI大模型 Meetup 华为云开源

支付宝小程序云托管, 1 分钟即可完成支付宝开放产品服务端部署

TRaaS

支付宝小程序 代码云托管

龙蜥社区第 21 次运营委员会圆满结束!

OpenAnolis小助手

开源 操作系统 龙蜥社区 运营委员会

企业软件定制开发有哪些优势?|app小程序网站搭建

Geek_16d138

小程序开发 定制软件开发 app定制开发

情感语音识别:现状、挑战与解决方案

数据堂

GeminiDB新特性:让Redis广告频控爱不释手的exHASH

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟

软件测试/测试开发/人工智能丨赋值运算符

测试人

人工智能 软件测试

互动LED电子大屏幕成为商显市场的头牌

Dylan

人脸识别 3D vr LED显示屏 AR、

软件测试/人工智能丨长春工业大学“火焰杯”软件测试赛喜获佳绩

测试人

人工智能 软件测试

全套赛事系统支持:和鲸祝贺粤港澳大湾区这项算法大赛圆满收官!

ModelWhale

人工智能 数据分析 算法赛 大学生竞赛 广州黄埔

EMQX ECP 2.0 产品发布会回顾:工业互联数据平台助力工业数字化转型

新消费日报

在游戏开发中,实时渲染和离线渲染对于游戏平衡的影响有哪些?

Finovy Cloud

云计算 游戏 渲染 云渲染 云游戏

基于YOLO模型建筑工地个人防护设备目标检测

3D建模设计

机器学习 目标检测 虚幻合成数据生成

Dapp开发

区块链技术

赛桨在结构领域全新探索:机理驱动的无网格结构拓扑优化

飞桨PaddlePaddle

飞桨 AI for Science

CodeWhisperer 体验总结

亚马逊云科技 (Amazon Web Services)

人工智能 云上探索实验室 Amazon CodeWhisperer

华为云WebAssembly代码静态符号执行技术实现新突破

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟

三大基础方案和AI出海计划重磅发布!加速盘古大模型生态发展

华为云开发者联盟

华为云 华为云开发者联盟 华为云盘古大模型 华为云AI出海计划

常见的JAVA四大开源规则引擎简介

小狗围观科幻

3D 纹理渲染如何帮助设计师有效、清晰地表达设计理念

3D建模设计

人工智能 3D渲染 材质 纹理

机器学习之危险品车辆目标检测

3D建模设计

人工智能 机器学习 合成数据生成 YOLO模型

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