Golang RCP调用挂起

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

Golang RCP call hanging

问题

我有一个后端应用程序和一个前端应用程序,都是用Go语言编写的。我正在尝试通过rpc使它们进行通信。

后端的main.go文件如下:

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "net/http"
  7. "net/rpc"
  8. "time"
  9. )
  10. type Application struct {
  11. config struct {
  12. server struct {
  13. port int
  14. network string
  15. }
  16. }
  17. }
  18. type MusicProject struct {
  19. Id string
  20. CreatedTime time.Time
  21. LastEditedTime time.Time
  22. Title string
  23. Year int
  24. Status string
  25. Description string
  26. ChoirRollup string
  27. }
  28. func main() {
  29. var app Application
  30. app.config.server.port = 5002
  31. app.config.server.network = "tcp"
  32. if err := rpc.Register(new(Application)); err != nil {
  33. log.Fatal(err)
  34. }
  35. rpc.HandleHTTP()
  36. // 启动rpc服务器
  37. log.Println("Starting server port", app.config.server.port)
  38. l, err := net.Listen("tcp", fmt.Sprintf(":%v", app.config.server.port))
  39. if err != nil {
  40. log.Fatal(err)
  41. }
  42. if err = http.Serve(l, nil); err != nil {
  43. log.Fatal(err)
  44. }
  45. }
  46. func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {
  47. musicProject := MusicProject{
  48. Id: id,
  49. CreatedTime: time.Now(),
  50. LastEditedTime: time.Now(),
  51. Title: "Test Project",
  52. Year: 2020,
  53. Status: "Completed",
  54. Description: "Short project Description",
  55. ChoirRollup: "Best Choir",
  56. }
  57. model = &musicProject
  58. return nil
  59. }

前端的rpc调用部分如下:

  1. package main
  2. import (
  3. "log"
  4. "net/rpc"
  5. "time"
  6. )
  7. type MusicProject struct {
  8. Id string
  9. CreatedTime time.Time
  10. LastEditedTime time.Time
  11. Title string
  12. Year int
  13. Status string
  14. Description string
  15. ChoirRollup string
  16. }
  17. func main() {
  18. dial, err := rpc.Dial("tcp", "localhost:5002")
  19. if err != nil {
  20. log.Println(err)
  21. }
  22. projectID := "some_id_123"
  23. var musicProject MusicProject
  24. err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
  25. if err != nil {
  26. log.Println(err)
  27. }
  28. log.Println(musicProject)
  29. }

当调用客户端方法时,调用会无限期地挂起,而不会返回任何错误,因此很难进行调试。

你有任何调试建议吗?你在我的代码中看到了什么问题吗?

谢谢你的帮助!

英文:

I have a back-end app and a front-end, both in Go. I am trying to make them talk via rpc.

back-end main.go

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "net/http"
  7. "net/rpc"
  8. "time"
  9. )
  10. type Application struct {
  11. config struct {
  12. server struct {
  13. port int
  14. network string
  15. }
  16. }
  17. }
  18. type MusicProject struct {
  19. Id string
  20. CreatedTime time.Time
  21. LastEditedTime time.Time
  22. Title string
  23. Year int
  24. Status string
  25. Description string
  26. ChoirRollup string
  27. }
  28. func main() {
  29. var app Application
  30. app.config.server.port = 5002
  31. app.config.server.network = "tcp"
  32. if err := rpc.Register(new(Application)); err != nil {
  33. log.Fatal(err)
  34. }
  35. rpc.HandleHTTP()
  36. // start the rpc server
  37. log.Println("Starting server port", app.config.server.port)
  38. l, err := net.Listen("tcp", fmt.Sprintf(":%v", app.config.server.port))
  39. if err != nil {
  40. log.Fatal(err)
  41. }
  42. if err = http.Serve(l, nil); err != nil {
  43. log.Fatal(err)
  44. }
  45. }
  46. func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {
  47. musicProject := MusicProject{
  48. Id: id,
  49. CreatedTime: time.Now(),
  50. LastEditedTime: time.Now(),
  51. Title: "Test Project",
  52. Year: 2020,
  53. Status: "Completed",
  54. Description: "Short project Description",
  55. ChoirRollup: "Best Choir",
  56. }
  57. model = &musicProject
  58. return nil
  59. }

front-end rpc call

  1. package main
  2. import (
  3. "log"
  4. "net/rpc"
  5. "time"
  6. )
  7. type MusicProject struct {
  8. Id string
  9. CreatedTime time.Time
  10. LastEditedTime time.Time
  11. Title string
  12. Year int
  13. Status string
  14. Description string
  15. ChoirRollup string
  16. }
  17. func main() {
  18. dial, err := rpc.Dial("tcp", "localhost:5002")
  19. if err != nil {
  20. log.Println(err)
  21. }
  22. projectID := "some_id_123"
  23. var musicProject MusicProject
  24. err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
  25. if err != nil {
  26. log.Println(err)
  27. }
  28. log.Println(musicProject)
  29. }

Once the client method is call, the call hanged indefinite with out sending back any error, so quite difficult to debug.

Do you have any suggestion for debugging? Do you see anything wrong in my code?
Thank you for your help!

答案1

得分: 0

你的服务器正在提供HTTP服务:

  1. if err = http.Serve(l, nil); err != nil {
  2. log.Fatal(err)
  3. }

但是你的客户端正在使用直接的TCP连接(HTTP在TCP上运行,但添加了另一层):

  1. err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)

所以要解决你的问题,你需要改变其中一方。例如,将服务器改为:

  1. rpc.Accept(l)

(或者你可以在客户端使用rpc.DialHTTP

你的代码还有一些其他问题(主要问题是在后端设置响应的方式)。以下是我测试通过的代码(没有花太多精力来整理或测试!)。

服务器

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "net/rpc"
  7. "time"
  8. )
  9. type MusicProject struct {
  10. Id string
  11. CreatedTime time.Time
  12. LastEditedTime time.Time
  13. Title string
  14. Year int
  15. Status string
  16. Description string
  17. ChoirRollup string
  18. }
  19. type Application struct {
  20. }
  21. func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {
  22. *model = MusicProject{
  23. Id: id,
  24. CreatedTime: time.Now(),
  25. LastEditedTime: time.Now(),
  26. Title: "Test Project",
  27. Year: 2020,
  28. Status: "Completed",
  29. Description: "Short project Description",
  30. ChoirRollup: "Best Choir",
  31. }
  32. return nil
  33. }
  34. func main() {
  35. const port = 5002
  36. if err := rpc.Register(new(Application)); err != nil {
  37. log.Fatal(err)
  38. }
  39. // 启动RPC服务器
  40. log.Println("在端口上启动服务器:", port)
  41. l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
  42. if err != nil {
  43. log.Fatal(err)
  44. }
  45. rpc.Accept(l)
  46. }

客户端

  1. package main
  2. import (
  3. "log"
  4. "net/rpc"
  5. "time"
  6. )
  7. type MusicProject struct {
  8. Id string
  9. CreatedTime time.Time
  10. LastEditedTime time.Time
  11. Title string
  12. Year int
  13. Status string
  14. Description string
  15. ChoirRollup string
  16. }
  17. func main() {
  18. dial, err := rpc.Dial("tcp", "localhost:5002")
  19. if err != nil {
  20. log.Fatal(err)
  21. }
  22. projectID := "some_id_123"
  23. var musicProject MusicProject
  24. err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
  25. if err != nil {
  26. log.Fatal("错误:", err)
  27. }
  28. log.Println(musicProject)
  29. }
英文:

Your server is serving HTTP:

  1. if err = http.Serve(l, nil); err != nil {
  2. log.Fatal(err)
  3. }

But your client is using straight TCP (HTTP runs over TCP but adds another layer):

  1. err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)

So to fix your issue you need to change one side or the other. For example change the server to:

  1. rpc.Accept(l)

(alternatively you could use rpc.DialHTTP in the client)

There are a couple of other issues with your code (the main one being the way you set the response in the back-end). The following works for me (have not put much effort into making it tidy or testing!).

server

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "net/rpc"
  7. "time"
  8. )
  9. type MusicProject struct {
  10. Id string
  11. CreatedTime time.Time
  12. LastEditedTime time.Time
  13. Title string
  14. Year int
  15. Status string
  16. Description string
  17. ChoirRollup string
  18. }
  19. type Application struct {
  20. }
  21. func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {
  22. *model = MusicProject{
  23. Id: id,
  24. CreatedTime: time.Now(),
  25. LastEditedTime: time.Now(),
  26. Title: "Test Project",
  27. Year: 2020,
  28. Status: "Completed",
  29. Description: "Short project Description",
  30. ChoirRollup: "Best Choir",
  31. }
  32. return nil
  33. }
  34. func main() {
  35. const port = 5002
  36. if err := rpc.Register(new(Application)); err != nil {
  37. log.Fatal(err)
  38. }
  39. // start the rpc server
  40. log.Println("Starting server on port:", port)
  41. l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
  42. if err != nil {
  43. log.Fatal(err)
  44. }
  45. rpc.Accept(l)
  46. }

client

  1. package main
  2. import (
  3. "log"
  4. "net/rpc"
  5. "time"
  6. )
  7. type MusicProject struct {
  8. Id string
  9. CreatedTime time.Time
  10. LastEditedTime time.Time
  11. Title string
  12. Year int
  13. Status string
  14. Description string
  15. ChoirRollup string
  16. }
  17. func main() {
  18. dial, err := rpc.Dial("tcp", "localhost:5002")
  19. if err != nil {
  20. log.Fatal(err)
  21. }
  22. projectID := "some_id_123"
  23. var musicProject MusicProject
  24. err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
  25. if err != nil {
  26. log.Fatal("error:", err)
  27. }
  28. log.Println(musicProject)
  29. }

huangapple
  • 本文由 发表于 2022年6月28日 22:13:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/72788065.html
匿名

发表评论

匿名网友

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

确定