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 nil
11}
注册 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()
11
12 if err!= nil{
13 log.Fatalln("accept failed:",err)
14 }
15
16 fmt.Println("jsonrpc server start lisen on 11223...")
17
18
19 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) {
10
11 $err = fwrite($this->conn, json_encode([
12 'method' => $method,
13 'params' => array($params),
14 'id' => 1,
15 ]));
16
17 if (empty($err)) {
18 return false;
19 }
20
21 stream_set_timeout($this->conn, 0, 300);
22
23 $line = fgets($this->conn);
24 if ($line === false) {
25 return NULL;
26 }
27
28 fclose($this->conn);
29
30 return json_decode($line, true);
31 }
32}
33
34$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] = x
4 return json.Unmarshal(*c.req.Params, ¶ms)
5 ...
通过这个坑发现,Go jsonrpc 并未严格按照 JSON-RPC 规范实现。
内部处理流程
作者介绍:
作者张大辉(企业代号名),目前负责贝壳找房 PHP、GO 方向研发工作。
本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。
原文链接:
https://mp.weixin.qq.com/s/k0cQ_kIs4FhfAz_ncctRBg
更多内容推荐
音视频同步!RTCP 协议解析及代码实现
RTCP 是实时控制协议(Real-Time Control Protocol)的缩写。RTCP 由 RFC 3550 定义(取代作废的 RFC 1889)。
2021-09-27
HTTP 认证
通过HTTP请求头来提供认证信息,而不是通过表单登录。有HTTP Basic authentication HTTP Digest authentication
2022-07-08
中科星图正式加入 openGauss 社区
8月29日,中科星图签署CLA(Contribution License Agreement, 贡献许可协议),正式加入openGauss 社区。
2022-10-08
zookeeper- 集群和 zab 协议
zookeeper-集群和zab协议
2022-07-19
SLO(服务等级目标)与 SLA(服务等级协议)
SLO和SLA是大家常见的两个名词:服务等级目标和服务等级协议。
2021-08-07
Go 专栏|流程控制,一网打尽
原文链接: Go 专栏|流程控制,一网打尽
2021-09-02
【愚公系列】2022 年 10 月 Go 教学课程 036- 类型断言
GO中的类型断言用于检查接口类型变量所持有的值是否实现了期望的接口或者具体的类型。
2022-10-22
34|WebSocket:如何在消息队列内核中支持 WebSocket?
WebSocket 是一种实时协议,它在单个 TCP 连接上提供持久的全双工通信。
2023-09-06
新手 Gopher 如何写出更健壮的 Go 代码
这篇文章总结如何写出更健壮的 Go 代码,不是讨论规范,而是讨论如何写出更符合预期的少 bug 的代码。
2021-10-19
加餐|GPT 编程(下) :如何利用 OpenAI 的 API 解决语言处理类任务?
如何利用OpenAI的API解决语言处理类任务?
2023-05-15
34|服务注册与监听:Worker 节点与 etcd 交互
这节课,让我们将Worker节点变为一个支持GRPC与HTTP协议访问的服务,让它最终可以被Master服务和外部服务直接访问。
2022-12-27
4. RPC 协议设计:响应编解码、重构代码与 error 处理
2023-09-27
Sevlet 规范:HttpServlet 类 和 HttpServletRequest 接口 源码解析
什么是协议?
2023-07-14
GO 学习之路 -2.GO 开发环境搭建
正所谓:工欲善其事,必先利其器。 开发之前要搭建好开发环境,以及实现高效编程的IDEA,本文就介绍一下GO开发环境和代码编辑器的配置
2022-11-30
5、Future 和 FutureTask
2023-09-26
数据同步 gossip 协议原理与应用场景介绍
Gossip是一种p2p的分布式协议。它的核心是在去中心化结构下,通过将信息部分传递,达到全集群的状态信息传播,传播的时间收敛在O(Log(N))以内,其中N是节点的数量。基于gossip协议,可以构建出状态一致的各种解决方案。
2023-02-10
在线 JSON 转 typescript 工具
在线JSON转typescript工具
2021-09-15
音视频传输协议众多, 5G 时代不同业务应该如何选择?
摘要:音视频传输协议众多, 不同业务应该如何选择? RTSP、RTMP、RTP/RTC、HLS、MSS、DASH、WEBRTC、RIST、SRT;在此我们就从业务发展的视角来理解各种流媒体协议,帮助大家有更加清晰的理解,选择时做出更理性的判断。
2021-01-29
go-zero docker-compose 搭建课件服务(二):编写 courseware rpc 服务
go-zero docker-compose 搭建课件服务(二):编写courseware rpc服务
2022-10-19
9.Nacos Server 处理注册流程
2023-09-29
推荐阅读
02|初出茅庐:构造一个极简的 HttpServer
2023-12-11
使用 Go 构建高性能的命令行工具
2023-12-01
Ubuntu 20.04 安装 VNC Server 的教程。
2023-08-15
打造企业级门户,WorkPlus 助您打造个性化与高效的企业通讯平台
2023-10-31
03|动态 Response:按照规范构造返回流
2023-12-13
21|Web 开发(上):如何使用 Axum 框架进行 Web 后端开发?
2023-12-11
区块链数字货币交易所开发方案,交易平台搭建
2023-09-27
电子书
大厂实战PPT下载
换一换 张深深 | 任意门科技(Soul) 效率产品负责人
王昭 | 美团 优选测试部工具链组负责人
张亮 | SphereEx CEO
评论 1 条评论