写点什么

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

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

一颗石榴给QA带来的启示

BY林子

软件测试 敏捷测试 测试工程师 敏捷QA

微服务与 API有什么区别?

雨果

微服务 数据api

设备端零改动迁移实战——实践类

阿里云AIoT

安全 物联网 开发工具 迁移 企业实例

Vue组件入门(三)插槽和动态组件

Augus

Vue 3 10月月更

DevOps 与 DataOps 相关吗?

雨果

DataOps

【实战】自定义 Github Action 库

小鑫同学

前端 Node 10月月更

Go 语言泛型编程之切片

宇宙之一粟

Go 泛型 泛型编程 10月月更

又一家!天数智芯天垓100 产品卡与龙蜥操作系统完成产品兼容互认证

OpenAnolis小助手

开源 适配 龙蜥操作系统 天数智芯 兼容

贤鱼的刷题日常--P1548 [NOIP1997 普及组] 棋盘问题

贤鱼很忙

c++ CSP 10月月更

走进“yarn create vite”的源码学习

小鑫同学

前端 Node 10月月更

2022 Java零基础必备 简单易学 Eclipse免费下载安装+JDK环境搭建一站式捆绑服务到底的教程 足够全、足够详细、足够劲爆 最关键可以一直让你免费使用!

Geek_yx5md7

eclipse 工具 开发工具 环境搭建 Java 开发

Java 序列化与反序列化

Yeats_Liao

后端 Java core 10月月更

数据质量监控,你一直都做错了

雨果

数据质量

2022-10-12:以下go语言代码输出什么?A:1;B:2;C:panic;D:不能编译。 package main import “fmt“ func main() { m := m

福大大架构师每日一题

golang 福大大 选择题

支撑阿里“双十一”的消息中间件,带你云淡风轻面对高并发

图灵社区

RocketMQ 中间件 架构师 消息中间件

贤鱼的刷题日常--P2671 [NOIP2015 普及组] 求和

贤鱼很忙

c++ 10月月更 题解

数字经济时代,企业应该如何搭建数字体验平台(DXP)?

Baklib

客户体验管理

同行四载,法大大携手SAP共筑数智未来

ToB行业头条

我决定以后一直使用Eclipse了 因为它也可以安装集成PyDec插件来实现Python开发了 哇哈哈哈

Geek_yx5md7

Python 开发环境搭建 eclipse+pyhton Python编译器 新手学编程

MySQL高级--性能优化查询截取分析

Java学术趴

10月月更

支撑阿里“双十一”的消息中间件,带你云淡风轻面对高并发

图灵教育

RocketMQ 中间件 架构师 消息中间件

io的实质

wzh

Linux 面试 后端 io java 编程

read、select、poll、epoll区别

wzh

网络 Linux Kenel epoll IO多路复用 poll

利用fs-extra实现"yarn create tlist"创建项目

小鑫同学

前端 Node 10月月更

【愚公系列】2022年10月 Go教学课程 026-结构体

愚公搬代码

10月月更

Java Lambda 表达式

Yeats_Liao

后端 Java core 10月月更

干货|什么是特性团队/功能团队(FeatureTeam)

laofo

Scrum 研发效能 PMO 敏捷精益 敏捷研发

这是我见过的,最好的工作流设计

跟YY哥学Jira

设计 Jira workflow

Spring Boot「04」Annotations 01

Samson

Java spring 学习笔记 spring-boot 10月月更

内网渗透-IPC$横向控制OA系统【网络安全】

网络安全学海

网络安全 信息安全 渗透测试 内网渗透 漏洞挖掘

cstdio的源码学习分析10-格式化输入输出函数fprintf整体分析

桑榆

源码刨析 10月月更 C++

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