【问题标题】:Java method implementation for Apache Thrift RPCs in a distributed environment分布式环境中 Apache Thrift RPC 的 Java 方法实现
【发布时间】:2017-07-06 18:31:49
【问题描述】:

我的项目的简要说明: 我正在编写一个名为“GreetingsNode”的 java 类,它在有一个“managementNode”的分布式环境中工作,它就像服务存储库一样,接收和存储其他节点和调度的信息(主机端口号和提供的服务)注册的服务提供的方法的 RPC。如果一个节点可以对 RPC 进行应答,则打开一个 thrift socket,并在调用节点和应答节点之间建立连接,应答节点返回结果。

我使用 Apache thrift 作为 IDL 和 RPC 框架。

现在的问题。 我的 GreetingsNodeHandler 类实现了一个简单的 thrift 接口,其中包含一个方法“getHello(user)”(user 是一个包含节点名称的结构,它是 GreetingsNode 类的构造函数的参数)。 当连接到管理节点的 GreetingsNode X 对该方法进行 RPC 时,另一个已注册的 GreetingsNode 必须以消息“hello X”进行响应。

我没有正确理解如何实现返回结果的处理程序部分,因此我不明白我应该如何编写应该检查方法实现是否正常工作的 junit 测试。

类似的断言 assertEquals(client.getHello(user).getMessage(), "Hello John Doe")

会工作,但我不明白,在我的情况下,我应该如何放置客户端部分......

GreetingService thrift 服务代码:

struct Message {
    1: string message   
}  

struct User {
    1: string name
}

service GreetingsService {
    Message getHello(1: User user)
}

必须实现 GreetingsService 方法 getHello() 的 GreetingsServiceHandler 代码

public class GreetingsServiceHandler implements GreetingsService.Iface {

private static Random random = new Random(10);
private ManagementService.Client managementClient;
private GreetingsService.Client helloClient;

@Override
public Message getHello(User user) throws TException {
    Message answer = null;
    // class ServiceProvider is generated by thrift, part of ManagementService thrift service 
    ServiceProvider provider = null; 
    List<ServiceProvider>providers = managementClient.getProvidersForService(user.name);

    if (providers.isEmpty())
        throw new NoProviderAvailableException(); //separate file contains Exception
    else {
        provider = providers.get(random.nextInt(providers.size()));
        //connection between nodes is established here
        TTransport helloTransport = new TSocket(provider.getHostName(), provider.getPort());
        TProtocol helloProtocol = new TBinaryProtocol(helloTransport);
        helloClient = new GreetingsService.Client(helloProtocol);
        helloTransport.open();

        // here lies my problem
        answer = helloClient.getHello(user);
        //if I use this instead, then helloClient variable is clearly not used, but of course I need it to answer the method call
        answer = answer.setMessage("Ciao " + user.getName() + ", welcome among us!");

    }
    return answer;

}

和 GreetingsNode 代码如下:

public class GreetingsNode implements NodeIface {

private ThriftServer helloServer;
private ManagementService.Client managementClient;
private NodeManifest nodeManifest;
private User user;
private String name;

public GreetingsNode(NodeManifest nodeManifest, String name) {
    this.nodeManifest = nodeManifest;
    this.helloServer = new ThriftServer(GreetingsServiceHandler.class);
    this.name = name;
}

@Override
public void turnOn() throws TException {

    helloServer.start();

    TSocket helloServerTransport = new TSocket("localhost", Constants.SERVER_PORT);
    TBinaryProtocol helloServerProtocol = new TBinaryProtocol(helloServerTransport);
    managementClient = new ManagementService.Client(helloServerProtocol);
    this.setUser(new User(name));
    helloServerTransport.open();

    helloServer = new ThriftServer(GreetingsServiceHandler.class);
    //portNegotiator is a class described in a separate file, that handles the registration of other nodes to the managementNode. NodeManifest is a file generated by thrift, part of managementService thrift file, describing a struct that contains hostname and port number of nodes.
    PortNegotiator negotiator = new PortNegotiator(managementClient);
    negotiator.negotiate(nodeManifest, helloServer);

}

@Override
public void turnOff() {
    helloServer.stop();
}

public User getUser() {
    return user;
}

public void setUser(User user) {
    this.user = user;
}

【问题讨论】:

  • 你看过tutorial code吗?
  • 我当然做到了,而且我已经实现了一个函数式算术计算器,其中一个“arithmeticNode”响应另一个节点发出的“executeOperation”方法的调用。当我使用字符串时,我无法翻译这种行为......不知道为什么实际上是因为如果不相同,这个概念应该非常相似

标签: java rpc thrift


【解决方案1】:

处理程序中的基本方法 impl 非常简单,应该执行以下操作(免责声明:未测试):

@Override
public Message getHello(User user) throws TException {
    Message answer = new Message();
    answer = answer.setMessage("Ciao " + user.getName() + ", welcome among us!");
    return answer;
}

如果我改用这个,那么显然没有使用 helloClient 变量,但是我当然需要它来回答方法调用

当连接到管理节点的 GreetingsNode X 对该方法进行 RPC 时,另一个已注册的 GreetingsNode 必须以消息“hello X”进行响应。

如果这意味着我们想要一个像 Client => ServerA => Server B 这样的调用序列,那么这也是可能的,只需要稍作修改。从我们上面的基本示例开始,我们相应地增强了代码:

private Message callTheOtherNode(User user) {
  // class ServiceProvider is generated by Thrift, 
  // part of ManagementService Thrift service 
  ServiceProvider provider = null; 
  List<ServiceProvider>providers = managementClient.getProvidersForService(user.name);

  if (providers.isEmpty())
      throw new NoProviderAvailableException(); //separate file contains Exception

  provider = providers.get(random.nextInt(providers.size()));
  //connection between nodes is established here
  TTransport helloTransport = new TSocket(provider.getHostName(), provider.getPort());
  TProtocol helloProtocol = new TBinaryProtocol(helloTransport);
  helloClient = new GreetingsService.Client(helloProtocol);
  helloTransport.open();
  return helloClient.getHello(user);
}

@Override
public Message getHello(User user) throws TException {
    Message answer = callTheOtherNode(user);
    return answer;
}

当然,被调用的“其他节点”需要对请求进行实际处理,而不是简单地将其再次转发到另一个节点。

【讨论】:

  • 我怀疑我过于复杂了 :( 非常感谢您,先生。
  • 两个疑问: 1) 我不确定应该将私有 CallOtherNode 方法的代码放在哪里,我猜它应该在 Handler 文件中。这样做会使 eclipse 发出警告,“GreetingsServiceHandler 类型的方法 CallOtherNode(User) 永远不会在本地使用”2) 第二个 getHello() 应该以不同的方式命名和/或也包含在我的节俭服务文件中,否则 eclipse 会一直告诉我(正确地)认为“GreetingsServiceHandler 类型的方法 sayHello(User) 必须覆盖或实现超类型方法”(因为它不包含在生成的 thrift 文件中)。
  • 是的,调用顺序是客户端(它是一个 GreetingsNode)==> 服务器 A(它是 managementNode)==> 服务器 B(它是另一个 Greetings 节点)。然后Server B与Client建立连接并接听电话。
  • "GreetingsServiceHandler 类型的方法 sayHello(User) 必须重写或实现超类型方法" -- 当然,这就是您的代码的位置,即上面的方法。也许方法签名不正确。正如我所说,未经测试。
猜你喜欢
  • 2021-10-05
  • 2016-08-10
  • 2013-05-18
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 1970-01-01
相关资源
最近更新 更多