gin框架 RPC服务

RPC架构:

简单了解了微服务定义和优缺点之后,在我们正式学习微服务框架之前,需要首先了解一下RPC架 构。通过RPC我们可以形象了解微服务的工作流程。

3.1 RPC的概念

RPC(Remote Procedure Call Protocol),是远程过程调用的缩写,通俗的说就是调用远处的一个 函数。与之相对应的是本地函数调用,我们先来看一- 下本地函数调用。当我们写下如下代码的时候: 规则

result := Add(1,2)

我们知道,我们传入了1, 2两个参数,调用了本地代码中的一个Add函数,得到result这个返回值。这 时参数,返回值,代码段都在个进程空间内,这是本地函数调用。 那有没有办法,我们能够调用一个跨进程(所以叫"远程",典型的事例,这个进程部署在另- -台服务器 上)的函数呢?

RPC:远程进通信-一应用层协议 (http协议同层)。底层使用TCP实现。 在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服务调用。

以下是一个Helloworld:

1、创建一个项目继续构建rpc 服务端:

package main

import (
	"fmt"
	"net"
	"net/rpc"
)

type Hello struct {
}

/*
1、方法只能有两个可序列化的参数,其中第二个参数是指针类型
	req表示获取客户端传过来的数据
	res表示给客户端返回数据
2、方法要返回一个error类型,同时必须是公开的方法。
3、req和res的类型不能是: channel (通道)、func (函数)均不能进行序列化
*/

func (this Hello) SayHello(req string, res *string) error {
	fmt.Println(req, "=======================.")
	*res = req + "你好"
	return nil
}

func main() {

	//注册RPC服务
	err := rpc.RegisterName("hello", new(Hello))  //注册服务 进行创建 一个Hello结构题对象

	if err != nil {
		fmt.Print(err)
	}

	//监听端口
	listen, err := net.Listen("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println(err)
	}

	//3、应用退出的时候关闭监听端口
	defer listen.Close()

	//放入for循环中使值一直处于建立连接中
	for {

		fmt.Println("开始建立连接")
		//4、建立连接
		accept, err := listen.Accept()

		if err != nil {
			fmt.Println(err)
		}
		//5、绑定服务
		rpc.ServeConn(accept)
	}
    
}

2、之后再创建一个项目 构建客户端进行访问:

package main

import (
	"fmt"
	"net/rpc"
)

func main() {

	//1、使用rpc.Dial 和rpc微服务建立远程连接
	dial, err := rpc.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Print(err)
	}

	//2、当客户端退出的时候关闭连接
	defer dial.Close()

	//调用远程函数
	var reply string
	/**
	第一个参数表示 我们的远程服务,名称加上要调用的方法名,
	第二个参数表示的就是我们传递过去的数据,
	第三个参数表示我们接收到的值
	*/
    //注意: hello 是我们rpc也买进行注册的服务名称
	err = dial.Call("hello.SayHello", "我是客户端", &reply)
	if err != nil {
		fmt.Println(err)
	}

	//获取返回连接
	fmt.Println(reply)

}

猜你喜欢

转载自blog.csdn.net/qq_63946922/article/details/127643363