我所在公司的项目是采用基于 Restful 的微服务架构,随着微服务之间的沟通越来越频繁,就希望可以做成用 rpc 来做内部的通讯,对外依然用 Restful。于是就想到了 golang 标准库的 rpc 包和 google 的 grpc。
这篇文章重点了解一下 golang 的 rpc 包。
golang 的 rpc 支持三个级别的 RPC:TCP、HTTP、JSONRPC。但 Go 的 RPC 包是独一无二的 RPC,它和传统的 RPC 系统不同,它只支持 Go 开发的服务器与客户端之间的交互,因为在内部,它们采用了 Gob 来编码。
Go RPC 的函数只有符合下面的条件才能被远程访问,不然会被忽略,详细的要求如下:
举个例子,正确的 RPC 函数格式如下:
- func (t *T) MethodName(argType T1, replyType *T2) error
T、T1 和 T2 类型必须能被
包编解码。
- encoding/gob
举一个 http 的例子。
下面是 http 服务器端的代码:
- package main
- import (
- "errors"
- "net"
- "net/rpc"
- "log"
- "net/http"
- )
- type Args struct {
- A, B int
- }
- type Quotient struct {
- Quo, Rem int
- }
- type Arith int
- func (t *Arith) Multiply(args *Args, reply *int) error {
- *reply = args.A * args.B
- return nil
- }
- func (t *Arith) Divide(args *Args, quo *Quotient) error {
- if args.B == 0 {
- return errors.New("divide by zero")
- }
- quo.Quo = args.A / args.B
- quo.Rem = args.A % args.B
- return nil
- }
- func main() {
- arith := new(Arith)
- rpc.Register(arith)
- rpc.HandleHTTP()
- l, e := net.Listen("tcp", ":1234")
- if e != nil {
- log.Fatal("listen error:", e)
- }
- http.Serve(l, nil)
- }
简单分析一下上面的例子,先实例化了一个 Arith 对象 arith,然后给 arith 注册了 rpc 服务,然后把 rpc 挂载到 http 服务上面,当 http 服务打开的时候我们就可以通过 rpc 客户端来调用 arith 中符合 rpc 标准的的方法了。
请看客户端的代码:
- package main
- import (
- "net/rpc"
- "log"
- "fmt"
- )
- type Args struct {
- A, B int
- }
- type Quotient struct {
- Quo, Rem int
- }
- func main() {
- client, err := rpc.DialHTTP("tcp", "127.0.0.1:1234")
- if err != nil {
- log.Fatal("dialing:", err)
- }
- // Synchronous call
- args := &Args{7,8}
- var reply int
- err = client.Call("Arith.Multiply", args, &reply)
- if err != nil {
- log.Fatal("arith error:", err)
- }
- fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)
- // Asynchronous call
- quotient := new(Quotient)
- divCall := client.Go("Arith.Divide", args, quotient, nil)
- replyCall := <-divCall.Done // will be equal to divCall
- if replyCall.Error != nil {
- log.Fatal("arith error:", replyCall.Error)
- }
- fmt.Printf("Arith: %d/%d=%d...%d", args.A, args.B, quotient.Quo, quotient.Rem)
- // check errors, print, etc.
- }
简单说明下,先用 rpc 的 DialHTTP 方法连接服务器端,调用服务器端的函数就要使用 Call 方法了,Call 方法的参数和返回值已经很清晰的表述出 rpc 整体的调用逻辑了。
我们把服务器端跑起来,再把客户端跑起来,这时候客户端会输出:
- Arith: 7*8=56
- Arith: 7/8=0...7
到此,整个 rpc 的调用逻辑就完成了。
来源: http://www.cnblogs.com/andyidea/p/6525714.html