写点什么

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

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

Yii2.0 RESTful API 认证教程

Middleware

php RESTful Yii2

JVM最佳学习笔记<三>---虚拟机性能监控与故障处理工具

Loubobooo

Java JVM

[JVM] String#intern 面试必会

猴哥一一 cium

Java JVM string pool string Java 25 周年

最长回文算法(马拉车算法)分析

Gadzan

Java 算法 LeetCode

介绍一下自研开源NLP工具库---MYNLP

陈吉米

自然语言处理 中文分词 mynlp nlp

2020年全球经济萎缩,飞链热交易所逆袭而来闪耀数字经济

极客编

Yii2.0 RESTful API 之速率限制

Middleware

php RESTful Yii2

简述 HTTP 缓存相关的首部及其行为

黄耗子皮

缓存 HTTP

Yii2.0 RESTful API 基础配置教程

Middleware

php RESTful Yii2

一周信创舆情观察(5.18~5.24)

统小信uos

基础软件 操作系统

七年老程序员面试经历

代码诗人

JVM最佳学习笔记<二>---垃圾收集器与内存分配策略

Loubobooo

Java JVM

ESP8266远程控制+MicroPython 固件初体验

黄耗子皮

物联网 esp8266

Yii2.0 RESTful API 之版本控制

Middleware

php RESTful Yii2

JVM最佳学习笔记<四>---虚拟机类加载机制

Loubobooo

Java JVM

如何用五步建设数据中台?

博文视点Broadview

大数据 数据中台 架构 中台

钱从哪里来 - 中国家庭的财富方案

石云升

读书笔记 工作 财富 买房 资产配置

运维与云

yann [扬] :曹同学

JVM最佳学习笔记---总览

Loubobooo

Java JVM

RocketMQ broker.properties

李绍俊

RocketMQ

技术工作的一二三之内功

拖地先生

个人成长

OAM v1alpha2 新版:平衡标准与可扩展性

孙健波

运维那点事 - jenkins流水线

yann [扬] :曹同学

JVM最佳学习笔记<一>---Java内存区域与内存溢出异常

Loubobooo

Java JVM

DevOps知识点——3C知多少

禅道项目管理

DevOps 测试 持续集成

Python 沙盒环境配置

黄耗子皮

技术工作的一二三之快餐

拖地先生

项目管理 软件开发 技术管理 软件开发流程

技术工作的一二三之价值观方法论

拖地先生

个人成长 方法论

如何成为高手: 到知识的源头去

lmymirror

学习 方法论 高手

将footer固定在底部: Flexbox vs Grid

寇云

CSS css3

到底谁是你老板

Neco.W

工作 创业心态

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