当前位置: 首页 > news >正文

跨语言RPC:使用Java客户端调用Go服务端的JSON-RPC服务

在分布式系统开发中,不同编程语言之间进行通信是一个常见的需求。通过远程过程调用(RPC)技术,我们可以让不同的程序像调用本地方法一样调用远程的服务。本文将介绍如何使用Go语言编写一个简单的JSON-RPC服务,并使用Java作为客户端来跨语言调用这个服务。

一、背景介绍

在之前的文章中,我们已经了解了如何使用Go语言构建一个基本的RPC服务。然而,默认情况下,Go语言的net/rpc包使用的是一种名为Gob的序列化格式,这限制了它只能与支持Gob编码的语言进行交互。为了实现跨语言的RPC调用,我们可以采用更通用的数据交换格式——如JSON。Go语言的net/rpc/jsonrpc包就提供了这样的功能,允许我们在不修改服务逻辑的情况下,轻松地与其他语言进行交互。

二、Go服务端实现

首先,我们需要创建一个Go服务端,该服务端将提供一个简单的“Hello”服务。以下是完整的代码示例:

package mainimport ("fmt""net""net/rpc""net/rpc/jsonrpc"
)// 定义一个服务结构体
type HelloService struct{}// 定义一个远程可调用的方法
func (s *HelloService) Hello(request string, reply *string) error {fmt.Printf("Received request: %s\n", request)*reply = "hello " + requestreturn nil
}func main() {// 监听本地 1234 端口listen, err := net.Listen("tcp", ":1234")if err != nil {panic(err)}defer listen.Close()// 注册服务err = rpc.RegisterName("HelloService", new(HelloService))if err != nil {panic(err)}// 接受连接并处理for {conn, err := listen.Accept()if err != nil {continue}go jsonrpc.ServeConn(conn)}
}

关键点解释:

  • 服务定义:我们定义了一个HelloService结构体,并为其添加了一个Hello方法。这个方法接收一个字符串参数,并返回一个经过处理后的字符串。
  • 注册服务:使用rpc.RegisterName函数将服务注册到RPC框架中,这里我们指定了服务名称为"HelloService"
  • 启动服务:监听指定端口并接受连接,然后使用jsonrpc.ServeConn来处理每一个新的连接。

代码解析

代码片段作用说明
type HelloService自定义的服务结构体,用于封装远程方法
func (s *HelloService) Hello(...)这是一个“导出方法”,可以被外部调用
net.Listen("tcp", ":1234")创建 TCP 监听器,监听本地 1234 端口
rpc.RegisterName("HelloService", ...)将服务注册为 RPC 框架的一部分,服务名是 "HelloService"
jsonrpc.ServeConn(conn)使用 JSON-RPC 协议处理每个连接,自动解析请求、调用方法并返回结果

✅ 总结:Go 服务端本质上是一个 TCP 服务器,使用 JSON-RPC 协议与客户端通信。客户端发送 JSON 请求,服务端执行对应方法后,返回 JSON 响应。

三、Java客户端实现

接下来,我们将编写一个Java客户端来调用上述Go服务端提供的“Hello”服务。以下是完整的Java代码示例:

import org.json.JSONObject;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;public class GoJsonRpcClient {
import org.json.JSONObject;import java.io.*;
import java.net.Socket;public class GoJsonRpcClient {public static void main(String[] args) throws IOException {String hostname = "127.0.0.1"; // Go服务端IP地址int port = 1234; // Go服务端监听端口try (Socket socket = new Socket(hostname, port)) {OutputStream output = socket.getOutputStream();PrintWriter writer = new PrintWriter(output, true);InputStream input = socket.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(input));JSONObject jsonRequest = new JSONObject();jsonRequest.put("jsonrpc", "2.0");jsonRequest.put("method", "HelloService.Hello");jsonRequest.put("params", new String[]{"Bob"});jsonRequest.put("id", 1);writer.println(jsonRequest.toString());String jsonResponse = reader.readLine();if (jsonResponse != null && !jsonResponse.isEmpty()) {JSONObject jsonObject = new JSONObject(jsonResponse);System.out.println("Received response: " + jsonObject.toString());if (jsonObject.has("result")) {System.out.println("Result: " + jsonObject.getString("result"));}} else {System.out.println("No response or empty response.");}} catch (IOException e) {throw new RuntimeException(e);}}
}public static void main(String[] args) {String hostname = "127.0.0.1"; // Go服务端IP地址int port = 1234; // Go服务端监听端口try (Socket socket = new Socket(hostname, port)) {PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));JSONObject jsonRequest = new JSONObject();jsonRequest.put("jsonrpc", "2.0");jsonRequest.put("method", "HelloService.Hello");jsonRequest.put("params", new String[]{"Bob"}); // 请求参数jsonRequest.put("id", 1); // 请求IDwriter.println(jsonRequest.toString());String jsonResponse = reader.readLine();if (jsonResponse != null && !jsonResponse.isEmpty()) {JSONObject jsonObject = new JSONObject(jsonResponse);System.out.println("Received response: " + jsonObject.toString());if (jsonObject.has("result")) {System.out.println("Result: " + jsonObject.getString("result"));}} else {System.out.println("No response or empty response.");}} catch (Exception e) {throw new RuntimeException(e);}}
}

关键点解释:

  • 请求构建:我们使用org.json.JSONObject来构造符合JSON-RPC规范的请求对象。在这个例子中,我们的请求包含了一个方法名(对应于Go服务端的Hello方法)、一组参数以及一个唯一的请求ID。
  • 发送请求:通过套接字连接向Go服务端发送构造好的请求。
  • 接收响应:从输入流中读取服务端返回的响应,并解析其中的结果字段。

代码解析

代码片段作用说明
Socket socket = new Socket(hostname, port)创建一个 TCP 连接到 Go 服务端
PrintWriter writer = new PrintWriter(output, true)获取输出流,用于向服务端发送请求
BufferedReader reader = new BufferedReader(...)获取输入流,用于接收服务端响应
JSONObject jsonRequest = new JSONObject()构造 JSON 请求对象
jsonRequest.put("method", "HelloService.Hello")设置要调用的服务方法
jsonRequest.put("params", new String[]{"Bob"})设置参数列表
writer.println(jsonRequest.toString())发送请求
String jsonResponse = reader.readLine()读取服务端返回的 JSON 响应
jsonObject.getString("result")提取返回值中的 result 字段

✅ 总结:Java 客户端通过 Socket 建立 TCP 连接,构造符合 JSON-RPC 规范的请求,发送给 Go 服务端,并等待响应。

四、测试与验证

确保Go服务端正在运行后,执行Java客户端程序。如果一切配置正确,你应该能够看到类似以下的输出结果:

Received response: {"jsonrpc":"2.0","result":"hello Bob","id":1}
Result: hello Bob

这表明Java客户端成功地调用了Go服务端的“Hello”方法,并收到了预期的响应。

五、总结

JSON-RPC 的核心思想

角色功能
服务端(Go)监听 TCP 端口,接收 JSON-RPC 请求,调用本地方法,返回 JSON-RPC 响应
客户端(Java)建立 TCP 连接,构造 JSON-RPC 请求,发送并读取响应
关键点使用 JSON 作为数据格式,TCP 作为传输层,实现跨语言通信

通过这篇文章,我们学习了如何使用Go语言构建一个JSON-RPC服务端,并使用Java作为客户端进行跨语言调用。这种方法不仅打破了语言之间的界限,还利用了JSON这种轻量级的数据交换格式,使得不同平台和语言之间的集成变得更加简单高效。

关于使用JSON-RPC替换RPC原本的序列化协议Gob的目的和优点可以看上一篇内容。

希望这篇博客能帮助你在实际项目中更好地应用RPC技术。

相关文章:

  • 性能测试|数据说话!在SimForge平台上用OpenRadioss进行汽车碰撞仿真,究竟多省时?
  • Leetcode-​713. 乘积小于 K 的子数组​
  • 45-Oracle 索引的新建与重建
  • phpstorm无缝切换vscode
  • Synopsys:Verification Continuum Platform介绍
  • python追加合并excel效率记录
  • 从C++编程入手设计模式——外观模式
  • C/C++中的位段(Bit-field)是什么?
  • [特殊字符]华为总部参观预约|企业通道揭秘
  • 《OpenAI Whisper模型深度研究报告:技术、应用与展望》
  • [驱动开发篇] SPI 驱动开发 - 原理解析篇
  • Vue-7-前端框架Vue之应用基础从Vue2语法到Vue3语法的演变
  • 神经体积记忆架构(NVM)-实现机械狗自主爬楼梯、跨缝隙、翻障碍
  • 《Whisper:OpenAI的先进语音识别模型》
  • Hadoop 版本进化论:从 1.0 到 2.0,架构革命全解析
  • 【Docker 07】Network - 网络
  • 博图SCL中WHILE语句的使用详解及案例
  • 探索KingbaseES在线体验平台:国产数据库新体验
  • 树 与 堆:从 数 据 结 构 基 础 到 算 法 实 践 的 全 面 解 析
  • 未来的随身AI IDC--AI手机
  • 怎么做网站板块/近10天的时事新闻
  • png图片可以做网站图标吗/网络营销策划案
  • 成都 网站改版/海外推广代理公司
  • 优化流程/温州seo结算
  • 洛阳霞光做网站/百度小说排行榜2021
  • 阿里巴巴1688全球采购批发平台/重庆镇海seo整站优化价格