2017-02-17 11 views
0

私のプロジェクトの簡単な説明: "managementNode"がある分散環境で動作する "GreetingsNode"というJavaクラスを作成しています。他のノードの情報(ホストポート番号とサービス提供)を受信して​​格納し、登録されたサービスが提供するメソッドのRPCをディスパッチします。ノードがRPCに応答できる場合、スリフトソケットが開かれ、発呼ノードと応答ノードとの間に接続が確立され、応答ノードが結果を返す。分散環境におけるApache Thrift RPCのJavaメソッド実装

私はRPC用のIDLとフレームワークとしてApache thriftを使用しています。

今問題です。 私のGreetingsNodeHandlerクラスは、単一のメソッド "getHello(user)"(GreetingsNodeクラスのコンストラクタのパラメータである、ノードの名前を含む構造体である)を含む簡単なスリフトインタフェースを実装します。 管理ノードに接続されているGreetingsNode XがそのメソッドのRPCを作成すると、別の登録済みGreetingsNodeがメッセージ「hello X」で応答する必要があります。

結果が返されるハンドラの部分を実装する方法を正しく理解していないため、メソッドの実装が正しく機能するかどうかを確認するjunitテストの記述方法を理解できません。

のassertEquals(client.getHello(ユーザー).getMessage()、 "こんにちはジョン・ドウ")

がうまくいくのassertのような、しかし、私は私の場合、私は置くべきか、得ることはありませんクライアント部分...

GreetingService倹約サービスのためのコード:

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

[チュートリアルコード](https:// thrift)をご覧ください。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がメッセージ「hello X」で応答する必要があります。

それは我々がクライアント=>サーバーA =>サーバ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

2つの疑問:1)私はどこにプライベートCallOtherNodeメソッドのコードを置くべきかわからない、それは私が推測するHandlerファイルの中にあるだろう。そうすることで、eclipseは「GreetingsServiceHandler型のメソッドCallOtherNode(User)は決してローカルでは使用されません」という警告をスローします。2)getHello()の名前を別に指定する必要があります。私はGreetingsServiceHandlerのメソッドsayHello(User)は、生成されたthriftファイルには含まれていないため、スーパータイプメソッドをオーバーライドまたは実装する必要があります。 – Gaspare79

+0

はい、呼び出しシーケンスはクライアント(GreetingsNode)==>サーバーA(これはmanagementNode)==>サーバーB(別のGreetingsノード)です。その後、サーバーBはクライアントとの接続を確立し、呼び出しに応答します。 – Gaspare79

関連する問題