gpt4 book ai didi

go - Go 中来自客户端和服务器的 RPC

转载 作者:IT王子 更新时间:2023-10-29 00:38:11 25 4
gpt4 key购买 nike

在 Go 中使用 net/rpc 包真的可以从服务器到客户端进行 RPC 调用吗?如果没有,是否有更好的解决方案?

最佳答案

我目前正在使用 thrift ( thrift4go ) 实现服务器->客户端和客户端->服务器 RPC 功能。默认情况下,thrift 只执行 client->server 调用,就像 net/rpc 一样。由于我还需要服务器-> 客户端通信,我做了一些研究并找到了 bidi-thrift . Bidi-thrift 解释了如何连接 java 服务器 + java 客户端以进行双向 thrift 通信。

bidi-thrift 的作用及其局限性。

TCP 连接有传入和传出通信线路(RC 和 TX)。 bidi-thrift 的想法是拆分 RS 和 TX,并将它们提供给客户端应用程序和服务器应用程序上的服务器(处理器)和客户端(远程)。我发现这在 Go 中很难做到。此外,这种方式不可能有“响应”(响应行正在使用中)。因此,服务中的所有方法都必须是“oneway void”。 (即发即忘,调用没有结果)。

解决方案

我改变了 bidi-thrift 的想法,让客户端打开两个到服务器的连接,A 和 B。第一个连接 (A) 用于执行客户端 -> 服务器通信(客户端像往常一样进行调用) ).第二个连接(B)被“劫持”,并连接到客户端上的服务器(处理器),同时连接到服务器上的客户端(远程)。我已经将它与 Go 服务器和 Java 客户端一起使用。它工作得很好。它快速可靠(就像普通的 thrift 一样)。

一些来源.. B连接(服务器->客户端)是这样设置的:

去服务器

// factories
framedTransportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()

// create socket listener
addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:9091")
if err != nil {
log.Print("Error resolving address: ", err.Error(), "\n")
return
}
serverTransport, err := thrift.NewTServerSocketAddr(addr)
if err != nil {
log.Print("Error creating server socket: ", err.Error(), "\n")
return
}

// Start the server to listen for connections
log.Print("Starting the server for B communication (server->client) on ", addr, "\n")
err = serverTransport.Listen()
if err != nil {
log.Print("Error during B server: ", err.Error(), "\n")
return //err
}

// Accept new connections and handle those
for {
transport, err := serverTransport.Accept()
if err != nil {
return //err
}
if transport != nil {
// Each transport is handled in a goroutine so the server is availiable again.
go func() {
useTransport := framedTransportFactory.GetTransport(transport)
client := worldclient.NewWorldClientClientFactory(useTransport, protocolFactory)

// Thats it!
// Lets do something with the connction
result, err := client.Hello()
if err != nil {
log.Printf("Errror when calling Hello on client: %s\n", err)
}

// client.CallSomething()
}()
}
}

Java 客户端

// preparations for B connection
TTransportFactory transportFactory = new TTransportFactory();
TProtocolFactory protocolFactory = new TBinaryProtocol.Factory();
YourServiceProcessor processor = new YourService.Processor<YourServiceProcessor>(new YourServiceProcessor(this));


/* Create thrift connection for B calls (server -> client) */
try {
// create the transport
final TTransport transport = new TSocket("127.0.0.1", 9091);

// open the transport
transport.open();

// add framing to the transport layer
final TTransport framedTransport = new TFramedTransport(transportFactory.getTransport(transport));

// connect framed transports to protocols
final TProtocol protocol = protocolFactory.getProtocol(framedTransport);

// let the processor handle the requests in new Thread
new Thread() {
public void run() {
try {
while (processor.process(protocol, protocol)) {}
} catch (TException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}.start();
} catch(Exception e) {
e.printStackTrace();
}

关于go - Go 中来自客户端和服务器的 RPC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13166004/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com