2017-02-17 30 views
0

Краткое описание моего проекта: Я пишу класс java с именем «GreetingsNode», который работает в распределенной среде, где есть «managementNode», это просто как сервисный репозиторий, а также получает и хранит информацию (номер порта хоста и предлагаемый сервис) других узлов и отправляет RPC методы, предлагаемые зарегистрированными услугами. Если узел может ответить на RPC, тогда открывается триггерный сокет и устанавливается соединение между вызывающим узлом и отвечающим узлом, а автоответчик возвращает результат.Реализация Java-метода для RPC Apache Thrift в распределенной среде

Я использую бережливость Apache в качестве IDL и рамки для RPC.

Теперь проблема. Класс My GreetingsNodeHandler реализует простой интерфейс trift, содержащий один метод «getHello (пользователь)» (пользователь является структурой, содержащей имя узла, которое является параметром конструктора класса GreetingsNode). Когда GreetingsNode X, подключенный к узлу управления, создает RPC этого метода, другой зарегистрированный GreetingsNode должен ответить сообщением «привет X».

Я не понимаю, как реализовать часть обработчика, на котором возвращен результат, и, следовательно, я не понимаю, как написать сценарий junit, который должен проверить правильность реализации метода.

как утверждают assertEquals (client.getHello (пользователь) .getMessage(), "Здравствуйте, John Doe")

будет работать, но я не понимаю, как в моем случае, я должен поставить Клиентская часть ...

код для обслуживания бережливости GreetingService:

struct Message { 
    1: string message 
} 

struct User { 
    1: string name 
} 

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

код для GreetingsServiceHandler, который должен реализовать метод GreetingsService getHello()

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; 
} 
+0

Вы просмотрели [учебный код] (https: // бережливость.apache.org/tutorial/java)? – JensG

+0

, конечно, я сделал, и я уже внедрил функциональный арифметический калькулятор, где «arithmeticNode» отвечает на вызовы метода «executeOperation», сделанные другим узлом. Я не могу перевести такое поведение, когда я использую строки ... Не знаю почему на самом деле, потому что концепция должна быть очень схожей, если не то же самое – Gaspare79

ответ

1

Основной метод осущ в обработчике довольно просто, что-то вроде следующие должны делать (отказ от ответственности: не тестировалось):

@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 должен ответить сообщением «привет X».

Если это означает, что мы хотим, чтобы последовательность вызовов, как Клиент => ServerA => Сервер 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; 
} 

Конечно «другой узел» который вызывается потребностями на самом деле сделать что-то с просьбой, вместо того, чтобы просто направить его снова еще один узел.

+0

У меня было подозрение, что я преувеличиваю :( Большое спасибо, сэр. – Gaspare79

+0

Два сомнения: 1) Я не уверен, где я должен поместить частный код метода CallOtherNode, это будет внутри файла Handler, я думаю. В результате eclipse бросает предупреждение о том, что «метод CallOtherNode (пользователь) из типа GreetingsServiceHandler никогда не используется локально» 2) второй getHello() должен быть назван по-разному и/или также включен в мой файл службы бережливости, иначе eclipse продолжает рассказывать me (правильно), что «Метод sayHello (Пользователь) типа GreetingsServiceHandler должен переопределить или реализовать метод супертипа» (потому что он не содержится в сгенерированном экономичном файле). – Gaspare79

+0

Да, последовательность вызовов будет Client (это GreetingsNode) ==> Сервер A (который является управляющимNode) ==> Сервер B (это еще один приветственный узел). Затем сервер B устанавливает соединение с клиентом и отвечает на вызов. – Gaspare79

 Смежные вопросы

  • Нет связанных вопросов^_^