Go微服务:基于net/rpc模块实现微服务远程调用

基于RPC协议实现微服务

  • 基于rpc实现跨语言调用,不限定服务提供方使用的语言
  • 在微服务架构中,每个微服务都被封装成了进程,相互独立
  • 在这里提供了客户端和服务端演示调用示例

1 )服务端

  • 新建 server/msg 目录,后执行 $ go mod init msg

  • 编辑 server/msg/main.go 文件

    go 复制代码
    package main
    
    // net 模块是go内置模块
    import (
    	"fmt"
    	"net"
    	"net/rpc"
    )
    
    // 定义一个可供远程调用的struct
    type Msg struct {}
    
    // 为Msg这个struct添加被调用函数 GetReplay
    func (this Msg) GetReplay(req string, res *string) error {
    	fmt.Println(req) // 服务端输出日志:请求参数
    	*res = "这是服务端返回的信息:已收到客户端的请求参数,参数为:" + req // 这是返回信息
    	return nil
    }
    
    func main() {
    	// 1. 注册RPC服务
    	err1 := rpc.RegisterName("msg", new(Msg))
    	// 错误处理
    	if err1 != nil {
    		fmt.Println(err1)
    	}
    	// 2、监听端口
    	listener, err2 := net.Listen("tcp", "127.0.0.1:3000")
    	if err2 != nil {
    		fmt.Println(err2)
    	}
    	// 3、应用退出的时候关闭监听端口
    	defer listener.Close()
    	for {
    		// 4、建立链接
    		conn, err3 := listener.Accept()
    		// 错误处理
    		if err3 != nil {
    			fmt.Println(err3)
    		}
    		fmt.Print("客户端参数为: ");
    		// 5. 绑定服务
    		rpc.ServeConn(conn)
    	}
    }
  • net包是一个 go 内置的一个模块

  • 准备调用函数 Msg.GetReplay

    • 此方法只能有两个可序列化的参数,注意第二个参数是指针类型
      • req 表示获取客户端传过来的数据
      • res 表示给客户端返回数据 (指针类型)
    • 方法要返回一个 error 类型,同时必须是公开的方法
    • req 和 res的类型不能是 channel(通道)、func(函数)
    • 因为它们均不能进行序列化
  • 整个流程如下:

    • 1 )通过 rpc.RegisterName 注册 rpc 服务,注意这里的 name 后期被客户端调用
    • 2 )通过 net.Listen 监听rpc服务,得到 listener 对象
    • 3 )通过 defer listener.Close() 应用退出时关闭监听端口
    • 4 )基于无限循环做响应处理,这里有两个环节
      • 4.1 )通过 listener.Accept() 接收连接信息,得到 conn 连接对象
      • 4.2 )通过 rpc.ServeConn(conn) 绑定服务

3 )客户端

  • 新建 client 目录,后执行 $ go mod init client

  • 这里在 client 项目目录中,新建一个 main.go 文件

  • 编辑 client/main.go 文件

    go 复制代码
    package main
    
    import (
    	"fmt"
    	"net/rpc"
    )
    
    func main() {
    	// 1. 用 rpc.Dial和rpc微服务端建立连接
    	conn, err1 := rpc.Dial("tcp", "127.0.0.1:3000")
    	// 错误处理
    	if err1 != nil {
    		fmt.Println(err1)
    	}
    	// 2、当客户端退出的时候关闭连接
    	defer conn.Close()
    	// 3. 调用远程函数
    	var reply string
    	err2 := conn.Call("msg.GetReplay", "滴滴滴", &reply)
    	// 错误处理
    	if err2 != nil {
    		fmt.Println(err2)
    	}
    	// 4、获取微服务返回的数据
    	fmt.Println(reply)
    }
  • 这里是客户端,需要经过以下几个步骤:

  • 1 )要连接的话,首先要建立连接 rpc.Dial 得到 conn 连接对象

  • 2 )添加客户端退出时的关闭连接处理 defer conn.Close()

  • 3 )基于 conn.Call 调用远程函数

    • 第一个参数,服务名.远程方法 的字符串形式
    • 第二个参数,给服务端的参数
    • 第三个参数,服务端返回的数据地址

3 )部署服务

  • 先启动服务端,再启动客户端
  • 当服务端启动的瞬间
    • 服务端接收到客户端的参数打印到服务端
    • 客户端接收到服务端的返回信息

注意

  • 在Golang中实现RPC非常简单,有封装好的官方库和一些第三方库提供支持
  • Go RPC 可以利用tcp或http来传递数据,可以对要传递的数据使用多种类型的编解码方式
  • Golang 官方的 net/rpc 库使用 encoding/gob 进行编解码,支持tcp或http数据传输方式
  • 由于其他语言不支持 gob 编解码方式,所以使用 net/rpc 库实现的 RPC 方法没办法进行跨语言调用
  • 另外,Golang官方还提供了 net/rpc/jsonrpc 库实现RPC方法,JSON RPC采用JSON进行数据编解码
  • 因而支持跨语言调用,但目前的 jsonrpc 库是基于tcp协议实现的,暂时不支持使用http进行数据传输
  • 除了Golang官方提供的rpc库,还有许多第三方库为在 Golang 中实现RPC提供支持
  • 大部分第三方 RPC 库的实现都是使用 protobuf 进行数据编解码
  • 根据 protobuf 声明文件自动生成 RPC 方法定义与服务注册代码
  • 在 Golang 中可以很方便的进行 RPC 服务调用
相关推荐
fanly1111 小时前
surging 发布命令行工具
微服务·surging
stark张宇8 天前
微服务架构必备:Gin + gRPC + Consul + Nacos + GORM 打造用户服务
微服务·gin·grpc
阿里云云原生11 天前
MSE Nacos Prompt 管理:让 AI Agent 的核心配置真正可治理
微服务·云原生
阿里云云原生11 天前
阿里云微服务引擎 MSE 及 API 网关 2026 年 1 月产品动态
微服务
花酒锄作田11 天前
Gin 框架中的规范响应格式设计与实现
golang·gin
麦聪聊数据12 天前
统一 Web SQL 平台如何收编企业内部的“野生数据看板”?
数据库·sql·低代码·微服务·架构
qwfys20012 天前
How to install golang 1.26.0 to Ubuntu 24.04
ubuntu·golang·install
云司科技codebuddy12 天前
技术支持过硬Trae核心代理
大数据·运维·python·微服务
codeejun12 天前
每日一Go-25、Go语言进阶:深入并发模式1
开发语言·后端·golang
递归尽头是星辰12 天前
微服务事务分级治理:从 Seata 全模式到 TDSQL 实战
微服务·云原生·架构·分布式事务·事务分级治理