go原生rpc调用封装

实现目标

  • 原生rpc使用是直接写死方法名进行调用, 但实际中我们使用其实是想像调用本地方法一样直接调用的
  • 以下我们就参考grpc的大致流程对go原生rpc进行一定的封装: grpc的大致流程主要分为, 客户端, 客户端stub(类似于代理), 服务端, 服务端stub, socket通信

原生rpc写法和我们要实现的目标写法

// 原生rpc调用方式, 使用call方法进行写死调用
var reply string
_ = dial.Call("HelloService.Hello", "rpc2", &reply)
fmt.Println(reply)
// 要实现的目标调用, 直接调用hello
if err := hello.Hello("rpc", &reply); err != nil {
	fmt.Println(err)
}

client和server公共部分

// 增加handler/handler.go HelloService名称
package handler

var HelloServiceName = "handler/HelloService"

客户端实现

  • 客户端代理部分
  • 增加client_stub/client.sub.go 实现一个client 调用的代理
package client_stub

import (
	"net/rpc"
	"new_helloword/handler"
)

type HelloServiceStub struct {
	*rpc.Client
}

func NewHelloServiceStub(network, address string) *HelloServiceStub {
	dial, err := rpc.Dial(network, address)
	if err != nil {
		panic(err)
	}
	return &HelloServiceStub{
		dial,
	}
}

func (s *HelloServiceStub) Hello(request string, reply *string) (err error) {
	// 调用原方法
	err = s.Call(handler.HelloServiceName+".Hello", request, reply)
	return
}
  • 客户端调用部分
func main() {
	helloStub := client_stub.NewHelloServiceStub("tcp", "127.0.0.1:1234")
	var reply string
	if err := helloStub.Hello("rpc", &reply); err != nil {
		fmt.Println(err)
	}

	fmt.Println(reply)
}

服务端实现

  • handler/handler.go 增加helloService 实现逻辑
type HelloService struct {
}

func (receiver *HelloService) Hello(arg string, reply *string) error {
	*reply = "hello " + arg
	return nil
}

  • 增加服务端stub, server_stub/server_sub.go ,并定义接口进行解耦 (因为调用的实际是方法, 跟哪个无关)
type HelloServicer interface {
	Hello(arg string, reply *string) error
}

// 使用接口进行解耦
func RegisterHelloService(rcvr HelloServicer) {
	// 注册rpc
	_ = rpc.RegisterName(handler.HelloServiceName, rcvr)
}

-服务端注册service

func main() {
	// 创建一个server实例
	listen, _ := net.Listen("tcp", ":1234")
	// 注册rpc服务
	server_stub.RegisterHelloService(&handler.HelloService{})
	// 启动server
	for {
		accept, _ := listen.Accept()
		go rpc.ServeConn(accept) // 进入的链接让rpc来执行
	}
}
  • 拓展, 目前封装的stub都是我们自己写的, 实际使用过程中这些代码应该是自动生成的,且可以生成多种语言的代码, 可参考grpc

你可能感兴趣的:(golang,golang,rpc,后端)