Golang RCP调用挂起

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

Golang RCP call hanging

问题

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

后端的main.go文件如下:

package main

import (
	"fmt"
	"log"
	"net"
	"net/http"
	"net/rpc"
	"time"
)

type Application struct {
	config struct {
		server struct {
			port    int
			network string
		}
	}
}

type MusicProject struct {
	Id             string
	CreatedTime    time.Time
	LastEditedTime time.Time
	Title          string
	Year           int
	Status         string
	Description    string
	ChoirRollup    string
}

func main() {

	var app Application
	app.config.server.port = 5002
	app.config.server.network = "tcp"

	if err := rpc.Register(new(Application)); err != nil {
		log.Fatal(err)
	}
	rpc.HandleHTTP()

	// 启动rpc服务器
	log.Println("Starting server port", app.config.server.port)
	l, err := net.Listen("tcp", fmt.Sprintf(":%v", app.config.server.port))
	if err != nil {
		log.Fatal(err)
	}
	if err = http.Serve(l, nil); err != nil {
		log.Fatal(err)
	}
}

func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {

	musicProject := MusicProject{
		Id:             id,
		CreatedTime:    time.Now(),
		LastEditedTime: time.Now(),
		Title:          "Test Project",
		Year:           2020,
		Status:         "Completed",
		Description:    "Short project Description",
		ChoirRollup:    "Best Choir",
	}

	model = &musicProject
	return nil
}

前端的rpc调用部分如下:

package main

import (
	"log"
	"net/rpc"
	"time"
)

type MusicProject struct {
	Id             string
	CreatedTime    time.Time
	LastEditedTime time.Time
	Title          string
	Year           int
	Status         string
	Description    string
	ChoirRollup    string
}

func main() {

	dial, err := rpc.Dial("tcp", "localhost:5002")
	if err != nil {
		log.Println(err)
	}

	projectID := "some_id_123"

	var musicProject MusicProject

	err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
	if err != nil {
		log.Println(err)
	}

	log.Println(musicProject)
}

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

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

谢谢你的帮助!

英文:

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

package main
import (
"fmt"
"log"
"net"
"net/http"
"net/rpc"
"time"
)
type Application struct {
config struct {
server struct {
port    int
network string
}
}
}
type MusicProject struct {
Id             string
CreatedTime    time.Time
LastEditedTime time.Time
Title          string
Year           int
Status         string
Description    string
ChoirRollup    string
}
func main() {
var app Application
app.config.server.port = 5002
app.config.server.network = "tcp"
if err := rpc.Register(new(Application)); err != nil {
log.Fatal(err)
}
rpc.HandleHTTP()
// start the rpc server
log.Println("Starting server port", app.config.server.port)
l, err := net.Listen("tcp", fmt.Sprintf(":%v", app.config.server.port))
if err != nil {
log.Fatal(err)
}
if err = http.Serve(l, nil); err != nil {
log.Fatal(err)
}
}
func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {
musicProject := MusicProject{
Id:             id,
CreatedTime:    time.Now(),
LastEditedTime: time.Now(),
Title:          "Test Project",
Year:           2020,
Status:         "Completed",
Description:    "Short project Description",
ChoirRollup:    "Best Choir",
}
model = &musicProject
return nil
}

front-end rpc call

package main
import (
"log"
"net/rpc"
"time"
)
type MusicProject struct {
Id             string
CreatedTime    time.Time
LastEditedTime time.Time
Title          string
Year           int
Status         string
Description    string
ChoirRollup    string
}
func main() {
dial, err := rpc.Dial("tcp", "localhost:5002")
if err != nil {
log.Println(err)
}
projectID := "some_id_123"
var musicProject MusicProject
err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
if err != nil {
log.Println(err)
}
log.Println(musicProject)
}

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服务:

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

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

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

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

rpc.Accept(l)

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

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

服务器

package main

import (
	"fmt"
	"log"
	"net"
	"net/rpc"
	"time"
)

type MusicProject struct {
	Id             string
	CreatedTime    time.Time
	LastEditedTime time.Time
	Title          string
	Year           int
	Status         string
	Description    string
	ChoirRollup    string
}

type Application struct {
}

func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {
	*model = MusicProject{
		Id:             id,
		CreatedTime:    time.Now(),
		LastEditedTime: time.Now(),
		Title:          "Test Project",
		Year:           2020,
		Status:         "Completed",
		Description:    "Short project Description",
		ChoirRollup:    "Best Choir",
	}
	return nil
}

func main() {
	const port = 5002
	if err := rpc.Register(new(Application)); err != nil {
		log.Fatal(err)
	}

	// 启动RPC服务器
	log.Println("在端口上启动服务器:", port)
	l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
	if err != nil {
		log.Fatal(err)
	}
	rpc.Accept(l)
}

客户端

package main

import (
	"log"
	"net/rpc"
	"time"
)

type MusicProject struct {
	Id             string
	CreatedTime    time.Time
	LastEditedTime time.Time
	Title          string
	Year           int
	Status         string
	Description    string
	ChoirRollup    string
}

func main() {
	dial, err := rpc.Dial("tcp", "localhost:5002")
	if err != nil {
		log.Fatal(err)
	}

	projectID := "some_id_123"

	var musicProject MusicProject

	err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
	if err != nil {
		log.Fatal("错误:", err)
	}
	log.Println(musicProject)
}
英文:

Your server is serving HTTP:

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

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

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:

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

package main

import (
	"fmt"
	"log"
	"net"
	"net/rpc"
	"time"
)

type MusicProject struct {
	Id             string
	CreatedTime    time.Time
	LastEditedTime time.Time
	Title          string
	Year           int
	Status         string
	Description    string
	ChoirRollup    string
}

type Application struct {
}

func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {
	*model = MusicProject{
		Id:             id,
		CreatedTime:    time.Now(),
		LastEditedTime: time.Now(),
		Title:          "Test Project",
		Year:           2020,
		Status:         "Completed",
		Description:    "Short project Description",
		ChoirRollup:    "Best Choir",
	}
	return nil
}

func main() {
	const port = 5002
	if err := rpc.Register(new(Application)); err != nil {
		log.Fatal(err)
	}

	// start the rpc server
	log.Println("Starting server on port:", port)
	l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
	if err != nil {
		log.Fatal(err)
	}
	rpc.Accept(l)
}

client

package main

import (
	"log"
	"net/rpc"
	"time"
)

type MusicProject struct {
	Id             string
	CreatedTime    time.Time
	LastEditedTime time.Time
	Title          string
	Year           int
	Status         string
	Description    string
	ChoirRollup    string
}

func main() {
	dial, err := rpc.Dial("tcp", "localhost:5002")
	if err != nil {
		log.Fatal(err)
	}

	projectID := "some_id_123"

	var musicProject MusicProject

	err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
	if err != nil {
		log.Fatal("error:", err)
	}
	log.Println(musicProject)
}

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:

确定