在PHP中调用Go RPC套接字方法

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

Call Go RPC socket methods in PHP

问题

我开始寻找RPC框架,发现了gRPC,但问题是它使用Protocol Buffer,我担心如果我想在当前的PHP单体应用程序中使用它,会变得非常混乱。因此,我开始实现一个基本的Go RPC服务,但目前我不知道如何在PHP中使用它。

基本上,我有一个databasemanager包,其中包含以下结构和方法:

type DatabaseManager struct {
	Database *gorm.DB
	Log      logging.Logger
}

func (db *DatabaseManager) Last(args *string, reply *string) error {

	db.Log[logging.INFO].Printf("%v", *args)
	reply = args
	db.Log[logging.INFO].Printf("%v", *reply)
	return nil
}

我正在使用一个命令来启动服务器监听:

func registerDatabaseManager(server *rpc.Server, dbManager *databasemanager.DatabaseManager) {
	server.RegisterName("DatabaseManager", dbManager)
}

func RunRPC(path string) error {
	db, _, log := dependencyInjection(path)
	dbManager := &databasemanager.DatabaseManager{
		Database: db,
		Log:      log,
	}
	server := rpc.NewServer()
	registerDatabaseManager(server, dbManager)
	listen, err := net.Listen("tcp", ":50051")
	if err != nil {
		log[logging.ERROR].Print(err)
	}
	log[logging.INFO].Print("Server started - listening on :50051")
	server.Accept(listen)
	return nil
}

基本上,它使用了一种非常基本的方法。请求和响应的格式将是JSON,因为大部分时间它将处理大量数据。

Golang中的客户端如下所示:

type DBManager struct {
	client *rpc.Client
}

func (t *DBManager) Last(args *string) string {
	*args = "awesome test"
	var reply string
	err := t.client.Call("DatabaseManager.Last", args, &reply)
	if err != nil {
		log.Fatal("arith error:", err)
	}
	return reply
}

func main() {
	conn, err := net.Dial("tcp", "localhost:50051")
	if err != nil {
		log.Fatal("Connectiong:", err)
	}
	dbManager := &DBManager{client: rpc.NewClient(conn)}
	asd := "asdasqwesaf"
	fmt.Println(dbManager.Last(&asd))
}

它工作得很好,我可以使用它,但是我提到过我有一个旧的PHP单体应用程序,我也想在那里使用这些方法。

我在互联网上找到了这个,它实现了我想要的相同功能,但问题是我尝试根据我的需求重写它,但它不起作用。基本上,我只是将callRPC的参数更改为以下内容:

$result = callRPC(
	"tcp://127.0.0.1:50051",
	[
		'{"method":"DatabaseManager.Last","params":["asd"],"id":0}',
	],
	1,
	8
);

我不知道,我是否采取了正确的方法?还是有其他更好的解决方案可以向我展示?

英文:

I started looking for RPC frameworks and I found the gRPC, but my problem it uses the Protocol-Buffer and I'm afraid if I want to use it in my current monolithic PHP application it will be a big mess. So, I started to implement a Go basic RPC service but currently I don't have any idea what and how to use it in PHP.

So basically I have a databasemanager package where I have these struct and methods:

type DatabaseManager struct {
	Database *gorm.DB
	Log      logging.Logger
}

func (db *DatabaseManager) Last(args *string, reply *string) error {

	db.Log[logging.INFO].Printf("%v", *args)
	reply = args
	db.Log[logging.INFO].Printf("%v", *reply)
	return nil
}

And I'm using a command which starts the server for listening:

func registerDatabaseManager(server *rpc.Server, dbManager *databasemanager.DatabaseManager) {
	server.RegisterName("DatabaseManager", dbManager)
}

func RunRPC(path string) error {
	db, _, log := dependencyInjection(path)
	dbManager := &databasemanager.DatabaseManager{
		Database: db,
		Log:      log,
	}
	server := rpc.NewServer()
	registerDatabaseManager(server, dbManager)
	listen, err := net.Listen("tcp", ":50051")
	if err != nil {
		log[logging.ERROR].Print(err)
	}
	log[logging.INFO].Print("Server started - listening on :50051")
	server.Accept(listen)
	return nil
}

So basically it is using a very basic approach. The request and response format will be JSON because most of the time it will handle big amounts of data.

The client in Golang is looks like:

type DBManager struct {
	client *rpc.Client
}

func (t *DBManager) Last(args *string) string {
	*args = "awesome test"
	var reply string
	err := t.client.Call("DatabaseManager.Last", args, &reply)
	if err != nil {
		log.Fatal("arith error:", err)
	}
	return reply
}

func main() {
	conn, err := net.Dial("tcp", "localhost:50051")
	if err != nil {log.Fatal("Connectiong:", err)}
	dbManager := &DBManager{client: rpc.NewClient(conn)}
	asd := "asdasqwesaf"
	fmt.Println(dbManager.Last(&asd))
}

It is working nicely and I can use it but had mentioned I have an old monolitic PHP where I want to use the methods there too.

I found this on the internet, which is to implement the same what I want, but the problem I tried to rewrite it for my needs, but it's not working. Basically I just changed the callRPC params as the following:

$result = callRPC(
	"tcp://127.0.0.1:50051",
	[
		'{"method":"DatabaseManager.Last","params":["asd"],"id":0}',
	],
	1,
	8
); 

I don't know, am I following a good approach? Or not? Maybe someone can show me a better solution.

答案1

得分: 2

Go rpc的默认实现net/rpc使用一种特定的编码,称为Gob,它专门用于Go结构体。据我所知,目前没有PHP的Gob编码/解码实现,因此您将无法从PHP调用一个Go语言的rpc服务器。
可选方案有:使用grpc(是的,它使用proto buffer,但并不难,而且自proto buffer 3以来有新的对象类型),或者使用消息代理,如ZeroMQRabbitMQ(如果您对两者都是初学者,我建议选择RabbitMQ,因为它更容易学习)。

英文:

The Go rpc default implementation net/rpc use a particular encoding specific for Go struct called Gob. Far as I know there isn't a implementation of encoding/deconding Gob for PHP and for this reason you will not able to call an rpc golang server from PHP.
The alternatives are: use grpc (yes, it use proto buffer but is not to difficult and since proto buffer 3 there new type of object) or use a message broker such as ZeroMQ or RabbitMQ (if you are beginner on both I suggest RabbitMQ since it's more easier to learn).

huangapple
  • 本文由 发表于 2017年2月14日 19:47:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/42225361.html
匿名

发表评论

匿名网友

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

确定