Golang unix sockets: 在不同的套接字上注册相同类型的RPC?

huangapple go评论103阅读模式
英文:

Golang unix sockets: registering same type for RPC on different sockets?

问题

我正在使用Go语言进行开发,并且对使用Unix套接字还不太熟悉。我尝试搜索类似的问题,但没有找到任何相关内容,所以如果之前已经有人回答过这个问题,我表示抱歉。

我想使用Unix套接字来模拟一个用于测试的机器集群。我正在测试我实现的Raft算法,所以我希望在不同的Unix套接字上注册多个相同类型的对象(一个庞大的结构体)。但是根据我编写的一个简单示例,效果似乎不是我想要的:对于相同的导出方法,拨号不同的套接字似乎会合并到一个单一的端口上:

我期望在调用不同客户端的Speak()方法时,控制台会打印出RICHARD和BENNY,但实际上它打印出其中一个两次,看起来是随机的。这是一个示例输出,这次似乎是RICHARD,但有时是BENNY。

编辑:感谢Pavlo Strokov的修复!如果未指定,默认情况下rpc.Register会使用DefaultServer,因此两者都会注册到同一个RPC服务器上:修正方法是调用rpc.NewServer(),并在该服务器上注册每个服务器。

请注意,我只翻译了你的问题和代码,没有回答你的问题。

英文:

I'm working in Go and a bit new to working with unix sockets. Tried searching for a similar question, but couldn't find anything, so apologies if this has been answered before.

I want to use unix sockets to simulate a cluster of machines for testing. I'm testing my implementation of Raft, so I want to register the multiple objects of the same type (a hefty struct) on different unix sockets. But looking at a simple example I wrote, the effect seems to be not what I want: dialing different sockets for the same exported method seems to collapse on a single port:

  1. package main
  2. import (
  3. "net"
  4. "fmt"
  5. "net/rpc"
  6. "log"
  7. "sync"
  8. )
  9. type Server struct {
  10. name string
  11. }
  12. type SpeakArgs struct {
  13. }
  14. type SpeakReply struct {
  15. Success bool
  16. }
  17. type AddArgs struct {
  18. A, B int
  19. }
  20. type AddReply struct {
  21. Answer int
  22. Success bool
  23. }
  24. func (s *Server) Add(args *AddArgs, reply *AddReply) error {
  25. reply.Answer = args.A + args.B
  26. reply.Success = true
  27. return nil
  28. }
  29. func (s *Server) Speak(args *SpeakArgs, reply *SpeakReply) error {
  30. fmt.Printf("My name is %v.\n", s.name)
  31. reply.Success = true
  32. return nil
  33. }
  34. func main() {
  35. var wgMain, wgRegister, wgCall sync.WaitGroup
  36. wgMain.Add(3)
  37. wgRegister.Add(2)
  38. wgCall.Add(1)
  39. go func() {
  40. server := &Server{name: "RICHARD"}
  41. rpc.Register(server)
  42. la, e := net.Listen("unix", "/tmp/example1.sock")
  43. if e != nil {
  44. log.Fatal("listen error:", e)
  45. }
  46. wgRegister.Done()
  47. go rpc.Accept(la)
  48. wgCall.Wait()
  49. la.Close()
  50. wgMain.Done()
  51. fmt.Println("Server exited.")
  52. }()
  53. go func() {
  54. server := &Server{name: "BENNY"}
  55. rpc.Register(server)
  56. lb, e := net.Listen("unix", "/tmp/example2.sock")
  57. if e != nil {
  58. log.Fatal("listen error:", e)
  59. }
  60. wgRegister.Done()
  61. go rpc.Accept(lb)
  62. wgCall.Wait()
  63. lb.Close()
  64. wgMain.Done()
  65. fmt.Println("Server exited.")
  66. }()
  67. go func() {
  68. wgRegister.Wait()
  69. oneclient, err1 := rpc.Dial("unix", "/tmp/example1.sock")
  70. twoclient, err2 := rpc.Dial("unix", "/tmp/example2.sock")
  71. if err1 != nil {
  72. log.Fatal("listen error:", err1)
  73. }
  74. if err2 != nil {
  75. log.Fatal("listen error:", err2)
  76. }
  77. addArgs := &AddArgs{1, 2}
  78. addReply := &AddReply{}
  79. speakArgs := &SpeakArgs{}
  80. speakReply := SpeakReply{}
  81. oneclient.Call("Server.Add", addArgs, addReply)
  82. oneclient.Call("Server.Speak", speakArgs, speakReply)
  83. twoclient.Call("Server.Speak", speakArgs, speakReply)
  84. fmt.Printf("Added numbers! %v + %v = %v.\n", addArgs.A, addArgs.B, addReply.Answer)
  85. wgCall.Done()
  86. oneclient.Close()
  87. twoclient.Close()
  88. wgMain.Done()
  89. fmt.Println("Client exited.")
  90. }()
  91. wgMain.Wait()
  92. }

I expect this to print both RICHARD and BENNY in console when Speak() is called on the different clients, but instead it prints one of them twice, seemingly randomly. Is there something I'm missing here? Example output, this time RICHARD seemed to come out, but sometimes it is BENNY.

  1. My name is RICHARD.
  2. My name is RICHARD.
  3. Added numbers! 1 + 2 = 3.
  4. Client exited.
  5. Server exited.
  6. Server exited.

Edit: Fix thanks to Pavlo Strokov! rpc.Register defaults to DefaultServer if not specified, so both were getting registered on the same RPC server: correction is to call rpc.NewServer() and register each server on that one.

  1. package main
  2. import (
  3. "net"
  4. "fmt"
  5. "net/rpc"
  6. "log"
  7. "sync"
  8. )
  9. type Server struct {
  10. name string
  11. }
  12. type SpeakArgs struct {
  13. }
  14. type SpeakReply struct {
  15. Success bool
  16. }
  17. type AddArgs struct {
  18. A, B int
  19. }
  20. type AddReply struct {
  21. Answer int
  22. Success bool
  23. }
  24. func (s *Server) Add(args *AddArgs, reply *AddReply) error {
  25. reply.Answer = args.A + args.B
  26. reply.Success = true
  27. return nil
  28. }
  29. func (s *Server) Speak(args *SpeakArgs, reply *SpeakReply) error {
  30. fmt.Printf("My name is %v.\n", s.name)
  31. reply.Success = true
  32. return nil
  33. }
  34. func main() {
  35. var wgMain, wgRegister, wgCall sync.WaitGroup
  36. wgMain.Add(3)
  37. wgRegister.Add(2)
  38. wgCall.Add(1)
  39. go func() {
  40. rpcServer := rpc.NewServer()
  41. server := &Server{name: "RICHARD"}
  42. rpcServer.Register(server)
  43. la, e := net.Listen("unix", "/tmp/example1.sock")
  44. if e != nil {
  45. log.Fatal("listen error:", e)
  46. }
  47. wgRegister.Done()
  48. go rpcServer.Accept(la)
  49. wgCall.Wait()
  50. la.Close()
  51. wgMain.Done()
  52. fmt.Println("Server exited.")
  53. }()
  54. go func() {
  55. rpcServer := rpc.NewServer()
  56. server := &Server{name: "BENNY"}
  57. rpcServer.Register(server)
  58. lb, e := net.Listen("unix", "/tmp/example2.sock")
  59. if e != nil {
  60. log.Fatal("listen error:", e)
  61. }
  62. wgRegister.Done()
  63. go rpcServer.Accept(lb)
  64. wgCall.Wait()
  65. lb.Close()
  66. wgMain.Done()
  67. fmt.Println("Server exited.")
  68. }()
  69. go func() {
  70. wgRegister.Wait()
  71. oneclient, err1 := rpc.Dial("unix", "/tmp/example1.sock")
  72. twoclient, err2 := rpc.Dial("unix", "/tmp/example2.sock")
  73. if err1 != nil {
  74. log.Fatal("listen error:", err1)
  75. }
  76. if err2 != nil {
  77. log.Fatal("listen error:", err2)
  78. }
  79. addArgs := &AddArgs{1, 2}
  80. addReply := &AddReply{}
  81. speakArgs := &SpeakArgs{}
  82. speakReply := &SpeakReply{}
  83. oneclient.Call("Server.Add", addArgs, addReply)
  84. oneclient.Call("Server.Speak", speakArgs, speakReply)
  85. twoclient.Call("Server.Speak", speakArgs, speakReply)
  86. fmt.Printf("Added numbers! %v + %v = %v.\n", addArgs.A, addArgs.B, addReply.Answer)
  87. wgCall.Done()
  88. oneclient.Close()
  89. twoclient.Close()
  90. wgMain.Done()
  91. fmt.Println("Client exited.")
  92. }()
  93. wgMain.Wait()
  94. }

which prints

  1. My name is RICHARD.
  2. My name is BENNY.
  3. Added numbers! 1 + 2 = 3.
  4. Client exited.
  5. Server exited.
  6. Server exited.

答案1

得分: 0

我认为这是因为你正在使用DefaultServer作为你的RPC服务器。相反,你应该为RICHARD和BENNY分别创建不同的服务器。
请查看我修改后的代码,以便在这里按预期工作:在一台机器上进行RPC调用

英文:

I think it is because you are using DefaultServer as your RPC server. Instead you should create different servers for each: RICHARD and BENNY.
Please take a look on your code modified by me to work as expected here: RPC calls on one machine

huangapple
  • 本文由 发表于 2017年7月28日 23:25:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/45377224.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定