Go RPC 库

打印 上一主题 下一主题

主题 908|帖子 908|积分 2724

RPC(Remote Poresedure Call)是远程方法调用的缩写。Go的RPC库可以实现通过网络或者其他I/O方式远程调用对象的方法。
服务器注册一个对象,让它作为一个以对象类型命名的服务,让这个对象导出的方法可以被远程调用。一个服务器可以注册多个不同类型的对象,但是不能注册同一类型的多个对象。
一个能够被远程调用的方法应该像下面这样:
  1. func (t *T) MethodName(argType T1, replyType *T2) error
复制代码
一个简单的例子:实现简单的kv存储,并(在同一台机器上)通过RPC调用Put和Get方法。
  1. package main
  2. import (
  3.         "fmt"
  4.         "log"
  5.         "net"
  6.         "net/http"
  7.         "net/rpc"
  8.         "sync"
  9.         "time"
  10. )
  11. // RPC struct definition
  12. type PutArgs struct {
  13.         Key string
  14.         Val string
  15. }
  16. type PutReply struct {
  17.         Ok bool
  18. }
  19. type GetArgs struct {
  20.         Key string
  21. }
  22. type GetReply struct {
  23.         Val string
  24. }
  25. type Kv struct {
  26.         data map[string]string
  27.         mu   sync.Mutex
  28. }
  29. // server
  30. func (kv *Kv) Get(args *GetArgs, reply *GetReply) error {
  31.         kv.mu.Lock()
  32.         defer kv.mu.Unlock()
  33.         reply.Val = kv.data[args.Key]
  34.         return nil
  35. }
  36. func (kv *Kv) Put(args *PutArgs, reply *PutReply) error {
  37.         kv.mu.Lock()
  38.         defer kv.mu.Unlock()
  39.         kv.data[args.Key] = args.Val
  40.         reply.Ok = true
  41.         return nil
  42. }
  43. func KvServer() {
  44.         kv := new(Kv)
  45.         kv.data = make(map[string]string)
  46.         rpc.Register(kv)
  47.         rpc.HandleHTTP()
  48.         l, err := net.Listen("tcp", ":1234")
  49.         if err != nil {
  50.                 log.Fatal("listen error: ", err)
  51.         }
  52.         http.Serve(l, nil)
  53. }
  54. // client interface
  55. func get(key string) string {
  56.         client, err := rpc.DialHTTP("tcp", "127.0.0.1"+":1234")
  57.         if err != nil {
  58.                 log.Fatal("dialing:", err)
  59.         }
  60.         args := GetArgs{key}
  61.         reply := GetReply{}
  62.         e := client.Call("Kv.Get", args, &reply)
  63.         if e != nil {
  64.                 log.Fatal("get error", e)
  65.         }
  66.         client.Close()
  67.         return reply.Val
  68. }
  69. func put(key string, val string) bool {
  70.         client, err := rpc.DialHTTP("tcp", "127.0.0.1"+":1234")
  71.         if err != nil {
  72.                 log.Fatal("dialing:", err)
  73.         }
  74.         args := PutArgs{key, val}
  75.         reply := PutReply{}
  76.         e := client.Call("Kv.Put", args, &reply)
  77.         if e != nil {
  78.                 log.Fatal("put error", e)
  79.         }
  80.         client.Close()
  81.         return reply.Ok
  82. }
  83. // test
  84. func main() {
  85.         go KvServer()
  86.         time.Sleep(time.Second) // wait for server to start
  87.         fmt.Println(put("key1", "value1"))
  88.         fmt.Println(put("key2", "value2"))
  89.         fmt.Println(put("key3", "value3"))
  90.         fmt.Println(get("key1"))
  91.         fmt.Println(get("key2"))
  92.         fmt.Println(get("key3"))
  93.         fmt.Println(get("value1"))
  94. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

北冰洋以北

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表