AICon 上海站|90%日程已就绪,解锁Al未来! 了解详情
写点什么

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

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

币币交易APP系统开发费用(源码)

华为云GaussDB深耕数字化下半场,持续打造数据库根技术

华为云开发者联盟

Serverless 云原生 华为云 GaussDB 云数据库

存储大师班 | 浅谈数据保护之快照与备份

QingStor分布式存储

分布式存储 快照 备份

百度智能云大数据全景架构图如何赋能企业数字化

百度开发者中心

大数据 案例分享 行业创新

数字货币交易软件系统开发介绍(搭建)

Tensorflow Lite移动平台编译|Bazel实践

轻口味

人工智能 tensorflow ios android 10月月更

Python代码阅读(第41篇):矩阵转置

Felix

Python 编程 Code Programing 阅读代码

场外OTC交易软件系统开发介绍(源码)

技术分享| 音视频多频道使用的正确姿势

anyRTC开发者

音视频 WebRTC 实时通信 多频道

《世界质量报告》重磅发布,人工智能与机器学习成软件质量保证测试焦点

币币撮合交易软件系统开发(源码搭建)

英特尔联合阿里巴巴深化从云到端全面技术合作,加速数智中国创新发展

科技新消息

直播预告 | Apache APISIX × Apache SkyWalking 线上分享

API7.ai 技术团队

Apache Skywalking API网关 APISIX Meetup

FastDFS环境搭建

Fox666

fastdfs

数字货币交易所系统软件开发介绍(案例)

一文读懂「TTS语音合成技术」

澳鹏Appen

人工智能 语音 nlp 语音合成 TTS

全周期数据管控,为「快递大数据+」保驾护航

BinTools图尔兹

为金融场景而生的数据类型:Numeric

青云技术社区

postgresql 云计算 源码 云原生

Spinnaker:云原生多云环境持续部署的未来

博文视点Broadview

场外OTC交易系统APP开发(案例)

滚雪球学 Python 番外篇之游戏世界,游戏也有 Hello World

梦想橡皮擦

10月月更

助力建设智慧社区,EMQ 映云科技服务美好生活

EMQ映云科技

物联网 mqtt 智慧社区

边缘AI方案落地问题探讨

华为云开发者联盟

机器学习 AI 算法 边侧数据 边缘云

三级等保是不是icp?两者是一样吗?

行云管家

网络安全 等级保护 等保三级 三级等保

数字货币交易所系统软件开发介绍(源码)

带你掌握java反序列化漏洞及其检测

华为云开发者联盟

Java 安全 漏洞

主干开发你必须知道的7件事

华为云开发者联盟

产品 测试 团队 开发 主干开发

LeaRun.Java可视化流程简单配置过程

雯雯写代码

java

分布式文件系统FastDFS实战

Fox666

fastdfs 分布式文件系统

小红书“致歉滤镜景点”:种草社区的尺度在哪?

石头IT视角

一看就懂|焱融 SaaS 数据服务平台上手指南

焱融科技

云计算 技术 分布式 高性能 文件存储

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