1、RPC的概念
RPC,是远程过程调用的缩写,通俗的说就是调用远处的一个函数。与之相对应的本地函数调用。
golang 已经内置了RPC服务
2、RPC微服务化的好处
1. 不限定服务的提供方使用什么技术选型,能够实现公司跨团队的技术解耦。
2. 每个服务都被封装成进程,彼此独立
3. 使用微服务可以跨进程通信
RPC: 远程进程通信-------应用层协议(http协议同层),底层使用TCP实现。
在golang中实现RPC非常简单,有封装好的官方库和一些第三方库提供支持,Go RPC可以利用tcp或http来传递数据,可以对要传递的数据使用多种类型的编解码方式。golang官方的net库使用encoding.gob进行编解码,支持TCP/HTTP数据传输方式,由于其他语言不支持gob的编解码方式,所以使用net/rpc库实现的RPC方法没办法进行跨语言调用。
golang官方还提供了net/rpc/jsonrpc库实现RPC方法,json RPC采用JSON进行数据编解码,因而支持跨语言调用。
除了golang官方提供的rpc库,还有许多第三方库在golang中实现RPC提供支持,大部分第三方rpc库的实现都是使用protobuf进行数据编解码,根据protobuf声明文件自动生成rpc方法定义与服务注册代码,在golang中可以很方便的进行rpc服务调用。
服务端代码:
package main
import (
"fmt"
"net"
"net/rpc"
)
type Hello struct{
}
/*
1. 方法只能有两个可序列化的参数,其中第二个参数是指针类型
req 表示获取客户端传过来的数据
res 表示给客户端返回的数据
2. 方法返回一个error,同时必须是公开的方法
req和res的类型不能是:channel(通道)、complex(复数类型)、func(函数)
*/
func (this Hello) SayHello(req string, res *string) {
*res = "你好" + req
return nil
}
func main(){
//1,注册RPC服务
err := rpc.RegisterName("hello", new(Hello))
if err != nil {
fmt.Println(err)
}
//2.监听端口
listener,err1 := net.Listen("tcp", "127.0.0.1:8080")
if err1 != nil {
fmt.Println(err1)
}
//3.应用退出的时候关闭监听端口
defer listener.Close()
for {
//4.建立连接
conn, err2 := listener.Accept()
if err2 != nil{
fmt.Println(err2)
}
//5.绑定服务
rpc.ServeConn(conn)
}
}
客户端代码:
package main
import (
"fmt"
"net/rpc"
)
func main() {
//1. 用rpc.Dial和rpc微服务建立连接
conn, err := rpc.Dial("tcp","127.0.0.1:8080")
if err != nil {
fmt.Println(err1)
}
//2.函数退出时候要关闭连接
defer conn.Close()
//2.调用远程函数
var reply string
err = conn.Call("hello.Helloworld","张三",&reply)
if err != nil {
fmt.Println("Call:",err)
return
}
fmt.Println(reply)
}
首选是通过rpc.Dial拨号RPC服务,然后通过client.Call调用具体的RPC方法。在调用client.Call时,第一个参数使用点好连接的PRC服务名字和方法名字,第二个和第三个参数分别我们定义RPC方法的两个参数。