首页 > 解决方案 > 是否可以确定 Thrift TBaseClient 当前是否忙碌或可用?

问题描述

在我们的系统中,我们有一个 C++ 组件作为 Thrift 服务器,一个 .netCore/C# 组件作为客户端。到目前为止,我正在管理单个连接,因此使用单例来创建实现 TBaseClient 的 ThriftPushClientWrapper。(通过 Thrift 接口生成的对象)

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

(目前使用 0.13 版本的 Thrift 库,需要尽快更新到 0.14.1,但想知道服务器部分是否也必须更新/首先)。这很好用。

现在,我想要多个可以同时连接到服务器的客户端,都在同一个 ip:port 上所以我正在启动一个 ClientFactory,但想知道如何处理客户端的创建。更准确地说,服务器部分配置为 5 个线程,所以我需要 5 个客户端。

一种简单的方法是每次都创建一个新客户端,但可能效率低下。

更好的方法是收集 5 个客户端,并使用下一个可用的免费客户端。所以我从以下工厂开始,我应该从外部获取索引。

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);
}

我的下一个问题是确定如何从外部设置索引。我从 SemaphoreSlim(5,5) 开始,使用 semaphore.CurrentCount 作为索引,但可能不是最好的主意。还尝试使用从 0 到 5 的滚动索引。但显然,CancellationToken 用于取消进一步的处理。还不确定根本原因。

是否可以确定 TBaseClient 当前是否忙碌或可用?

处理大量客户的推荐策略是什么?

标签: .net-corethrift

解决方案


解决这个问题的最简单的解决方案是做对。如果您要使用资源池中的某些资源,请将其从池中取出,或者以某种合适的方式将其标记为当时使用。

值得注意的是,这个问题与 Thrift 无关。您试图通过尝试利用其他人的代码来解决弱资源管理方法,而这些代码从未打算在这种情况下工作。

关于如何实现对象池,this other question可以提供进一步的建议。还要记住,尤其是在 Windows 平台上,并非所有系统资源都可以跨线程自由共享。


推荐阅读