0

In our system, we have one C++ component acting as a Thrift Server, and one .netCore/C# component as a client. So far, I was managing a single connection, so using a singleton to create my ThriftPushClientWrapper which implements TBaseClient. (via the generated object from the thrift interface)

.AddSingleton<IThriftPushClientWrapper>(sp =>
{
     var localIpAddress = IPAddress.Parse(serverIp);
     var transport = new TSocketTransport(localIpAddress, dataPort);
     var protocol = new TBinaryProtocol(transport);
     return new ThriftPushClientWrapper(protocol);
});

(so far using 0.13 version of the Thrift library, need to update to 0.14.1 soon, but wonder if the server part must be updated too/first). This is working great.

Now, I want multiple clients that can connect to the server simultaneously, all on the same ip:port So I am starting a ClientFactory, but wonder how to deal with the creation of the client. To be more precise, the server part is configured for 5 threads, so I need 5 clients.

One simple approach would be to create a new client each time, but probably inefficient.

A better approach is to have a collection of 5 clients, and using the next available free one. So I started with the following factory, where I should get the index from outside.

private readonly ConcurrentDictionary<int, IThriftPushClientWrapper> _clientDict;

public IThriftPushClientWrapper GetNextAvailablePushClient(int index)
{
    IThriftPushClientWrapper client;
    if (_clientDict.ContainsKey(index))
    {
        if (_clientDict.TryGetValue(index, out client) && client != null)
            return client;
        else  // error handling
    }

    // add new client for the expecting index
    client = CreateNewPushClient();
    _clientDict.TryAdd(index, client);
    return client;
}

private IThriftPushClientWrapper CreateNewPushClient()
{        
    var localIpAddress = IPAddress.Parse(serverIp);
    var transport = new TSocketTransport(localIpAddress, dataPort);
    var protocol = new TBinaryProtocol(transport);
    return new ThriftPushClientWrapper(protocol);
}

My next issue it to determine how to set the index from outside. I started with a SemaphoreSlim(5,5) using the semaphore.CurrentCount as index, but probably not the best idea. Also tried with a rolling index from 0 to 5. But apparently, a CancellationToken is used to cancel further procceesing. Not sure the root cause yet.

Is it possible to determine whether a TBaseClient is currently busy or available?

What is the recommended strategy to deal with a pool of clients?

EricBDev
  • 1,279
  • 13
  • 21

1 Answers1

1

The easiest solution to solve this is to do it right. If you are going to use some resource from a pool of resources, either get it off the pool, or mark it used in some suitable way for that time.

It's notable that the question has nothing to do with Thrift in particular. You are trying to solve a weak resource management approach by trying to leverage other peoples code that was never intended to work in such a context.

Regarding how to implement object pooling, this other question can provide further advice. Also keep in mind that especially on Windows platforms not all system resources can be shared freely across threads.

JensG
  • 13,148
  • 4
  • 45
  • 55
  • thanks for your comment. My question is exactly: **how to do it right?** Do we have example how to handle multi connections in parallel? – EricBDev May 10 '21 at 17:46
  • I primarily answered the question asked. More precisely, I tried to circumvent a real answer by giving better information and (now) added a suitable stackoverflow link. The real answer to the question asked is "you should not need to know". A resource becomes busy when it is taken off the pool and becomes available again when you put it back, and that's all we want to know. – JensG May 10 '21 at 23:12
  • thanks for the link, this gives me some ideas. – EricBDev May 11 '21 at 07:45
  • hanks JensG for your amazing work of bringing Thrift to .NET world! Just to be sure, can you please confirm that Thrift supports multiple connection on the same port and on the same time, having multiple "client' Transport objects? I deal here only on the client part, I also need to sync with colleagues about their server part... – EricBDev May 11 '21 at 09:47
  • Too much honour, its really teamwork. Thrift uses standard system resources, no special magic involved - sockets, http, pipes - you name it. – JensG May 11 '21 at 20:35
  • I've been working around, built a pooling system and co. But I get System.Net.Sockets.SocketException that have nothing to do with the re usable TTransport objects. When creating always a new transport object, on parallel requests, the socket behind Thrift just don't take it. until now, I was preventing that issue with a single connection and a semaphore with timeout, so that no data can be sent in parallel on the socket. As long as I allow more than 1 simultaneous use of the Thrift interface, the socket behind just refuse it. – EricBDev May 12 '21 at 08:54
  • I opened a more Thrift specific question here https://stackoverflow.com/questions/67607523/how-to-use-multiple-tsockettransport-simultaneously and will close the current one. – EricBDev May 19 '21 at 16:49