飞天发布时刻:2024年 Forrester 公有云平台Wave™评估报告解读 了解详情
写点什么

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

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

基于 MelosBoom ,捕获 DePIN 赛道发展红利

石头财经

PPT AI生成软件有哪些?10款顶级的AI合成PPT工具推荐!

彭宏豪95

人工智能 效率工具 PPT AIGC AI生成PPT

《龙蜥理事说》第三期对话中兴通讯 探索下一代新型算力和智能化技术

OpenAnolis小助手

AI 操作系统 龙蜥社区 中兴通讯 龙蜥理事说

客户在哪儿AI生产的企业全历史行为数据是ToB大客户营销的最佳抓手

客户在哪儿AI

ToB营销 ToB获客 ToB增长 大客户营销

如何根据淘宝买家秀API返回值优化商品详情页

技术冰糖葫芦

API Explorer api 货币化 API 文档

开个技术外挂|用技术轻松实现GPU显卡冷却风扇噪声控制

Altair RapidMiner

gpu 仿真 显卡 GPU实例 altair

全链路追踪 & 性能监控,GO 应用可观测全面升级

阿里巴巴云原生

阿里云 云原生 可观测

DataCanvas Alaya九章元识大模型通过北京市生成式人工智能服务备案

九章云极DataCanvas

基于Java+SpringBoot+Vue前后端分离常规应急物资管理系统设计和实现

hunter_coder

后端开发

基于 MelosBoom ,捕获 DePIN 赛道发展红利

BlockChain先知

龙蜥社区第五届理事大会圆满结束!深度探讨 AI 浪潮下的合作模式

OpenAnolis小助手

AI 操作系统 龙蜥社区 CentOS迁移 龙蜥理事大会

Java & Go 定时任务

FunTester

基于Java+SpringBoot+Vue前后端分离宠物商城网站设计和实现

hunter_coder

后端开发

基于Java+SpringBoot+Vue前后端分离成绩管理系统设计和实现

hunter_coder

后端开发

基于Java+SpringBoot+Vue前后端分离餐饮管理系统设计和实现

hunter_coder

后端开发

基于Java+SpringBoot+vue前后端分离宠物领养系统设计实现

hunter_coder

后端开发

基于Java+SpringBoot+Vue前后端分离车辆管理系统设计和实现

hunter_coder

后端开发

基于Java+SpringBoot+vue前后端分离城镇保障性住房管理系统设计实现

hunter_coder

后端开发

基于Java+SpringBoot+vue前后端分离大学城水电管理系统设计实现

hunter_coder

后端开发

ToB企业市场部四分之三的工作都需要企业全历史行为数据的支持

客户在哪儿AI

ToB营销 活动营销 ToB增长 大客户营销

全面解析淘宝商品详情API的SKU信息

技术冰糖葫芦

API Explorer API 编排 api 货币化 API 文档 pinduoduo API

聚焦创新巅峰 | 5000台Gather G-BOX矿机于7月23日全面上线

股市老人

华为云Serverless可观测性解决方案打造高效、可靠的云原生应用

华为云PaaS服务小智

Serverless 华为云

基于Java+SpringBoot+Vue前后端分离餐厅管理系统设计和实现

hunter_coder

后端开发

基于Java+SpringBoot+vue前后端分离厨艺交流平台设计实现

hunter_coder

后端开发

基于Java+SpringBoot+vue前后端分离大型商场应急预案管理系统设计实现

hunter_coder

后端开发

一个典型的性能分析案例

老张

性能测试 需求分析 云存储 TOS

参与OpenTiny征文活动,赢取500元开发者大礼包!

OpenTiny社区

开源 前端 低代码 组件库 TinyVue

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