如何为多个线程创建Thrift客户端?

6
我在以下代码片段中拥有一个正常运行的Thrift客户端。
TTransport transport = new THttpClient(new Uri("http://localhost:8080/api/"));
TProtocol protocol = new TBinaryProtocol(transport);
TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "UserService");
UserService.Client userServiceClient = new UserService.Client(mp);
System.out.println(userServiceClient.getUserById(100));

在多线程环境下运行客户端时,
threads[i] = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println(userServiceClient.getUserById(someId));
    }
}

我收到了一个异常:响应顺序错误
org.apache.thrift.TApplicationException: getUserById failed: out of sequence response
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:76)

我猜原因是Thrift生成的客户端不是线程安全的。 但是如果我希望多个客户端同时调用相同的方法getUserById(),该怎么做呢?


每个线程可能需要一个客户端(new THttpClient(..); ...),你能使用连接池吗?(我不了解thrift) - zapl
是的,THttpClient 有一个连接池,但它并不能解决问题。当我创建一个全新的客户端(即 userServiceClient_2,使用 mp_2、protocol_2 和 transport_2)时,它可以正常工作。但我认为这不是一个好的解决方法。 - Rocherlee
1个回答

5
Thrift客户端不适合在线程之间共享。如果需要多个客户端线程,为每个线程设置一个Thrift客户端。
但是,如果我想要多个客户端同时调用相同的getUserById()方法,该怎么办呢?
我们不太了解上下文,所以我必须猜测一下。如果问题是有很多这样的调用同时到来,可能的解决方案是将调用分组以节省往返时间:
service wtf {
  list<string>  getUsersById( 1 : list<int> userIds)
}

这只是一个简短的想法。也许你想返回list<user_data_struct>。出于实际原因,我建议将返回的列表包装到结构体中,这样整个过程变得更加可扩展。


我想创建多个线程,不仅调用相同的方法,还要同时调用多个方法。我发现我必须为每个线程创建一个新的客户端(具有新的TTransport、TProtocol和TMultiplexedProtocol)。 - Rocherlee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接